Content
# SkeletonGraph
**A zero-LLM, tree-sitter structural index that reranks cheap lexical retrieval
and fetches one function at a time — for AI coding agents.**
SkeletonGraph (SG) indexes a codebase into function-level structure, a cross-file
call graph, and PageRank centrality — **with no LLM**. At query time it resolves the
symbols an issue names, expands the call graph, and reranks a BM25 recall pool so the
agent lands the **right function** instead of burning turns reading files. Its
companion operating point, **`sg-rerank`** (the product default), takes BM25's wide
recall pool and reorders it by structural confirmation — best file *and* function
recall of any method we tested, at the lowest token cost.
The thesis: code-context tools have been validated as a **token-optimization** game
(token-count math). We re-center on **retrieval quality** — landing the correct
function — of which lower token cost is a *consequence*, visible only end-to-end
inside the agent loop.
## Results (SWE-bench Verified, nemotron-120B, 100 tasks)

| arm | pass@1 | file recall | function recall@10 | tokens (k) | $ |
|---|--:|--:|--:|--:|--:|
| **`sg-rerank`** (method) | **42.0** | **.924** | **.404** | 175 | .051 |
| **`sg`** (lean core) | 35.0 | .854 | .319 | 172 | .050 |
| `sg-chain` (graph-path) | 36.0 | .902 | .312 | **159** | **.046** |
| `cbmem` (zero-LLM graph) | 38.0 | .746 | .228 | 286 | .080 |
| `graphify` (knowledge graph) | 38.0 | — | — | 282 | .080 |
| `grep` | 39.0 | .883 | — | 286 | .081 |
| `bm25` | 38.0 | .846 | .342 | 265 | .075 |
| `none` (no retrieval) | 37.0 | — | — | 279 | .079 |
| `aider` (repo-map) | 42.0 | — | — | 1,218 | .333 |
**Findings:** (1) on this contaminated benchmark **solve rate is retrieval-insensitive** —
pass@1 spans just 35–42%, `none` (no retrieval) scores 37%, and McNemar finds **no arm
significantly better than no-retrieval** (`sg-rerank` vs `none`, p = 0.27). The same 100
tasks re-scored ~7 points lower on *every* arm — including `none` — between runs, so
pass@1 is run-noise; **tokens and function recall are the honest axes**. (2) **file recall
≠ function recall** — most arms find the file, not the function. (3) the **`sg` family is
cheapest** (159–175k tokens vs 265–286k for baselines and 1,218k for aider) while
**`sg-rerank` has the best retrieval quality of any arm** (file recall .924, function
recall .404), with **no LLM** in its index — ahead of the strong-RAG (`hybrid`, 44% in
the prior run) and deployed-graph (`aider`) baselines, not just the keyword floor.
_File/function recall are from a deterministic retrieval pass (model-independent); pass@1,
tokens and $ are from the latest agent run (v3, nemotron-120B). Scope: SWE-bench Verified
(Python). A contamination-controlled multi-language split (SWE-bench Pro, 10 languages —
file recall ~0.78 across Go/TS/JS/Python; function recall pending gold-FQN scoring) is
evaluated separately and reported as it completes._
### Deployment: SkeletonGraph vs native Claude Code (MCP, verified)
The table above is model-independent retrieval. This is the product itself —
SkeletonGraph as an MCP server driving **Claude Code (sonnet)**, against Claude Code on
its own tools (`native`). 30 paired SWE-bench Verified tasks, Docker-verified pass@1:
| arm | pass@1 | retrieval hit | turns | input tokens (k) | $/task | $/solved |
|---|--:|--:|--:|--:|--:|--:|
| `native` (Claude's own Grep/Read) | 23/30 | 24/30 | 15.6 | 731 | .486 | .634 |
| **`sg-fusion`** (SkeletonGraph MCP) | 23/30 | **29/30** | **11.8** | **506** | **.394** | **.514** |
**Same solve rate at −19% cost, −24% turns, −31% tokens** (−19% cost per solved task) —
the cost edge held steady as the sample grew (−25% at n=10, −22% at n=12, −24% at n=20,
−19% at n=30), settling in the high-teens/low-20s range rather than drifting to zero. Cost
≈ turns × accumulated context, so the win comes from cutting turns where localization is
hard — one native run that thrashed 54 turns / \$2.12 became 22 turns / \$0.90 with SG.
SG's retrieval is essentially saturated (29/30 hit); the residual gap to a higher solve
rate is fix-quality, not localization — outside what a retrieval layer can move. SG's one
weak spot: when the issue text already hands over the exact file path, any retrieval tool
is pure overhead.
**Against published competitors, on the identical 20 of these 30 tasks, run through the
NIM/nemotron react loop** (agent-loop cost only, same tool surface for every arm):
| arm | task-completion rate | retrieval hit | turns | $/task | total $ |
|---|--:|--:|--:|--:|--:|
| `cbmem` (Codebase-Memory) | 8/20 (40%) | 3/20 | 26.2 | .061 | 1.21 |
| `graphify` (knowledge-graph) | 11/20 (55%) | 8/20 | 21.7 | .071 | 1.41 |
| **`sg-fusion`** | **19/20 (95%)** | **15/20** | **18.0** | **.050** | **1.00** |
SG wins every column — highest completion rate, best retrieval, fewest turns, *and*
lowest cost (not a quality/cost tradeoff — strictly better and cheaper). graphify's figure
above is agent-loop cost only; it also pays a one-time LLM graph-extraction cost per repo
that isn't in this table, so its true total cost is higher still. _n=30 Claude Code,
n=20 NIM-react; sonnet + nemotron; multi-model runs planned._
**A note on competitors _as MCP servers inside Claude Code_ (vs. the react loop above).**
We also wired Codebase-Memory (cbmem, official v0.7.0) as a real MCP server driving Claude
Code head-to-head. It connected cleanly and all 14 of its tools were registered and visible
to the agent — but across 10 tasks **Claude never once invoked a cbmem tool, defaulting to
its native `grep` every time** (verified from the session transcripts). So an unsteered
competitor MCP server, however good its retrieval, provides no benefit if the agent doesn't
reach for it. SG's edge is not only retrieval quality but the adoption mechanism (a
PreToolUse gate that routes the agent to structural search first) that makes it actually get
used. We therefore do not report a cbmem-in-Claude-Code retrieval number — it would measure
non-adoption, not the tool. _Broader competitor set (Serena, claude-context, CodeGraph) and
a forced-tool comparison are planned._
SkeletonGraph is wrapper-first: it returns a full context packet or exposes a
retrieval index (AST skeletons + call graph + local summaries + optional embeddings)
so the IDE agent or CLI can choose targets.
SkeletonGraph has two product surfaces:
- **SG IDE**: MCP context server for Cursor, Claude Code, Copilot, Codex,
Antigravity, Windsurf, and other agentic IDEs.
- **SG CLI**: terminal pipeline for route, prepare, dry-run, provider execution,
and cost-aware model selection.
## Why SkeletonGraph
Most coding agents spend expensive turns discovering the repo:
```text
search -> read file -> read neighbor -> read tests -> realize the target
```
SkeletonGraph moves that work into a deterministic graph pipeline:
```text
prompt -> (optional) retrieval planner -> classify task -> find target nodes -> expand graph -> assemble packet
```
The goal is not only lower token cost. The useful product outcomes are:
- fewer exploratory file reads
- faster first useful answer
- better target/test/blast-radius context
- transparent routing reasons
- lower model overkill for routine tasks
- reusable packets for IDEs, CLIs, and other agents
## Install
```bash
pip install skeletongraph
```
For provider-backed CLI execution:
```bash
pip install "skeletongraph[llm]"
```
## Quick Start: SG IDE
Use this path when you already work inside Cursor, Claude Code, Copilot, Codex,
Antigravity, or another MCP-capable coding environment.
```bash
cd your-project
sg init
sg build
sg doctor
```
`sg init` writes the MCP config and the agent instruction file for the selected
IDE. SG IDE does not require an API key. Your IDE subscription/model still does
the reasoning and editing; SkeletonGraph supplies the packet or retrieval
signals for efficient target selection.
Supported IDE setup targets include:
| IDE | Integration | Model switching |
| --- | --- | --- |
| Cursor | MCP + rules | manual in IDE |
| Claude Code | MCP + `CLAUDE.md` | `/model` command |
| GitHub Copilot | MCP + instructions | manual in IDE |
| Codex | MCP + `AGENTS.md` | manual in agent |
| Antigravity | MCP + rules | manual in IDE |
| Windsurf | MCP + rules | manual in IDE |
## Quick Start: SG CLI
Use this path when you want a terminal-first context and model-routing pipeline.
```bash
cd your-project
sg build
sg route "fix the auth token validation bug"
sg prepare "fix the auth token validation bug" --out .skeletongraph/context.md
sg run "fix the auth token validation bug" --dry-run
```
`sg route`, `sg prepare`, and `sg run --dry-run` do not need an API key.
To call a provider:
```bash
sg config --cli-provider anthropic
$env:ANTHROPIC_API_KEY = "..."
sg run "fix the auth token validation bug" --execute
```
To test locally without a paid provider key:
```bash
ollama pull qwen3-coder:latest
ollama serve
sg config --cli-provider local
sg run "fix the auth token validation bug" --dry-run
sg run "fix the auth token validation bug" --execute
```
Local execution is intended for cheap pipeline testing. Use provider models for
quality benchmarks unless the benchmark is specifically for local models.
## Model Routing
SkeletonGraph separates IDE-facing model labels from CLI provider model names.
For IDEs, model tiers are recommendations:
| Tier | Typical use |
| --- | --- |
| SLM | docs, explanations, simple lookup |
| MLM | normal coding, debugging, tests, review |
| LLM | architecture, broad migrations, low-confidence tasks |
For CLI execution, SkeletonGraph can route to provider model names:
```bash
sg config --cli-provider anthropic
sg config --cli-provider openai
sg config --cli-provider google
sg config --cli-provider local
```
Dynamic routing uses task mode, confidence, candidate count, token size, and
complexity. Code-changing work keeps an MLM floor by default so cost savings do
not come from making weak models edit code unsafely. Retrieval planning can use
small models to propose targets over AST/summaries before the heavy model runs.
## IDE Integration
After `sg init` and `sg build`, register SG as an MCP server and write IDE hooks:
```bash
sg install --ide claude-code # Claude Code: hooks + MCP server + CLAUDE.md rules
sg install --ide cursor # Cursor: MCP + .cursor/rules/skeletongraph.mdc + hooks
sg install --ide cline # Cline / Roo: MCP config + rules block
sg install --ide copilot # GitHub Copilot: MCP + copilot-instructions.md
sg install --ide windsurf # Windsurf: MCP + .windsurfrules
sg install # auto-detect all installed IDEs
```
After install, restart your editor. SkeletonGraph runs as a background MCP server
(`sg serve --path .`) that the IDE connects to automatically.
## MCP Tools
Six tools are exposed to the IDE agent. Use these **instead of** grep/glob/file reads:
| Tool | When to call | Returns |
| --- | --- | --- |
| `sg_overview` | Session start — once per session | Constraints + top-N functions (by PageRank) + recent turns + index stats |
| `sg_search "query"` | **Primary retrieval** — almost every prompt | Top-3 matches with body excerpts + summaries + 1-hop callers; top-4..N as signatures + summaries. One call usually enough — no need to chain. |
| `sg_get "fqn"` | When the exact FQN is known | Signature + summary + 1-hop callers + callees |
| `sg_expand "target"` | When more body is needed than `sg_search` returned | Full function body / file / line range (token-capped) |
| `sg_constraint list` / `propose` | Before proposing changes | Confirmed + proposed project rules |
| `sg_log` | Reviewing recent session turns | Last-N turn summaries with files touched |
**Smart context routing.** On each `UserPromptSubmit`, SG classifies the prompt
(architecture / explain / decision / debug / test / review / general) and
includes the matching MD file from `.skeletongraph/` — e.g. `architecture.md`
only for design/refactor queries, `project.md` only for "what is this codebase"
queries. Constraints + session digest + relevant functions are always injected.
**Cold start.** If no `.skeletongraph/` index exists when an MCP tool is called,
SG auto-builds on first invocation (see `auto_build_on_query` in config).
## CLI Reference
**Indexing & status**
| Command | Purpose |
| --- | --- |
| `sg init [--agent cursor]` | Configure project, IDE preset, MCP, constraints |
| `sg index` | Full index (alias for `sg build`) |
| `sg index --incremental` | Only re-index changed files |
| `sg build` | Full index with detailed output |
| `sg update` | Incremental update |
| `sg status` | Show index status |
| `sg doctor` | Check index, routing, provider, Ollama readiness |
| `sg overview` | Project skeleton: top functions, constraints, session |
| `sg install [--ide <name>]` | Write IDE hooks + MCP config |
**Retrieval**
| Command | Purpose |
| --- | --- |
| `sg search "query"` | BM25 + graph search (no API key) |
| `sg get "fqn"` | Get function signature, summary, callers |
| `sg expand "target"` | Expand function body / file / line range |
**Constraints & session**
| Command | Purpose |
| --- | --- |
| `sg constraint list` | List all constraints |
| `sg constraint propose "text"` | Add a proposal |
| `sg constraint confirm <id>` | Promote proposal → decisions.md |
| `sg constraint remove <id>` | Remove a constraint |
| `sg constraint aggregate` | Import from IDE rule files |
| `sg log [--last-n 10]` | Show recent session turns |
**Summarization**
| Command | Purpose | API key |
| --- | --- | --- |
| `sg summarize --tier local` | Ollama Tier-0.5 (free, on-device) | no |
| `sg summarize --tier cloud` | Cloud LLM Tier-1 | provider key |
| `sg summarize --tier cloud --force` | Re-summarize all functions | provider key |
**Model routing & execution**
| Command | Purpose | API key |
| --- | --- | --- |
| `sg route "task"` | Show task mode, tier, recommended model | no |
| `sg run "task" --dry-run` | Plan routed execution | no |
| `sg run "task" --execute` | Call configured provider | provider or local |
| `sg config [--agent cursor]` | Configure IDE and CLI models | no |
| `sg config --cli-provider anthropic` | Set CLI execution provider | no |
**Background indexing**
| Command | Purpose |
| --- | --- |
| `sg watch` | Daemon: auto-reindex files on save |
Provider output from `sg run --execute` is written to `.skeletongraph/runs/`.
Evaluation is currently done externally via SWE-bench harness — see `docs/swe_bench_runbook.md`.
## Python API
```python
from skeletongraph.engine import SGEngine
engine = SGEngine(project_root=".")
result = engine.query("fix the content-length bug", delivery="cli")
print(result.context_text)
print(result.query_mode)
print(result.model_tier)
print(result.recommended_model)
print(result.routing_reason)
```
## Architecture
```text
src/skeletongraph/
parser/ AST extraction
graph/ dependency graph and ranking
storage/ .skeletongraph persistence
retrieval/ classification, resolution, model routing
assembly/ context packet construction
session/ memory and dedup
server/ MCP server
llm/ LiteLLM wrapper for optional CLI execution
cli/ Click commands
engine.py unified query pipeline
```
## Evaluation
The architecture/pipeline blueprint and evaluation plan are in:
```text
docs/blueprint.md
docs/evaluation.md
```
SkeletonGraph should be evaluated on both quality and cost:
- target recall and packet completeness
- missed tests/callers
- first useful answer latency
- file reads after SG context
- pass rate
- cost per passing task
- dynamic routing overkill/underpower rate
- IDE compliance with SG-first context usage
Cost savings are only meaningful when reported with pass rate.
## Install
```bash
pip install skeletongraph # core: indexing, MCP server, CLI (no API key needed)
pip install "skeletongraph[llm]" # + litellm for sg run --execute / sg summarize --tier cloud
pip install "skeletongraph[all]" # everything
```
## License
MIT
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.