Why
Where the tokens go
An agent that wants one signature usually reads the whole file to get it. A 2,500-line file costs about 26,000 tokens. Over a ten-turn session that adds up to more than the context window holds, so the harness compacts the conversation and the agent forgets the rules it was given.
Read the file
cat crates/code-kb-core/src/queries.rs
- Lines
- 2,473
- Tokens
- ≈ 25,900
- Needed
- one signature
Ask code-kb
file_skeleton("queries.rs")
get_symbol_context("search_symbols_scoped")
- Skeleton
- ≈ 1,800 tokens, 93% less
- Context slice
- ≈ 780 tokens, 97% less
- Query time
- 2 ms
What it does
Seven capabilities for AI coding agents
- Skeletons
file_skeletonreturns every type, trait, signature, and docstring in a file with the bodies removed.codebase_outlinedoes the same for a directory in about 200 tokens.- Context slices
get_symbol_contextreturns one function's body, the signatures of the functions it calls, its parameter types, and its tests. One call replaces four to six searches.- Blast radius
blast_radiuswalks the callers of a symbol across several hops with a recursive SQLite query and names the tests to run. With no target, it reads the uncommitted git changes.- Atomic edits
replace_symbol_bodyvalidates the edited file throughjulie-extract checkfor every language the extractor parses, about 40; other paths report validation skipped. It then verifies a hash, writes the file, and re-indexes it in one turn.- Token telemetry
telemetry_summarytracks tokens saved, call counts, and error rates across sessions in a central SQLite database.code-kb statsprints the report from the terminal.- Windows first
- Every release ships a Windows binary tested on NTFS. Paths use forward slashes, verbatim prefixes are stripped, and file handles close before any rename.
- Native hooks
code-kb hook SessionStartprints routing instructions for the agent from the binary itself. No Node.js, Python, or shell in the path.
Compared
code-kb against a bare agent
| Task | With code-kb | With grep, cat, and read |
|---|---|---|
| Prompt tokens per lookup | 85–98% fewer | 5,000–15,000 per file read |
| Find a signature | file_skeleton, bodies removed |
Whole file in the prompt |
| Search by concept | BM25 full-text search in under 3 ms | Text grep that also matches comments, strings, and logs |
| Prepare an edit | get_symbol_context, one call |
Four to six searches across turns |
| Callee noise | Standard library calls filtered in 40+ languages | Every runtime call listed |
| Predict which tests to run | blast_radius, recursive SQL |
Guess, or run the whole suite |
| Replace a function | Syntax checked before the write by julie-extract for about 40 languages; skipped otherwise |
Text or regex replacement |
| Query time | 0–5 ms median | 10–50 ms of disk reads, then the model reads it all |
| Memory held by the server | Under 15 MB | None, paid for in prompt size instead |
| Context left for the task | Instructions survive the session | Compaction, forgotten constraints |
Steps
From a cold start to a verified edit
The order an agent follows on a repository it has never seen. Each step costs less than the file read it replaces.
-
Orient
Directory tree and the main exports, about 200 tokens.
codebase_outline(depth=2)
-
Find the interface
Signatures and traits with bodies removed. Search by concept when the name is unknown.
file_skeleton("src/server.rs") search_symbols("auth token validation") -
Get the context
The target body, its callees' signatures, parameter types, and tests in one call.
get_symbol_context("handle_request") -
Check the impact
Callers across several hops and the tests that cover them.
blast_radius(symbol="compute_hash")
-
Edit
Syntax validation by
julie-extractfor about 40 languages; other paths report it skipped. Hash check, atomic write, re-index.replace_symbol_body( symbol_name="calculate", file_path="calc.rs", new_body="{ a + b }" ) -
Verify
Run the predicted tests, then read the tool telemetry.
cargo test compute_hash code-kb stats
Tools
Eleven tools, each with a matching command
Every MCP tool has a one-to-one CLI command, so you can check any answer from the terminal.
| MCP tool | CLI command | Returns | Accepts |
|---|---|---|---|
codebase_outline | code-kb outline [path] | Directory tree and main symbols | path, depth |
file_skeleton | code-kb skeleton <file> | File outline, bodies removed | file_path |
lookup_symbol | code-kb lookup <query> | Exact or prefix symbol match | query, path |
search_symbols | code-kb search <query> | Full-text search over docstrings and signatures | query, path |
get_symbol_body | code-kb body <symbol> | Source of one symbol | symbol_name, file_path |
get_symbol_context | code-kb context <symbol> | Body, callee signatures, types, tests | symbol_name, file_path |
find_references | code-kb refs <symbol> | Callers or callees, stdlib filtered | symbol_name, direction (default callers) |
blast_radius | code-kb blast-radius [target] | Multi-hop callers and tests to run | symbol, file; omitted target reads git changes |
find_structural_facts | code-kb facts [category] | Routes, queries, models, config keys | no category lists all |
replace_symbol_body | code-kb edit <symbol> | Atomic replacement; syntax validation for supported languages | symbol_name, file_path, new_body, expected_body_hash |
telemetry_summary | code-kb stats | Token savings, call counts, error rates | time_window, workspace_only |
Install
Connect it to your agent
Install the plugin for your agent. It needs Node.js 18 or newer; on first run it downloads the release archive for your platform, which holds code-kb and the matching julie-extract side by side. Or download the archive yourself, put both binaries on PATH, and register the server by hand. GUI apps such as Cursor start the server from their own install directory, so their config passes --root with the project path; terminal agents need no flag. The README has every harness.
As a plugin, which also installs the skill and hooks (two separate prompts):
/plugin marketplace add anortham/code-kb
/plugin install code-kb@code-kb
Or by hand, for every project on this machine:
claude mcp add --scope user code-kb -- code-kb serve
For one project, in .mcp.json:
{
"mcpServers": {
"code-kb": {
"command": "code-kb",
"args": ["serve"]
}
}
}
As a plugin, which also installs the skill and hooks:
grok plugin install anortham/code-kb --trust
# or from a local checkout:
grok plugin install /path/to/code-kb --trust
For one project, in .mcp.json:
{
"mcpServers": {
"code-kb": {
"command": "code-kb",
"args": ["serve"]
}
}
}
As a plugin, which also installs the skill and hook:
agy plugin install https://github.com/anortham/code-kb
Or by hand, from the command line:
agy mcp add code-kb code-kb serve
Or in ~/.gemini/config/mcp_config.json with eager tools. The AGY CLI starts the server in the project directory; the Antigravity IDE does not, so add --root for the IDE:
{
"mcpServers": {
"code-kb": {
"command": "code-kb",
"args": ["serve", "--root", "/absolute/path/to/project"],
"disabled": false,
"eager": true,
"force_all_tools_eager": true
}
}
}
In ~/.gemini/config/hooks.json (Antigravity uses PreInvocation):
{
"code-kb": {
"PreInvocation": [
{
"command": "code-kb hook PreInvocation",
"timeout": 10,
"type": "command"
}
]
}
}
Link the skill so the agent knows when to use each tool:
ln -sf /path/to/code-kb/skills/code-kb ~/.gemini/config/skills/code-kb
As a plugin, which also installs the skill and hooks:
codex plugin marketplace add anortham/code-kb
codex plugin add code-kb@code-kb
Or by hand, in ~/.codex/config.toml:
[mcp_servers.code-kb]
command = "code-kb"
args = ["serve"]
In .cursor/mcp.json at the repository root. Cursor and other GUI apps start the server from their install directory, so --root names the project:
{
"mcpServers": {
"code-kb": {
"command": "code-kb",
"args": ["serve", "--root", "/absolute/path/to/project"]
}
}
}
code-kb hook prints the routing instructions the agent reads at session start. No Node.js or shell needed. Supports SessionStart, SubagentStart, and PreInvocation (Antigravity).
code-kb hook SessionStart
code-kb hook SubagentStart
code-kb hook PreInvocation
# hooks/claude-codex-hooks.json wires both:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [{ "type": "command", "command": "code-kb hook SessionStart" }]
}
],
"SubagentStart": [
{
"hooks": [{ "type": "command", "command": "code-kb hook SubagentStart" }]
}
]
}
}