Code intelligence for 15+ languages: semantic graph queries instead of file reads. 37 MCP tools.
io.github.aovestdipaperino/tokensave MCP Server
This MCP server provides code intelligence for 15+ programming languages using semantic graph queries instead of file reads. It exposes 37 MCP tools, as indicated by the repository description. The included excerpt frames the approach as targeting fewer tokens and fewer tool calls, with processing noted as local.
π οΈ Key Features
Semantic graph queries rather than file reads
Code intelligence support for 15+ languages
37 MCP tools
π Use Cases
Querying code context across multiple languages
Reducing reliance on direct file reads during agent-assisted coding
β‘ Developer Benefits
Semantic graph-based access to code information
Potentially fewer tokens and tool calls, with β100% localβ noted in the excerpt
β οΈ Limitations
Specific tool names, query scope, and supported graph operations are not detailed in the provided excerpt
AI coding agents waste tokens exploring codebases. Every grep, glob, and file read costs money. On complex tasks, agents spawn multiple Explore sub-agents that scan hundreds of files just to build context.
tokensave gives agents a pre-indexed semantic knowledge graph. Instead of scanning files, the agent queries the graph and gets instant, structured answers -- the right symbols, their relationships, and source code, in one call.
Without tokensave: Agents use grep, glob, and Read to scan files -- many API calls, high token usage.
With tokensave: Agents query the graph via MCP tools -- instant results, local processing, fewer tokens.
Key Features
Smart Context Building
Semantic Search
Impact Analysis
One tool call returns everything the agent needs -- entry points, related symbols, and code snippets.
Find code by meaning, not just text. Search for "authentication" and find login, validateToken, AuthService.
Know exactly what breaks before you change it. Trace callers, callees, and the full impact radius of any symbol.
80+ MCP Tools
50+ Languages
12+ Agent Integrations
From call graph traversal to dead code detection, atomic edit primitives, code-health metrics, test mapping, and complexity analysis.
Rust, Go, Java, Python, TypeScript, C, C++, Swift, Svelte, Astro, and 43 more including WGSL/HLSL/Metal shaders, CUDA/HIP, and Markdown. Three tiers (lite/medium/full) control binary size.
Claude Code, Codex CLI, Gemini CLI, Qwen Code, Kiro, Cursor, OpenCode, Copilot, Cline, Roo Code, Zed, Antigravity, Kilo CLI, Kimi CLI, Mistral Vibe, Grok Build, Factory Droid, OMP, Pi, Plank.
Multi-Branch Indexing (opt-in)
100% Local
Always Fresh
Optional per-branch databases. Cross-branch diff and search without switching your checkout.
No data leaves your machine. No API keys. No external services. Everything runs on a local libSQL database.
On-demand staleness check on every MCP call (30 s cooldown) plus catch-up sync when the server connects. Multi-agent work is expected to use git worktrees β each agent gets its own checkout and the index diverges are merged by git, not by a file watcher.
Subprocess-Isolated Extraction
Code-Health Analytics
Atomic Edit Primitives
A native crash in any tree-sitter grammar (abort, segfault, anything) kills only the worker; the pool respawns it and sync continues. Sync never dies on a malformed file.
Composite health score (0-10000), Gini inequality, file-DAG depth, design-structure matrix, risk-weighted test gaps, and session deltas.
Edit files without regex or shell-quoting hazards: unique-anchor str_replace, atomic multi-replace, AST-rewrite, anchored insert. Auto re-indexes after writes.
# Fast install prebuilt binary without compiling:
cargo binstall tokensave
# Or compile from source:
cargo install tokensave # full (50+ languages, default)
cargo install tokensave --features medium # medium tier
cargo install tokensave --no-default-features # lite (smallest binary)
Prebuilt binaries (Linux, Windows, macOS):
Download from the latest release and place the binary in your PATH.
Platform
Archive
macOS (Apple Silicon)
tokensave-vX.Y.Z-aarch64-macos.tar.gz
Linux (x86_64)
tokensave-vX.Y.Z-x86_64-linux.tar.gz
Linux (ARM64)
tokensave-vX.Y.Z-aarch64-linux.tar.gz
Windows (x86_64)
tokensave-vX.Y.Z-x86_64-windows.zip
2. Configure your agent
bash
tokensave install # auto-detects installed agents
tokensave install --agent antigravity # Google Antigravity (formerly Windsurf)
tokensave install --agent auggie # AugmentCode
tokensave install --agent claude # Claude Code
tokensave install --agent cline # Cline
tokensave install --agent codex # OpenAI Codex CLI
tokensave install --agent copilot # GitHub Copilot
tokensave install --agent cursor # Cursor
tokensave install --agent droid # Factory Droid
tokensave install --agent gemini # Gemini CLI
tokensave install --agent kilo # Kilo CLI
tokensave install --agent kiro # AWS Kiro
tokensave install --agent kimi # Moonshot Kimi CLI
tokensave install --agent omp # Oh My Pi (OMP)
tokensave install --agent opencode # OpenCode
tokensave install --agent pi # Pi (pi.dev)
tokensave install --agent plank # Plank (macOS only)
tokensave install --agent qwen # Qwen Code
tokensave install --agent roo-code # Roo Code
tokensave install --agent vibe # Mistral Vibe
tokensave install --agent zed # Zed
tokensave install --agent grok # Grok Build (xAI)
tokensave install --git-hook yes# auto-install the global post-commit and post-checkout hooks (no prompt)
tokensave install --git-hook no # skip the post-commit and post-checkout hooks (no prompt)
tokensave githooks # show which global git hooks tokensave owns
tokensave githooks off # remove them, leaving any hook content you wrote
Each agent gets its MCP server registered in the native config format. Claude Code additionally gets a PreToolUse hook (blocks wasteful Explore agents), a UserPromptSubmit hook, a Stop hook, prompt rules in CLAUDE.md, and auto-allowed tool permissions. Kiro gets global MCP config, tokensave.md steering loaded as a resource, and a tokensave-managed default agent with permissive built-in/tokensave tool approval, delegation guardrail hooks, and post-write sync; user-managed Kiro agents are preserved.
Global OMP installs target the profile reported by bare omp config path, writing <resolved-agent-dir>/mcp.json and <resolved-agent-dir>/rules/tokensave.md. Export OMP_PROFILE or OMP's compatible PI_PROFILE when installing into a named profile; OMP's resolver also honors PI_CONFIG_DIR and PI_CODING_AGENT_DIR. Tokensave trusts that native resolver rather than duplicating OMP's profile logic. Tokensave installs MCP and advisory rules for OMP; it does not install OMP hook enforcement.
All changes are idempotent -- safe to run again after upgrading. After agent setup, you'll be offered global git post-commit and post-checkout hooks. tokensave uninstall removes those hooks along with the agent integrations; pass --keep-git-hooks to leave them, or manage them on their own with tokensave githooks.
Project-local install
By default tokensave install registers the MCP server in your global agent config (e.g. ~/.claude.json). To register tokensave for just the current project instead, add --local:
bash
tokensave install --local --agent claude
tokensave install --local --agent omp
This writes project-scoped config you can commit and share with your team. For Claude that's ./.mcp.json, ./.claude/settings.json, and ./CLAUDE.md; OMP uses ./.omp/mcp.json and ./.omp/rules/tokensave.md without invoking the OMP CLI. Supported agents: claude, cursor, droid, gemini, zed, opencode, roo-code, kiro, auggie, omp, plank (each writes its own project file, e.g. .cursor/mcp.json, .factory/mcp.json, .gemini/settings.json, .zed/settings.json, opencode.json, .roo/mcp.json, .kiro/settings/mcp.json, .augment/settings.json, .omp/mcp.json, .mcp.json for plank). Other agents have no project-scoped config and report an error with --local.
Remove a project-local install with tokensave uninstall --local.
3. Index your project
bash
cd /path/to/your/project
tokensave init
This creates a .tokensave/ directory with the knowledge graph database. Initialization and sync are separate commands: init is a one-time opt-in per project, while sync only updates projects that were already initialized. This prevents the global git hooks from silently creating databases in repos you never intended to index. After init, use tokensave sync to incrementally update -- only changed files are re-indexed.
The hook runs tokensave hook-pre-tool-use -- a native Rust command (no bash or jq required). It intercepts Agent, Grep, Glob, and Bash tool calls: Explore agents are blocked outright, symbol-shaped grep/rg/ag invocations (plain identifiers, alternations, \b-wrapped names) are redirected to the matching tokensave MCP tool, and path-shaped discovery (Glob, find -name, fd --extension) over code extensions is redirected to tokensave_files. Regex patterns, git grep, piped commands, non-code extensions, search roots outside the index, and find predicates that change what the command does (-exec, -delete, -mtime) all pass through untouched; set TOKENSAVE_DISABLE_GREP_HOOK=1 to opt out per shell.
Filters are read most-specific-first: an explicit type is authoritative, then an explicit file glob, then the search path. A documentation search such as path: "." with glob: "**/*.md" therefore passes through rather than being treated as a code search on the broad path, while a code-only glob (**/*.rs) still redirects even under a non-code path. Mixed globs (**/*.{rs,md}) pass through, since they can return documentation.
Headless / subagent dispatch (claude -p). Child processes dispatched by an orchestrating session inherit its ~/.claude/settings.json, including this hook. To let a child run raw searches, set TOKENSAVE_DISABLE_GREP_HOOK=1 in the child's environment -- the native binary honors it and passes every path (Grep, Glob, Bash, Agent) through, so there is no need for the blunt --settings '{"hooks": {}}' that strips all hooks. The guardrail is stateless: it never consults citation history, so it only ever redirects the symbol-shaped searches described above and steers untyped research fan-out; ordinary commands are unaffected whether the session is interactive or headless.
CLAUDE.md rules
Appends instructions to ~/.claude/CLAUDE.md that tell Claude to use tokensave tools before reaching for Explore agents or raw file reads.
Crash-Resilient Sync
Tree-sitter grammars are compiled C/C++ code. They occasionally hit an internal assertion or otherwise terminate the process by paths that Rust panic handling cannot intercept. As of v4.3.0, every file is parsed inside a short-lived worker subprocess: if a grammar segfaults, calls abort(), or hits a stack overflow, only the worker dies. The pool respawns it, the offending file is logged and skipped, and sync keeps going.
The worker is a hidden extract-worker subcommand authenticated against the parent via a 256-bit per-spawn token, required as both a TOKENSAVE_WORKER_TOKEN env var and as the first 32 bytes received on stdin. Direct invocation by users fails. Defaults to available_parallelism() workers; opt out with TOKENSAVE_DISABLE_SUBPROCESS=1.
Edit primitives (tokensave_str_replace, tokensave_insert_at, etc.) still run in-process: they target one file at a time where subprocess overhead would dominate, and an extractor crash there is immediately visible to the agent.
Multi-Branch Indexing (Optional)
tokensave can optionally maintain a separate code graph per git branch. When enabled, switching branches never gives you stale results and never re-indexes files you already parsed on another branch. Multi-branch tracking is opt-in -- without it, tokensave uses a single database for all branches.
How it works
When you track a branch, tokensave copies the nearest ancestor DB and syncs only the files that differ. This means tracking a feature branch off main is nearly instant -- it only parses the files you've changed.
CLI commands
bash
tokensave branch add # track the current branch
tokensave branch list # see tracked branches and DB sizes
tokensave branch remove <name> # stop tracking a branch
tokensave branch removeall # remove all tracked branches except default
tokensave branch gc # clean up branches deleted from git
Cross-branch MCP tools
Three MCP tools enable cross-branch queries without switching your checkout:
tokensave_branch_search -- search symbols in another branch's graph
tokensave_branch_diff -- compare code graphs between two branches: symbols added, removed, and changed (signature differs). Supports file and kind filters.
tokensave_branch_list -- list tracked branches with DB sizes, parent branch, and sync times
Branch fallback
When the MCP server can't find a database for the current branch, it serves from the nearest ancestor branch's DB and includes a warning in every tool response suggesting you run tokensave branch add.
Automatic branch tracking (v7.3.0)
Once multi-branch mode is bootstrapped (a first manual tokensave branch add created the branch metadata), new branches can be tracked automatically instead of falling back to the ancestor DB. Two independent mechanisms cover this; projects in single-DB mode are never affected, and neither mechanism ever touches the default branch's database.
Git hook (on branch checkout). The post-checkout hook that tokensave install sets up recognizes a branch checkout (as opposed to a file checkout) and runs tokensave branch add in the background. That command is a no-op when the branch is already tracked or is the default branch, so ordinary switching between known branches costs nothing. The initial checkout of a fresh git clone and of a new git worktree add is a branch checkout too, and it can land on a branch that is not the default one (git clone -b feature, git worktree add -b feature); there the hook runs tokensave init first and tokensave branch add after it, in that order. A hook written by an earlier version keeps the body it was installed with β the installer never rewrites an existing one β so on those installs a fresh worktree still needs auto_track below, or a manual tokensave branch add.
Open-time auto-track (opt-in). When TokenSave::open runs β CLI command or MCP server start β and the active branch is untracked, tokensave can track it on the spot by copying the nearest tracked ancestor's DB and recording it in the branch metadata. This is gated by the auto_track config field (default false) or the TOKENSAVE_AUTO_TRACK environment variable, which overrides the config per-run (any value enables it except 0, false, no, off, or empty). The copy is the same near-instant ancestor-DB copy a manual branch add performs; no sync runs at that moment β the post-commit hook keeps the new branch DB fresh as you commit, or run tokensave sync to refresh immediately. Auto-tracking is strictly best-effort: any failure is reported as a warning and open() proceeds with the usual ancestor fallback, so it can never break a tool call.
In short: with the hook installed, checking out a new feature branch β including the branch a fresh clone or worktree starts on β transparently gives it its own per-branch graph; with auto_track enabled, even a branch created outside a checkout is picked up the first time tokensave opens the project on it.
Measured against this repo (tokensave itself) using the shipped generic query set:
#
Query
Baseline
Context
Savings
Files
Nodes
1
How is configuration loaded at startup?
45.3k
454
99%
4
5
2
Where are command-line arguments parsed and dispatched?
948
402
58%
3
3
3
How is the main entry point organized?
6.1k
251
96%
3
8
4
How are errors defined, wrapped, and propagated?
3.5k
819
77%
2
3
5
Where is logging or diagnostic output emitted?
8.6k
514
94%
6
14
6
How are tests organized and what test harness is used?
3.5k
818
77%
2
3
7
How is data persisted to disk or to a database?
11.9k
330
97%
3
6
8
How are async tasks or background work spawned?
29.4k
364
99%
2
3
9
How does the build wire up dependencies and initialize state?
10.9k
1.4k
88%
4
5
10
How are public API surfaces exposed (HTTP endpoints, library exports, or CLI commands)?
22.5k
235
99%
4
5
Aggregate: 88% mean retrieval savings (142.8k β 5.5k tokens across 10 queries).
The default query set targets patterns present in most application codebases (CLIs, daemons, services). Run it on your own project with tokensave bench to see your numbers, or write a tailored query file (--queries my.toml) for tighter recall.
Criterion bench against large real-world repos
benches/large_repos.rs is a criterion micro-benchmark that exercises the MCP tools end-to-end against four large open-source codebases pinned at constant refs. Each tool is driven by at least 5 queries with arguments (node ids, qualified names, file globs, β¦) sampled from the indexed graph once per repo, so timings are reproducible across runs.
Repos and pinned refs (defined in benches/repos.rs):
Each repo is shallow-cloned (git init + git fetch --progress --depth 1 origin <ref> + checkout FETCH_HEAD) on first use and cached locally; subsequent runs reuse the checkout. Git output is streamed to the terminal so the multi-GB fetch shows real-time progress.
Force-sync on every run. Before any benchmark fires, the harness runs the equivalent of tokensave sync --force on each repo (index_all() regardless of .tokensave/ freshness) so timings always reflect the pinned source.
Write benches and cleanup. Write tools mutate files. To keep the "match must be unique" precondition holding, the harness uses criterion's iter_batched β a small scratch file under <repo>/.tokensave-bench-scratch/ is rewritten with known content before every timed iteration, then the edit tool runs against it. After all benchmarks finish, the harness runs git stash --include-untracked && git stash drop inside every prepared repo so the working tree returns to the pinned ref.
Criterion configuration. The bench overrides criterion's defaults to sample_size = 10 and measurement_time = 30s (vs the stock 100 / 5s), which gives each per-query timing ~30 seconds of measurement β enough that slow tools like tokensave_context on polkadot-sdk produce stable numbers.
Run it:
bash
# Required: a writable cache directory for the cloned repos + their indexes.
<p align="center">
<a href="https://ai.enzolombardi.net/"><img src="https://img.shields.io/badge/built%20with-AI-D97757?style=flat-square&labelColor=101010&logo=anthropic&logoColor=white" alt="Built with AI β part of Enzo Lombardi's AI portfolio"></a>
</p>
# Expect several GB of disk and a long first run (shallow clone + full index of each repo).export TOKENSAVE_BENCH_REPOS_DIR=~/tokensave-bench-cache
cargo bench --bench large_repos
If TOKENSAVE_BENCH_REPOS_DIR is unset the bench prints a notice and registers zero benchmarks (so cargo bench --all stays cheap on contributors' machines).
Configuration (all optional, via environment):
Variable
Effect
TOKENSAVE_BENCH_REPOS_DIR
Required. Root directory where each repo is cloned to $DIR/<repo-name>/.
TOKENSAVE_BENCH_REPOS
Comma-separated subset of repo names to bench, e.g. TOKENSAVE_BENCH_REPOS=emacs,scipy. Defaults to all four.
TOKENSAVE_BENCH_SKIP_CLONE
If set, the bench fails fast for any repo not already at its pinned ref instead of fetching. Useful in CI / offline runs.
Filtering benchmarks uses the standard criterion CLI β for example, only the search tool on scipy:
Reports (HTML + raw samples) land under target/criterion/.
To change the pinned refs (e.g. to a newer release or a specific SHA), edit REPOS in benches/repos.rs and delete the corresponding $TOKENSAVE_BENCH_REPOS_DIR/<repo>/.bench-ref marker so the next run re-fetches. If you skip the post-run cleanup (e.g. you Ctrl-C mid-bench), running git stash --include-untracked && git stash drop inside each repo dir restores it manually.
MCP test-matrix probe (scripts/mcp_probe)
scripts/mcp_probe/ is a Python harness that drives tokensave serve over stdio against a configurable set of real repos and exercises every read-only MCP tool with 5 query variants per language, producing a per-tool / per-repo status table. Same harness serves two purposes:
Perf probe. Per-call timings are logged in TSV; the same fixed corpus of repos doubles as a coarse cross-version comparison. The current tokensave_inheritance_depth cycle bug was found by this harness when a single tool on polkadot-sdk timed out at >60 s.
Layout β probe.py is the driver (id-matched JSON-RPC so a slow tool can't poison subsequent calls), isolated.py re-runs a single tool with a fresh server per call (escapes server queueing), build_matrix.py reads the TSV and emits markdown, tools/<lang>.py modules contribute per-language query sets (Rust shipped; add Python/Go/β¦ by dropping a new module), repos.toml lists target repos (override via $TOKENSAVE_PROBE_REPOS).
Different from the criterion bench above: criterion measures per-iteration latency for a focused tool set on pinned refs and produces statistical reports under target/criterion/; mcp_probe exercises every tool with a broader query set on whatever repos you point it at, optimising for breadth of coverage rather than measurement precision.
80+ MCP Tools
The server exposes more than 80 tools (one fewer when the optional ast-grep binary is not on PATH); the tables below group the most commonly used ones by category. Most are read-only, safe to call in parallel, and annotated with readOnlyHint. The edit primitives are scoped to single files and re-index in place; session baseline and memory-recording tools also mutate local .tokensave state and are annotated as non-read-only. The three core tools (tokensave_context, tokensave_search, tokensave_status) are marked anthropic/alwaysLoad so they bypass the client's tool-search round-trip.
Query another initialized project
Semantic read tools can query an explicitly selected local graph without
restarting the MCP server:
Selected results include canonical root/branch provenance. Node IDs are
namespaced to that graph, and the matching selectors must be repeated on
follow-up calls. For example, a follow-up to a branch-selected query includes
both values:
graph_root must be the exact absolute root of an already initialized project.
graph_branch is optional and, when supplied, must name a tracked branch.
Selected opens are read-only: they never initialize, sync, migrate, auto-track,
or write graph/source data. They also do not contribute to savings accounting.
Calls without selectors behave exactly as before.
graph_root is only useful if you know the other project exists, so the server
tells you: initialized projects sitting directly beside the served root are
named in the MCP instructions, in tokensave_status, and in empty
tokensave_search / tokensave_context results β the point at which a session
would otherwise conclude a symbol does not exist rather than look next door
(#375). Only immediate siblings are offered, at most five, and nothing is opened
or indexed on their behalf; querying one still requires an explicit graph_root.
Selectors are intentionally unavailable on tools that write, shell out, or
depend on the current checkout: the edit primitives, VCS and branch tools,
diagnostics and test execution, dependency and runtime introspection, workflow
and session-memory tools, the persistent-cache tool (tokensave_redundancy),
and server administration. Those tools reject a selector instead of silently
ignoring it.
Discovery
Tool
Purpose
tokensave_context
Get relevant code context for a task -- entry points, related symbols, code snippets
tokensave_search
Find symbols by name (functions, classes, types)
tokensave_node
Get details + source code for a specific symbol
tokensave_files
List indexed project files (source and tracked artifacts) with filtering
tokensave_module_api
Public API surface of a file or directory
tokensave_similar
Find symbols with similar names
tokensave_annotations
Attribute/annotation/decorator introspection -- histogram of all annotations or per-site listings with target filters
tokensave_doc
Companion Markdown documentation for a source file -- doc content, the files it covers, and a staleness signal
tokensave_dependencies
Package-manifest introspection across 17 ecosystems -- workspace summary, per-package lookup, license surface, version drift
tokensave_status
Index status, statistics, tokens saved
Non-code artifacts
tokensave_files covers more than source. Files whose extension is listed in
artifact_extensions (.feature, .json, .yaml, .yml, .sql, .toml,
.proto, .graphql, .md, .bnd, .bndrun by default) are tracked by path
so questions like "where are the .feature files for the login flow?" have a
graph answer rather than a blocked find (#323). They are never parsed and contribute no symbols;
kind: "artifact" and kind: "code" filter between the two, and analyses that
mean "code" exclude them. An extension already handled by a language extractor
is ignored in this list, so it cannot be used to stop a language being parsed.
The list also decides what literal search can look inside (#442). A literal
(literal: true) search over tokensave_search reads bytes rather than
symbols, so it needs no parser -- but it iterates the indexed files, so it can
only reach a file the index holds a row for. A tracked .rst document or
.tmpl template has neither an extractor nor a default artifact entry, so its
matches are missing; add the extension here and run tokensave sync -f and its
lines are searched like any other, reported with enclosing: null since there
is no symbol context. A literal response that could not reach every tracked
file says so in an unscanned block naming the count and the extensions, so a
partial answer is never presented as a complete one.
Call Graph & Impact
Tool
Purpose
tokensave_callers
Find what calls a function
tokensave_callees
Find what a function calls
tokensave_impact
See what's affected by changing a symbol
tokensave_affected
Find test files affected by source changes
tokensave_rename_preview
All references to a symbol (preview rename impact)
tokensave_hotspots
Most connected symbols (highest call count)
Code Quality
Tool
Purpose
tokensave_complexity
Rank functions by cyclomatic & cognitive complexity, nesting depth, Halstead metrics, maintainability index, CRAP, and safety metrics
tokensave_dead_code
Find unreachable symbols (no incoming edges; symbols named as an ambiguity candidate are excluded)
tokensave_ambiguous_calls
Call sites the resolver could not pin to one target, with every tied candidate
tokensave_god_class
Find classes with too many members
tokensave_coupling
Rank files by fan-in/fan-out
tokensave_inheritance_depth
Find the deepest inheritance hierarchies
tokensave_circular
Detect circular file dependencies
tokensave_imports
Module-level import dependencies, cycles, and cut simulation
tokensave_recursion
Detect recursive/mutually-recursive call cycles
tokensave_unused_imports
Import statements never referenced
tokensave_doc_coverage
Public symbols missing documentation
tokensave_simplify_scan
Quality analysis of changed files (duplications, dead code, complexity)
Code-Health Analytics
Five tools surface structural quality signals from the existing graph. The composite score uses a geometric mean over independent dimensions so no single one can be gamed.
Tool
Purpose
tokensave_health
Composite quality signal (0-10000) from acyclicity, depth, equality, redundancy, and modularity
tokensave_gini
Gini inequality coefficient for any metric (complexity, lines, fan-in/out, members) -- finds god files and uneven distribution
tokensave_dependency_depth
Longest file-level dependency chains (Lakos levelization) with full chain reconstruction after Tarjan SCC cycle-breaking
tokensave_dsm
Design Structure Matrix in stats, clusters, or matrix form -- reveals layering violations and hidden coupling
tokensave_test_risk
Risk-weighted test-gap analysis combining complexity, fan-in, coverage, and 90-day git churn into a single score
Sessions
Snapshot health metrics at the start of an AI coding session, then diff at the end to see what improved or regressed.
Tool
Purpose
tokensave_session_start
Save current health metrics as a JSON baseline for later comparison
tokensave_session_end
Recompute and diff against the baseline -- per-dimension deltas, pass/fail, automatic cleanup
Edit Primitives
Four writer tools that let agents modify files without regex or shell-quoting hazards. Each is single-file, anchored, and triggers an in-place re-index after writing so the graph never goes stale.
Tool
Purpose
tokensave_str_replace
Replace a unique old_str with new_str; fails if 0 or >1 matches (protects against multi-edit bugs)
tokensave_multi_str_replace
Apply N (old, new) replacements atomically -- all-or-nothing transaction
tokensave_insert_at
Insert content before or after a unique anchor string or line number
tokensave_ast_grep_rewrite
Structural code rewrite via the ast-grep CLI in --rewrite mode
Semantic summary of uncommitted changes for commit message drafting
tokensave_pr_context
Semantic diff between git refs for pull request descriptions
tokensave_changelog
Semantic diff between two git refs
tokensave_test_map
Source-to-test mapping at the symbol level, with uncovered symbol detection
tokensave_test_coverage
Per-file/symbol/test-fn coverage rollup with transitive call-edge expansion
Type System
Tool
Purpose
tokensave_type_hierarchy
Recursive type hierarchy tree for traits, interfaces, and classes
tokensave_rank
Rank nodes by relationship count (most implemented interface, most extended class)
tokensave_distribution
Node kind breakdown per file or directory
tokensave_largest
Rank nodes by size -- largest classes, longest methods
Porting
Tool
Purpose
tokensave_port_status
Compare symbols between source/target directories to track porting progress
tokensave_port_order
Topological sort of symbols for porting -- port leaves first, then dependents
Multi-Branch
Tool
Purpose
tokensave_branch_search
Search symbols in another branch's graph
tokensave_branch_diff
Compare symbols between branches (added/removed/changed)
tokensave_branch_list
List tracked branches with DB sizes and sync times
MCP Resources
Four resources are exposed via resources/list and resources/read:
tokensave://status -- graph statistics as JSON
tokensave://files -- indexed file tree grouped by directory
tokensave://overview -- project summary with language distribution and symbol kinds
tokensave://branches -- tracked branches with DB sizes and parent info
Token Tracking
tokensave measures the tokens it saves on every MCP tool call. Each tool response includes a tokensave_metrics: before=N after=M line showing how many raw-file tokens were avoided by that specific call.
Turning the reporting off. The metrics line, together with a sentence in the MCP instructions, asks the agent to report savings to you β which means the model spends output tokens narrating a saving tokensave made on input tokens. Output tokens are the more expensive kind, so if your agent mentions tokensave on nearly every turn, that narration can offset the win (#356). Set report_savings to false in .tokensave/config.json, or the TOKENSAVE_REPORT_SAVINGS environment variable to override it per-run (any value enables it except 0, false, no, off, or empty). Both the metrics line and the instruction disappear; tokensave install likewise stops writing the reporting rule into agent prompt files. Measurement is untouched either way β every call still lands in the savings ledger, so tokensave gain, tokensave list, status and monitor keep reporting exactly as before. The default stays true.
Cost observability
bash
tokensave cost # 7-day cost summary (default)
tokensave cost today # today only
tokensave cost --by-model # breakdown by Claude model
tokensave cost --by-task # breakdown by task category (coding, debugging, exploration, ...)
tokensave cost --export json # JSON export to stdout
tokensave cost --export csv # CSV export to stdout
Parses Claude Code session transcripts (~/.claude/projects/**/*.jsonl), classifies each API turn into one of 13 task categories, computes dollar cost using model pricing, and stores results in ~/.tokensave/global.db for fast aggregate queries. Pricing is refreshed from LiteLLM every 24 hours and falls back to an embedded table when offline.
The tokensave status header includes a cost row showing today's spend, 7-day total, and efficiency ratio (tokens saved / total tokens). The tokensave monitor TUI shows a live cost panel alongside the savings feed. At the end of each Claude Code session, the hook_stop handler prints a one-line receipt to the terminal.
Task classification categories: Coding, Debugging, Feature Dev, Refactoring, Testing, Exploration, Planning, Delegation, Git Ops, Build/Deploy, Brainstorming, Conversation, General. Classification is deterministic (pattern matching on tool names and Bash commands), requires no LLM calls, and is adapted from AgentSeal/codeburn.
Live monitor
bash
tokensave monitor
A global TUI that shows MCP tool calls from all projects in real time, via a shared memory-mapped ring buffer at ~/.tokensave/monitor.mmap. Each entry shows the project name, tool name, and token delta. A cost panel at the top shows today's spend, savings, efficiency, and top model (refreshed every 30 seconds).
Memory diagnostics
bash
tokensave memory [--clean]
A machine-wide memory report for every tokensave process (MCP servers, syncs, index runs), via a shared memory-mapped table at ~/.tokensave/memory.mmap. Each instance self-samples its RSS best-effort at startup, per MCP tool call, and around the sync/resolution phases, so the report shows current and peak RSS with the phase that produced the peak β the data needed to attribute high memory use (see #253). Rows are flagged alive, dead (an OOM-killed process leaves its peak/phase behind as a forensic record), or orphan (still running but reparented to init). --clean purges dead slots.
PEAK PHASE names the highest sample, so it is only as precise as the sampling. Incremental sync records, in order: sync:extract, sync:resolve:load_nodes, sync:resolve:build_caches, sync:resolve:refs, sync:variants, sync:done. A full index records index:extract, index:resolve:build_caches, index:resolve:refs, index:resolve:done, index:insert, index:done.
Each is recorded after the work it names. They used to be recorded before it, so every sample reported the previous step's RSS under the next step's label β which attributed 73 MiB to the node load that in fact belonged to loading the unresolved references, a step with no sample at all, and pointed a memory investigation at the wrong subsystem for months (#409). If you add a phase, sample after the work, not before it, and add one for any step large enough to hold the peak.
Session and lifetime counters
bash
tokensave current-counter # show per-project session counter
tokensave reset-counter # reset the session counter
tokensave status # shows project + global lifetime totals + cost
tokensave status renders the project index stats, language breakdown, cost row (today / 7d / efficiency), and project + worldwide lifetime totals:
Worldwide counter
All tokensave users contribute to an anonymous aggregate counter. tokensave status shows both your project total and the worldwide total. The upload sends only a single number (e.g. 4823) with no identifying information. Opt out with tokensave disable-upload-counter.
Index Freshness
tokensave keeps the graph up to date without a background daemon or an OS-level file watcher.
On-demand staleness check. Every MCP tool call checks whether any indexed files have been modified since the last sync. If stale files are found, they are re-extracted before the tool response is returned. A 30-second cooldown prevents back-to-back calls from re-walking the tree on every keystroke.
Catch-up sync on connect. When the MCP server starts, it immediately runs a non-blocking catch-up sync that picks up any changes made while no agent was attached β a git pull, an IDE edit, a build step β so the very first tool call of a session sees a fresh index.
Multi-agent work and git worktrees. When multiple agents work on the same project concurrently, the strong assumption is that each agent operates in its own git worktree. Worktrees are independent filesystem checkouts of the same repository: agent A and agent B each have their own copy of every file, so they never overwrite each other's in-flight edits. tokensave automatically detects when a query comes from a worktree nested inside the main checkout and serves results from the correct branch graph. Changes accumulate independently and are eventually reconciled via git merge or rebase β the same process used for any other parallel development. This design avoids the complexity and failure modes of cross-agent locking over a shared mutable directory.
CLI-only workflows. If you run tokensave commands without an attached agent (no MCP server), the staleness check is not running between commands. Install git hooks to keep the index fresh automatically after every commit or clone:
The standalone tokensave daemon command and its launchd/systemd/Windows Service autostart were removed in 6.0.0. The embedded OS-level file watcher that replaced the daemon was itself removed in 6.1.1 (it caused runaway CPU and memory on large monorepos with deep node_modules or target trees). The on-demand staleness model above is the current design.
If you still have a daemon autostart from 5.x, remove it:
Windows: sc.exe delete tokensave-daemon (from an elevated terminal)
If you don't recall the exact name: launchctl list | grep tokensave / systemctl --user list-units | grep tokensave / sc.exe query state= all | findstr -i tokensave.
Self-Upgrade
bash
tokensave upgrade # upgrade to latest in current channel
tokensave channel # show current channel (stable/beta)
tokensave channel beta # switch to beta channel
tokensave channel stable # switch back to stable
tokensave upgrade downloads the correct platform binary from GitHub releases and replaces the running binary in place. Supports stable and beta channels independently.
Versioning & upgrades
tokensave version numbers look like SemVer but do not follow it: the component that changes encodes the maintenance the update requires, which tokensave performs automatically on the next launch β you never run a reinstall or reindex by hand.
Bump
Example
Update requires
Automatic action
Patch (x.y.Z)
7.2.0 β 7.2.1
Nothing
None β no reinstall, no reindex
Minor (x.Y.0)
7.2.0 β 7.3.0
A reinstall (new harnesses, new tools, new config)
Global reinstall of every installed agent integration (refreshes permissions, hooks, and MCP config)
Major (X.0.0)
7.2.0 β 8.0.0
A reinstall + full resync
Global reinstall and a per-project forced reindex (sync -f equivalent)
Global reinstall. On the first run of a new minor or major build, tokensave silently re-runs install for each agent it has registered, so the agent config always points at the current binary and exposes the current tool set. Patch bumps skip this β the running version marker is simply advanced.
The reinstall is genuinely silent: the per-agent setup output you see from an explicit tokensave install is suppressed here, so it never appears in front of an ordinary tokensave init or tokensave sync. If an agent's config can't be refreshed β the app isn't installed, or its config lives somewhere read-only β you get one line naming the agents that failed:
code
warning: could not refresh tokensave config for: copilot.
Run tokensave install to see the error.
Run tokensave install to see the underlying error. The version markers advance either way, so a config path that can never be written is reported once per upgrade rather than retried on every subsequent command.
Per-project forced reindex (major only). A major bump means project indexes must be rebuilt. tokensave does this lazily and per project: on the first MCP tool call in a project after a major upgrade, it spawns a background full reindex (equivalent to tokensave sync --force) that never blocks the tool response.
Brew / cargo fallback. External upgrades that replace the binary outside of tokensave upgrade β brew upgrade tokensave or cargo install tokensave β are detected the same way: if the running version is newer than the last version that performed an install, the reinstall runs on the next launch just as it would after a self-upgrade.
See TOKENSAVE-VERSIONING.md for why tokensave diverges from SemVer (encoding maintenance in the version is what makes zero-touch upgrades possible), the marker mechanics, the independent database schema version, and the maintainer rules for cutting releases.
CLI Reference
bash
tokensave init [path] # Initialize a new project (full index)
tokensave sync [path] # Incremental sync (must be initialized first)
tokensave sync --force [path] # Force a full re-index
tokensave sync --doctor [path] # Sync and list added/modified/removed files
tokensave status [path] # Show statistics + cost summary
tokensave status [path] --json # Show statistics (JSON output)
tokensave status --details # Include node-kind breakdown
tokensave cost [range] # Token cost summary (default: 7d)
tokensave cost --by-model # Cost grouped by model
tokensave cost --by-task # Cost grouped by task category
tokensave cost --export json|csv # Export cost data
tokensave query <search> [path] # Search symbols
tokensave files [--filter dir] [--pattern glob] [--json] # List indexed files
tokensave affected <files...> [--stdin] [--depth N] # Find affected test files
tokensave install [--agent NAME] # Configure agent integration
tokensave reinstall # Refresh settings for all installed agents
tokensave uninstall [--agent NAME] # Remove agent integration
tokensave serve [--idle-timeout-secs N] # Start MCP server (N: exit after N idle seconds)
tokensave servers [--json] # List running servers and the index each one holds
tokensave monitor # Live TUI showing MCP calls across all projects
tokensave memory [--clean] # Per-instance RSS report for all tokensave processes
tokensave upgrade # Self-update to latest version
tokensave channel [stable|beta] # Show or switch update channel
tokensave doctor [--agent NAME] # Check installation health
tokensave githooks [on|off] [--local] # Manage git hooks (--local: this repo only, no core.hooksPath)
tokensave branch add|list|remove|removeall|gc # Multi-branch management
tokensave current-counter # Show per-project token counter
tokensave reset-counter # Reset per-project token counter
tokensave disable-upload-counter # Opt out of worldwide counter uploads
tokensave enable-upload-counter # Re-enable worldwide counter uploads
tokensave doctor
Run a comprehensive health check of your tokensave installation:
bash
tokensave doctor
Checks: binary location, project index, global DB, user config, agent integration (MCP server, hooks, permissions, prompt rules), and network connectivity. If any tool permissions are missing after an upgrade, it tells you to run tokensave install. Use --agent to check a specific agent only.
Doctor also validates that each installed hook uses the correct tokensave subcommand and auto-repairs broken hooks.
How It Works with Claude Code
Once configured, Claude Code automatically uses tokensave instead of reading raw files when it needs to understand your codebase. Three layers reinforce each other:
Layer
What it does
Why it matters
MCP server
Exposes 80+ tokensave_* tools to Claude
Claude can query the graph directly
CLAUDE.md rules
Tells Claude to prefer tokensave over agents/file reads
Prevents the model from falling back to expensive patterns
PreToolUse hook
Native Rust hook blocks Explore agents
Catches cases where the model ignores the CLAUDE.md rules
UserPromptSubmit hook
Runs at prompt submission
Lifecycle tracking for token accounting
Stop hook
Runs when the session ends
Flushes token counters
The result: Claude gets the same code understanding with far fewer tokens. A typical Explore agent reads 20-50 files; tokensave returns the relevant symbols, relationships, and code snippets from its pre-built index.
Network Calls & Privacy
tokensave's core functionality (indexing, search, graph queries, MCP server) is 100% local -- your code never leaves your machine.
Call
Data sent
When
Opt-out
Worldwide counter upload
Token count (a number) + country (from IP)
sync, status, MCP sessions
tokensave disable-upload-counter
Worldwide counter read
Nothing (GET request)
status
N/A (read-only, 1s timeout)
Version check
Nothing (GET request)
status (cached 5m), sync (parallel)
N/A (1s timeout, no-op on failure)
Model pricing refresh
Nothing (GET request)
tokensave cost (cached 24h)
N/A (5s timeout, falls back to embedded pricing)
The worldwide counter upload sends a single HTTP POST with a JSON body like {"amount": 4823}. No cookies, no tracking, no user ID. The Cloudflare Worker logs the country of your IP address (derived from request headers) for aggregate geographic statistics -- your actual IP address is not stored.
The model pricing refresh fetches a public JSON file from GitHub (raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json) to keep Claude model pricing up to date for tokensave cost. No data is sent -- it is a plain HTTPS GET. The response is cached at ~/.tokensave/pricing.json for 24 hours. If the fetch fails, tokensave uses its compiled-in pricing table.
50+ Languages
tokensave supports more than 50 programming languages organized into three tiers controlled by Cargo feature flags. Each tier includes all languages from the tier below it. Markdown headers are extracted as Module nodes with hierarchical Contains edges so document structure participates in graph queries alongside source code.
Lite -- --no-default-features
Always compiled. The smallest binary for the most popular languages, plus Svelte and Astro (script-block extraction via the TypeScript extractor, no extra grammar dependency).
Language
Extensions
Rust
.rs
Go
.go
Java
.java
Scala
.scala, .sc
TypeScript
.ts, .tsx
JavaScript
.js, .jsx
Python
.py
C
.c, .h
C++
.cpp, .hpp, .cc, .cxx, .hh
Kotlin
.kt, .kts
C#
.cs
Swift
.swift
Svelte
.svelte
Astro
.astro
Medium (Lite + 9 more) -- --features medium
Language
Extensions
Feature flag
Dart
.dart
lang-dart
Pascal
.pas, .pp, .dpr
lang-pascal
PHP
.php
lang-php
Ruby
.rb
lang-ruby
Bash
.sh, .bash
lang-bash
Protobuf
.proto
lang-protobuf
PowerShell
.ps1, .psm1
lang-powershell
Nix
.nix
lang-nix
VB.NET
.vb
lang-vbnet
Full (Medium + everything else) -- default
Language
Extensions
Feature flag
ActionScript
.as
lang-actionscript
Lua
.lua
lang-lua
Zig
.zig
lang-zig
Objective-C
.m, .mm
lang-objc
Perl
.pl, .pm
lang-perl
Batch/CMD
.bat, .cmd
lang-batch
Fortran
.f90, .f95, .f03, .f08, .f18, .f, .for
lang-fortran
COBOL
.cob, .cbl, .cpy
lang-cobol
MS BASIC 2.0
.bas
lang-msbasic2
GW-BASIC
.gw
lang-gwbasic
QBasic
.qb
lang-qbasic
QuickBASIC 4.5
.bi, .bm
lang-qbasic
Dockerfile
Dockerfile, .dockerfile
lang-dockerfile
GLSL
.glsl, .vert, .frag, .comp
lang-glsl
Godot Shader
.gdshader, .gdshaderinc
lang-glsl
Minecraft Function
.mcfunction
lang-mcfunction
WGSL
.wgsl
lang-wgsl
HLSL
.hlsl, .fx
lang-hlsl
Verilog / SystemVerilog
.v, .vh, .sv, .svh
lang-systemverilog
Metal
.metal
lang-metal
CUDA / HIP
.cu, .cuh
lang-cuda
Markdown
.md, .markdown
lang-markdown
R
.r, .R
lang-r
SQL
.sql
lang-sql
Julia
.jl
lang-julia
Haskell
.hs, .lhs
lang-haskell
OCaml
.ml, .mli
lang-ocaml
Clojure
.clj, .cljs, .cljc
lang-clojure
Erlang
.erl, .hrl
lang-erlang
Elixir
.ex, .exs
lang-elixir
F#
.fs, .fsi, .fsx
lang-fsharp
F*
.fst, .fsti
lang-fstar
Quint
.qnt
lang-quint
Terraform
.tf, .tfvars
lang-terraform
TOML
.toml
lang-toml
Lean
.lean
lang-lean
HTML
.html, .htm
lang-html
CSS
.css
lang-css
Individual languages can also be cherry-picked without a full tier:
All extractors share the same depth: functions, classes, methods, fields, imports, call graphs, inheritance chains, docstrings, complexity metrics, decorator/annotation extraction, and cross-file dependency tracking.
HTML and CSS are the exception, because neither language has callable symbols. HTML records elements carrying an id, custom elements, and the stylesheets and scripts a page pulls in; CSS records class and id selectors, custom properties, @keyframes names, and @imports. Neither resolves a class="..." attribute to a stylesheet rule: class names are ordinary words, and matching them by bare name across a whole project invents edges rather than finding them.
tokensave vs CodeGraph
tokensave is a ground-up Rust rewrite of CodeGraph (Node.js/TypeScript). Both build semantic code graphs for AI coding agents, but they diverge significantly in scope and capabilities.
4 atomic writers (str_replace, multi_str_replace, insert_at, ast_grep_rewrite) with auto re-indexing
No
Crash resilience
Subprocess-isolated extraction; native grammar aborts skip the file, sync continues
No
Self-upgrade
tokensave upgrade with stable/beta channels
npm update
DB engine
libsql (SQLite fork, WAL, async)
better-sqlite3 / wa-sqlite (WASM)
Indexing speed
~1.2s for 1,782 files
~4s for 1,782 files
Binary size
~25 MB compressed download (all grammars bundled)
~80 MB (node_modules + WASM)
CodeGraph pioneered the approach and remains a solid choice if you prefer npm tooling and only need Claude Code integration. tokensave extends the concept with deeper analysis, more agents, multi-branch support, and a native binary with no runtime dependencies.
For detailed comparisons against CodeGraph, Dual-Graph (GrapeRoot), code-review-graph, and OpenWolf, see docs/COMPARABLE-TOOLS.md.
Several tools reduce token usage for AI coding agents. Here's why tokensave stands apart.
Single native binary, zero dependencies
Most alternatives require a runtime: Python, Node.js, or both. tokensave ships as a single Rust binary with all 50+ tree-sitter grammars bundled (~25 MB compressed download). Nothing else to install -- and unlike LSP-backed tools such as Serena, no language server to install, start or warm up per language. Two tools now match tokensave on packaging: CodeGraph bundles its own runtime, and LeanCTX is also a single Rust binary.
Deepest code intelligence
tokensave works at the symbol level: functions, structs, fields, call edges, type hierarchies, complexity metrics. Alternatives like Dual-Graph (GrapeRoot) work at the file level -- they know which files exist but can't answer "who calls this function?" or "what breaks if I change this struct?" tokensave's 80+ specialized MCP tools cover call graph traversal, impact analysis, dead code detection, test mapping, rename preview, type hierarchies, circular dependency detection, complexity ranking, code-health analytics (Gini, DSM, dependency depth, risk-weighted test gaps), atomic edit primitives, and more. The closest comparable graph tool, code-review-graph, exposes 30; several others expose fewer than 10 by deliberate design.
Broadest agent support
More than a dozen AI coding agent integrations with per-agent native configuration formats. No other tool covers as many agents with as deep an integration. Claude Code gets hooks, prompt rules, and auto-allowed tool permissions. Kiro gets global MCP config, tokensave.md steering loaded as a resource, a managed agent with permissive built-in/tokensave tool approval, and hooks for delegation guardrails plus post-write sync. Other agents get MCP server registration in their native config format.
Multi-branch indexing
The only tool in this space with optional per-branch graph databases and cross-branch diff and search. When enabled, switching branches is instant -- no re-indexing required.
Per-call token tracking
The only tool that reports exactly how many tokens each individual MCP tool call saved, plus a live TUI monitor across all projects and lifetime counters.
Fully open source
MIT-licensed Rust, auditable end to end. Dual-Graph's core engine (graperoot on PyPI) is proprietary -- you can't see what it does with your code graph. OpenWolf is AGPL-3.0, which requires derivative works to be open-sourced.
Performance
Full-index benchmark on a 1,782-file mixed Rust/Java/Scala codebase (57K nodes, 103K edges):
Tool
Time
Speedup
CodeGraph (TypeScript)
31.2s
1x
tokensave (Rust)
1.2s
26x
Troubleshooting
"tokensave not initialized"
The .tokensave/ directory doesn't exist in your project.
bash
tokensave init
MCP server not connecting
The AI agent doesn't see tokensave tools.
Ensure the agent config includes the tokensave MCP server (run tokensave doctor)
Restart the agent completely
Check that tokensave is in your PATH: which tokensave
Missing symbols in search
Run tokensave sync to update the index
Check that the language is supported (see table above)
Verify the file isn't excluded by .gitignore
Indexing is slow
Large projects take longer on the first full index.
Subsequent runs use incremental sync and are much faster
Use tokensave sync (not --force) for day-to-day updates
Staleness is checked automatically on every MCP tool call while an agent is connected
Disabling tokensave for specific projects
If a project is too large and tokensave uses too much RAM, you can disable the MCP server per-project by setting TOKENSAVE_DISABLE_SERVER=true in its environment. The server exits cleanly without initializing.
Claude Code β add to your project's .claude/settings.json:
Other agents β set the environment variable in whatever config your agent uses to launch MCP servers.
You can also set it globally via the shell (TOKENSAVE_DISABLE_SERVER=true claude), but this disables the tokensave MCP server for every project in the session.
DISABLE_TOKENSAVE=true remains supported as a deprecated compatibility alias for configurations created before this variable was namespaced.
Origin
This project is a Rust port of the original CodeGraph TypeScript implementation by @colbymchenry. The port maintains the same architecture and MCP tool interface while leveraging Rust for performance and native tree-sitter bindings.
Building
bash
cargo build --locked --release # full (50+ languages, default)
cargo build --locked --release --features medium # medium tier
cargo build --locked --release --no-default-features # lite (smallest binary)
cargo test --workspace --locked # run all tests (requires full)
cargo check --locked --no-default-features # verify lite compiles
cargo clippy --workspace --all-targets --locked
Development commands use debug builds; installation uses optimized release output
only (cargo install --path . --locked). target/debug is never an installation input.