Code intelligence for 15+ languages: semantic graph queries instead of file reads. 37 MCP tools.
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.
┌──────────────────────────────────────────────────────────────┐
│ AI Coding Agent (Claude Code, Codex, Gemini, Cursor, ...) │
│ │
│ "Implement user authentication" │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Sub-agent │ ───── │ Sub-agent │ │
│ └────────┬────────┘ └─────────┬───────┘ │
└───────────┼──────────────────────────┼───────────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ tokensave MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Search │ │ Callers │ │ Context │ │
│ │ "auth" │ │ "login()" │ │ for task │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ libSQL Graph DB │ │
│ │ • Instant lookups │ │
│ │ • FTS5 search │ │
│ └───────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
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.
| 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. |
Homebrew (macOS):
brew install aovestdipaperino/tap/tokensave
Scoop (Windows):
scoop bucket add tokensave https://github.com/aovestdipaperino/scoop-bucket
scoop install tokensave
Cargo / cargo-binstall (any platform):
# 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 |
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.
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:
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.
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.
{
"mcpServers": {
"tokensave": {
"command": "/path/to/tokensave",
"args": ["serve"]
}
}
}
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.
Appends instructions to ~/.claude/CLAUDE.md that tell Claude to use tokensave tools before reaching for Explore agents or raw file reads.
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.
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.
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.
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
Three MCP tools enable cross-branch queries without switching your checkout:
tokensave_branch_search -- search symbols in another branch's graphtokensave_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 timesWhen 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.
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.
See docs/BRANCHING-USER-GUIDE.md for the full guide.
Three MCP tools persist decisions and code-area context across sessions, stored in the per-project .tokensave/tokensave.db.
| Tool | Purpose |
|---|---|
tokensave_record_decision | Save a design/architecture decision with optional reason, files, and tags |
tokensave_record_code_area | Mark a path the agent has worked in (touch counter + last_touched_at) |
tokensave_session_recall | FTS5 query over saved decisions; pair with the two write tools |
Use these so the agent doesn't have to re-explain architecture choices session-to-session.
Every MCP call writes an append-only row to ~/.tokensave/global.db (savings_ledger table). Inspect with tokensave gain:
tokensave gain # current project, last 30 days
tokensave gain --all # all projects
tokensave gain --history --range 7d
tokensave gain --json
Dollar estimates use the existing pricing module (Sonnet input pricing, refreshed daily via LiteLLM).
tokensave bench runs a fixed query set through tokensave_context and reports retrieval savings vs a full-file baseline (mirrors the CCE methodology):
tokensave bench # ships with 10 default queries
tokensave bench --queries my-queries.toml --json
tokensave bench --max-nodes 5
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.
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):
| Repo | URL | Ref |
|---|---|---|
| polkadot-sdk | https://github.com/paritytech/polkadot-sdk | polkadot-stable2412 |
| emacs | https://github.com/emacs-mirror/emacs | emacs-30.1 |
| scipy | https://github.com/scipy/scipy | v1.14.1 |
| node | https://github.com/nodejs/node | v22.11.0 |
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.
Tools covered (5 queries each). Read tools — search, context, callers, callees, node, by_qualified_name, signature, impact, body, files, complexity, doc_coverage, largest, hotspots, god_class, module_api, derives, dead_code, rank, coupling, circular. Write tools — str_replace, multi_str_replace, insert_at, and (if ast-grep is on PATH) ast_grep_rewrite.
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:
# Required: a writable cache directory for the cloned repos + their indexes.
# 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:
cargo bench --bench large_repos -- 'scipy/tokensave_search'
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.
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:
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).
Quick run:
cargo build --release --bin tokensave
python3 scripts/mcp_probe/probe.py
python3 scripts/mcp_probe/build_matrix.py > matrix.md
Output cells are ✓ 5/5 (clean), 🐛 e/N (errors), ⏱ N/N (timeouts), ∅ E/N (empty), 🐢 ok/slow (>10 s calls). Any cell carrying an error or timeout earns a 🚩 in the rightmost column. Per-call detail with the first 100 chars of each error landS in the TSV log for follow-up.
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.
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.
Semantic read tools can query an explicitly selected local graph without restarting the MCP server:
{
"query": "screenGate",
"graph_root": "/absolute/path/to/typewhisper"
}
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:
{
"node_id": "graph:<fingerprint>:function:<raw-id>",
"graph_root": "/absolute/path/to/typewhisper",
"graph_branch": "feature/auth"
}
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.
| 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 |
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.
| 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) |
| 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) |
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 |
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 |
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 |
| Tool | Purpose |
|---|---|
tokensave_diff_context | Semantic context for changed files -- modified symbols, dependencies, affected tests |
tokensave_commit_context | 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 |
| 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 |
| 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 |
| 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 |
Four resources are exposed via resources/list and resources/read:
tokensave://status -- graph statistics as JSONtokensave://files -- indexed file tree grouped by directorytokensave://overview -- project summary with language distribution and symbol kindstokensave://branches -- tracked branches with DB sizes and parent infotokensave 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.
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.
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).
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.
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:
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.
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:
cp scripts/post-commit scripts/post-checkout .git/hooks/
chmod +x .git/hooks/post-commit .git/hooks/post-checkout
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:
launchctl unload ~/Library/LaunchAgents/com.tokensave.daemon.plist && rm ~/Library/LaunchAgents/com.tokensave.daemon.plistsystemctl --user disable --now tokensave-daemon && rm ~/.config/systemd/user/tokensave-daemon.servicesc.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.
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.
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:
warning: could not refresh tokensave config for: copilot.
Run tokensave install to see the error.
Run `tokensa
This listing does not have a supported local package template. Use the maintainer’s documentation for its hosted endpoint, authentication, and client-specific setup. No install command has been inferred.
https://github.com/aovestdipaperino/tokensave/releases/download/v4.0.2/tokensave-v4.0.2-aarch64-macos.mcp.tar.gzotherTokenSave works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.