Fewer tokens • Fewer tool calls • 100% local
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.
tracedecay 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 │ │
│ └────────┬────────┘ └─────────┬───────┘ │
└───────────┼──────────────────────────┼───────────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ tracedecay MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Search │ │ Callers │ │ Context │ │
│ │ "auth" │ │ "login()" │ │ for task │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ libSQL Graph DB │ │
│ │ • Instant lookups │ │
│ │ • FTS5 search │ │
│ └───────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Without tracedecay: Agents use grep, glob, and Read to scan files -- many API calls, high token usage.
With tracedecay: 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. |
| 70+ 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 42 more including WGSL/HLSL/Metal shaders and Markdown. Three tiers (lite/medium/full) control binary size. | Claude Code, Codex CLI, Gemini CLI, Hermes, Kiro, Cursor, OpenCode, Copilot, Cline, Roo Code, Zed, Antigravity, Kilo CLI, Kimi CLI, Mistral Vibe. |
| Multi-Branch Indexing (opt-in) | 100% Local | Always Fresh |
| Optional per-branch databases. Cross-branch diff and search without switching your checkout. | Source code and memory content stay on your machine. No API keys or hosted database are required; the index runs on local libSQL. | 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. |
| Local Dashboard | Subprocess-Isolated Extraction | Code-Health Analytics |
| Explore holographic memory (facts, entities, similarity detection) and LCM session data via a local web UI. Built-in PCA projection, duplicate detection, and curation tools. | 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. |
| Atomic Edit Primitives | ||
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 ScriptedAlchemy/tap/tracedecayScoop (Windows):
scoop bucket add tracedecay https://github.com/ScriptedAlchemy/scoop-bucket
scoop install tracedecayNote: The Homebrew tap and Scoop bucket are external repositories updated separately from this one — until they pick up the rename, the package may still be published under the legacy
tokensavename.
Cargo (any platform):
cargo install tracedecay # full (50+ languages, default)
cargo install tracedecay --features medium # medium tier
cargo install tracedecay --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) | tracedecay-vX.Y.Z-aarch64-macos.tar.gz |
| Linux (x86_64) | tracedecay-vX.Y.Z-x86_64-linux.tar.gz |
| Linux (ARM64) | tracedecay-vX.Y.Z-aarch64-linux.tar.gz |
| Windows (x86_64) | tracedecay-vX.Y.Z-x86_64-windows.zip |
tracedecay install # auto-detects installed agents
tracedecay install --agent antigravity # Google Antigravity (formerly Windsurf)
tracedecay install --agent claude # Claude Code
tracedecay install --agent cline # Cline
tracedecay install --agent codex # OpenAI Codex CLI
tracedecay install --agent copilot # GitHub Copilot
tracedecay install --agent cursor # Cursor
tracedecay install --agent gemini # Gemini CLI
tracedecay install --agent hermes # Hermes Agent
tracedecay install --agent hermes --profile work
tracedecay install --agent kilo # Kilo CLI
tracedecay install --agent kiro # AWS Kiro
tracedecay install --agent kimi # Moonshot Kimi CLI
tracedecay install --agent opencode # OpenCode
tracedecay install --agent roo-code # Roo Code
tracedecay install --agent vibe # Mistral Vibe
tracedecay install --agent zed # ZedEach agent gets its MCP server registered in the native config format where that is the agent's integration model. 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, tracedecay.md steering loaded as a resource, and a tracedecay-managed default agent with permissive built-in/tracedecay tool approval, delegation guardrail hooks, and post-write sync; user-managed Kiro agents are preserved. Codex gets a Codex plugin bundle for MCP + skills, prompt rules in AGENTS.md, and a Claude-style lifecycle hook set in ~/.codex/hooks.json (see below). Hermes gets a native profile plugin that registers tracedecay tools through Hermes' plugin API, plus a tracedecay memory provider and a tracedecay LCM context engine with native lcm_* session tools backed by the tracedecay_lcm_* MCP tools. Cursor gets a local Cursor plugin installed into ~/.cursor/plugins/local/tracedecay; the installer writes a real plugin directory, rewrites plugin MCP/hooks to the resolved absolute tracedecay executable path, and bundles MCP, hooks, and the tracedecay rule.
All changes are idempotent -- safe to run again after upgrading. After agent setup, you'll be offered a global git post-commit hook.
For project-scoped setup, run from the repository root:
tracedecay install --local --agent cursorLocal install writes only workspace files such as .mcp.json, .codex/config.toml, .vscode/mcp.json, .hermes/plugins/tracedecay/, or the equivalent project config for Claude, Codex, Gemini, Hermes, Kiro, OpenCode, Copilot/VS Code, Zed, Roo Code, Kimi, Kilo, and Vibe. Generated MCP configs and plugin wrappers use the resolved absolute tracedecay executable path. Hermes installs into ~/.hermes/plugins/tracedecay/ by default, or into ~/.hermes/profiles/<name>/plugins/tracedecay/ with --profile <name>; profile names are normalized to lowercase and must match [a-z0-9][a-z0-9_-]{0,63}. The generated context engine resolves its project from explicit host kwargs first, then a project_root key on the Hermes config object, then the install-time pin, and finally the session cwd. Pin a profile to one project with tracedecay install --agent hermes [--profile <name>] --project-root /abs/path — the pin is written into the generated plugin, applies to every plugin tool call regardless of the Hermes working directory, and survives later unpinned reinstalls. Use tracedecay uninstall --agent hermes --profile <name> to remove a named profile install; reinstall and doctor --agent hermes currently operate on the default profile. To refresh generated plugin code after an upgrade without any config writes, run tracedecay update-plugin (alias update-plugins): it rewrites only tracedecay-generated artifacts — the Hermes plugin files and dashboard page for every detected profile (pin re-read from config.yaml, never written), the Cursor plugin bundle, the Codex plugin bundle, and the Kiro managed agent — and leaves config.yaml, config.toml, mcp.json, settings, hooks, and prompt rules byte-for-byte intact. Config-managed integrations (Claude, Gemini, …) have no generated artifacts and are reported as untouched; tracedecay reinstall remains the command that reconciles their config entries. Hermes wrappers run from Hermes' current working directory, use a 600-second timeout, and include truncated stdout/stderr in error JSON. Hermes local install without --profile writes only project plugin files and .hermes/config.yaml; tracedecay install --local --agent hermes --profile <name> is a deliberate mixed-scope mode that targets the named profile instead. Project-local Hermes plugins are loaded by launching Hermes with HERMES_HOME=<project>/.hermes. For Codex, global install writes a Codex plugin source bundle to ~/plugins/tracedecay, registers it in ~/.agents/plugins/marketplace.json, and prints codex plugin add tracedecay@personal; hooks and AGENTS.md stay config-managed because current Codex plugin manifests accept MCP and skills but not hook declarations. For Cursor, both global and --local install put the plugin in ~/.cursor/plugins/local/tracedecay and require a Cursor reload. The plugin MCP config runs tracedecay serve --path ${workspaceFolder}, so it resolves the active workspace instead of the plugin directory and uses the workspace .tracedecay/ index rather than the legacy global Cursor MCP registration. Cursor install no longer writes .cursor/mcp.json, .cursor/hooks.json, .cursor/rules/tokensave.mdc (legacy artifact name), or .cursor/permissions.json; approvals are left to Cursor approval/run-mode behavior. The plugin hooks are:
sessionStart— fire-and-forget; injects context steering the Agent toward tracedecay MCP tools and reports index freshness (suggeststracedecay initwhen no.tracedecay/exists).subagentStart— blocks research/explore subagents until tracedecay MCP tools have been tried; the plugin's owncode-explorer/code-health-auditor/session-historianagents are allow-listed.postToolUse(unmatched — Cursor's docs enumerate no matcher value for semantic search) — fail-open; injects a softadditional_contexthint after broad search/read tools (Grep, Glob, Read, semantic search, shellrg) so Cursor switches totracedecay_context,tracedecay_search,tracedecay_outline, ortracedecay_files. Each hint category is emitted at most once per session (persisted in.tracedecay/tool_hints_seen.json).beforeSubmitPrompt— resets the local token counter for the new turn and ingests the current Cursor transcript into.tracedecay/sessions.dbwhentranscript_pathis present.afterFileEdit(unmatched, so every Agent edit tool counts) — runs a targeted single-file sync of just the edited path(s) viasync_if_stale_silent, never a full-tree scan (which would scale with repo size, not edit size).afterShellExecution— on Agent-rungit checkout/switch/worktree add, bootstraps/maintains tracedecay branch tracking (branch add); on other state-changing git commands (pull/merge/rebase/reset/cherry-pick/stash apply|pop), runs a coalesced incremental sync.workspaceOpen— ensures the current branch's DB exists (branch add if missing) and runs a catch-up incremental sync.
All Cursor hooks are fail-open and only act when a .tracedecay/ index already exists. Blind spot: Cursor hooks only observe the Cursor Agent's own actions and IDE lifecycle. Manual/external-terminal git checkout and in-place branch switches are NOT seen by these hooks (workspaceOpen does not fire for an in-place checkout). For those, the git post-commit hook and the on-demand MCP staleness check remain the freshness mechanism. We intentionally keep the Cursor postToolUse hint nonblocking: it nudges broad search toward tracedecay but does not deny reads/search.
Manual Cursor plugin install for local development:
mkdir -p ~/.cursor/plugins/local
rm -rf ~/.cursor/plugins/local/tracedecay
cp -R /path/to/tracedecay/cursor-plugin ~/.cursor/plugins/local/tracedecayReload Cursor after installing or replacing the plugin. Manual copies use the commands in the source bundle (tracedecay ...), so make sure GUI-launched Cursor can resolve tracedecay from PATH; the normal tracedecay install --agent cursor path rewrites commands to the absolute binary path. The plugin relies on Cursor expanding ${workspaceFolder} in MCP config; if tools do not connect, upgrade Cursor and run tracedecay doctor --agent cursor to inspect the generated plugin files.
Codex now supports a Claude-style lifecycle hook system (verified against Codex 0.136.0 — the old "Codex has no hook system" note was wrong). Both global (~/.codex/hooks.json) and project-local (<root>/.codex/hooks.json) installs register tracedecay hooks, written in Codex's nested hooks[event] -> { matcher?, hooks: [ { type:"command", command, timeout } ] } shape and reconciled idempotently (foreign hooks preserved). Each hook reads Codex's stdin JSON event and emits Codex-shaped stdout:
SessionStart— emitshookSpecificOutput.additionalContextsteering the agent toward tracedecay MCP tools and reporting index freshness (suggeststracedecay initwhen uninitialized).UserPromptSubmit— resets the per-project local counter and injects the same steering context for the new turn.SubagentStart— redirects research/explore subagents toward tracedecay MCP tools viaadditionalContext. (Per Codex docs,SubagentStartcannot hard-stop a subagent —continue:falseis ignored — so this steers rather than denies.)PostToolUse(matcherBash|apply_patch) — forapply_patchedits, runs a targeted single-file sync of just the patched paths (parsed from the patch envelope); forBashgit commands, reuses the shared classifier to route branch switches →branch addand other state-changing commands → coalesced incremental sync.
All Codex hooks are fail-open and only act when a .tracedecay/ index exists. Trust gate: Codex skips new or changed non-managed command hooks until you trust them — run /hooks inside Codex to review and trust the tracedecay hooks (the installer prints this reminder; --dangerously-bypass-hook-trust exists for one-off non-interactive runs). Blind spots: PostToolUse only fires for apply_patch edits and "simple" Bash — raw-shell file edits, unified_exec, and WebSearch are not observed; there is no first-class branch-switch event, so branch switches are derived from Bash git commands. PreToolUse is intentionally not installed: Codex documents it as a partial guardrail (it can't intercept unified_exec/WebSearch/raw-shell edits), so a redundant-exploration blocker there would be unreliable and noisy.
Local install does not update ~/.tracedecay/config.toml, installed-agent tracking, the last installed version, or the global git post-commit hook. Antigravity and Cline are global-only and return clear unsupported errors for --local.
cd /path/to/your/project
tracedecay initNon-interactive environments (CI, containers, headless shells): init, status, and bare invocation skip prompts and use safe defaults. init creates the index without modifying .gitignore (prints a notice); status exits cleanly without creating an index if none exists.
This creates a .tracedecay/ directory with the knowledge graph database. (Projects initialized before the rename keep working: an existing .tokensave/ directory is still honored as a fallback.) 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 post-commit hook from silently creating databases in repos you never intended to index. After init, use tracedecay sync to incrementally update -- only changed files are re-indexed.
What install writes for Claude Code
{
"mcpServers": {
"tracedecay": {
"command": "/path/to/tracedecay",
"args": ["serve"]
}
}
}The hook runs tracedecay hook-pre-tool-use -- a native Rust command (no bash or jq required). It intercepts Agent tool calls and blocks Explore agents, redirecting Claude to use tracedecay MCP tools instead.
Appends instructions to ~/.claude/CLAUDE.md that tell Claude to use tracedecay tools before reaching for Explore agents or raw file reads.
tracedecay includes a local web dashboard for exploring your project's holographic memory and LCM (Lossless Context Management) session data. Everything runs locally — no external services or API keys required.
# Start the dashboard (serves on http://127.0.0.1:7341 by default)
tracedecay dashboard
# Use a custom port or bind to a different address
tracedecay dashboard --port 8080
tracedecay dashboard --host 0.0.0.0 --port 7341
# Let the OS pick a free port (prints the URL)
tracedecay dashboard --port 0
# Open the dashboard in your default browser automatically
tracedecay dashboard --openMCP-connected agents can also start/stop the dashboard via the tracedecay_dashboard tool, which runs the server as a background task inside the MCP server and returns the listening URL (idempotent; pass action: "stop" to shut it down gracefully).
The dashboard has four main tabs:
Holographic Memory — Explore your project's persistent memory:
- Inspector: Browse facts, entities, and memory banks with trust scores and HRR coverage
- Semantic Map: 2D PCA visualization of holographic vectors showing fact relationships
- Association Graph: Interactive graph of facts, entities, categories, and banks
- Similarity: Detect likely duplicates and merge candidates using phase-vector cosine similarity
- Curation: (feature-flagged) Preview and run similarity-based deduplication; applying a plan permanently deletes (hard-delete) the lower-trust fact in each duplicate pair. There is no archive, no restore, and no soft-delete state—deleted facts immediately disappear from all recall paths.
LCM — Analyze Lossless Context Management session data:
- Overview: Message counts, summary nodes, compression ratios, and role/source breakdowns
- Search: Full-text search across raw messages and summary nodes with role/source/session filters
- Timeline: Time-bucketed activity visualization (hourly or daily)
- Compression: Per-session and per-node compression statistics showing token savings
Code Graph — Interactively explore the indexed code graph:
- Overview: Symbols by kind family, files by language, most-connected symbols, largest files
- Canvas: Force-directed explorer with search-to-focus, progressive neighbor expansion, callers/callees, filters, and shortest-path finding between two symbols
See docs/graph-explorer.md for the Code Graph tab's API and interaction details.
Savings & Cost — Token usage analytics and cost tracking (under active development).
When using the Hermes agent, the dashboard can be accessed via the TraceDecay tab. Two integration modes are supported:
- Spawn mode (default): Hermes automatically launches the dashboard server
- External URL mode: Point Hermes at an already-running dashboard
See docs/dashboard.md for full documentation on environment variables, API endpoints, and troubleshooting.
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 TRACEDECAY_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 TRACEDECAY_DISABLE_SUBPROCESS=1.
Edit primitives (tracedecay_str_replace, tracedecay_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.
tracedecay 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, tracedecay uses a single database for all branches.
When you track a branch, tracedecay 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.
Branch databases are stored with collision-safe names (special characters encoded) to support any valid git branch name, including those with slashes, spaces, or Unicode characters.
tracedecay branch add # track the current branch
tracedecay branch list # see tracked branches and DB sizes
tracedecay branch remove <name> # stop tracking a branch
tracedecay branch removeall # remove all tracked branches except default
tracedecay branch gc # clean up branches deleted from gitThree MCP tools enable cross-branch queries without switching your checkout:
tracedecay_branch_search-- search symbols in another branch's graphtracedecay_branch_diff-- compare code graphs between two branches: symbols added, removed, and changed (signature differs). Supports file and kind filters.tracedecay_branch_list-- list tracked branches with DB sizes, parent branch, and sync times
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 tracedecay branch add.
See docs/BRANCHING-USER-GUIDE.md for the full guide. If branch state ever drifts or a branch DB goes missing, see docs/MULTI-BRANCH-RECOVERY.md for the diagnosis-and-recovery runbook.
tracedecay memory is stored in the per-project .tracedecay/tracedecay.db as durable, entity-linked facts:
| Tool | Purpose |
|---|---|
tracedecay_fact_store |
Store a fact with entities, source, reason, related facts, contradictions, tags, and an initial confidence signal |
tracedecay_fact_feedback |
Record user or agent feedback that raises, lowers, supersedes, or contradicts a fact's trust score |
tracedecay_memory_status |
Repair dirty memory banks, then inspect fact-store readiness, entity counts, trust-score distribution, and vector/backfill health |
Trust scoring is fact-level, not just text-level. The store combines source metadata, feedback history, retrieval counters, contradiction scans, and recency into the returned score components. Entity recall returns facts linked to the requested symbol, file, subsystem, or named concept with why metadata so agents can explain why a memory was surfaced.
See docs/USER-GUIDE.md for common memory payloads. For the exact current input schema, inspect the live MCP descriptors for tracedecay_fact_store, tracedecay_fact_feedback, and tracedecay_memory_status.
Memory hygiene is covered by a behavioral eval suite (no-pollution, secret rejection, supersede-without-dup, multi-turn continuity, curation conservatism): a deterministic layer runs in the normal test suite, and a cost-gated real-agent layer drives Hermes or cursor-agent against throwaway fixtures. See docs/memory-evals.md.
Every MCP call writes an append-only row to ~/.tracedecay/global.db (savings_ledger table). Each row records before (the indexed size of every file the response references, bytes/4, as if each had been read in full) and after (the response size, chars/4); reported savings are max(0, before - after) per call. This is an estimated upper bound: chars/4 approximates real tokenization, repeated calls re-count the same files, and an agent would not always have read every referenced file raw. The in-process lifetime counters credit the same net amount per call (full-file reads credit zero). Inspect with tracedecay gain:
tracedecay gain # current project, last 30 days
tracedecay gain --all # all projects
tracedecay gain --history --range 7d
tracedecay gain --jsonDollar estimates use the existing pricing module (Sonnet input pricing, refreshed daily via LiteLLM).
tracedecay bench runs a fixed query set through tracedecay_context and reports retrieval savings vs a full-file baseline (mirrors the CCE methodology):
tracedecay bench # ships with 10 default queries
tracedecay bench --queries my-queries.toml --json
tracedecay bench --max-nodes 5Measured against this repo (tracedecay itself) using the shipped generic query set:
| # | Query | Baseline | Context | Savings |
|---|---|---|---|---|
| 1 | How is configuration loaded at startup? | 15,475 | 460 | 97% |
| 2 | Where are command-line arguments parsed and dispatched? | 8,047 | 242 | 97% |
| 3 | How is the main entry point organized? | 11,883 | 242 | 98% |
| 4 | How are errors defined, wrapped, and propagated? | 11,883 | 270 | 98% |
| 5 | Where is logging or diagnostic output emitted? | 14,714 | 310 | 98% |
| 6 | How are tests organized and what test harness is used? | 348 | 195 | 44% |
| 7 | How is data persisted to disk or to a database? | 53,894 | 414 | 99% |
| 8 | How are async tasks or background work spawned? | 13,439 | 221 | 98% |
| 9 | How does the build wire up dependencies and initialize state? | 20,368 | 400 | 98% |
| 10 | How are public API surfaces exposed (HTTP endpoints, library exports, or CLI commands)? | 30,345 | 630 | 98% |
Aggregate: 93% mean retrieval savings (180,396 → 3,384 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 tracedecay 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 tracedecay sync --force on each repo (index_all() regardless of .tracedecay/ 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>/.tracedecay-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 tracedecay_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 TRACEDECAY_BENCH_REPOS_DIR=~/tracedecay-bench-cache
cargo bench --bench large_reposIf TRACEDECAY_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 |
|---|---|
TRACEDECAY_BENCH_REPOS_DIR |
Required. Root directory where each repo is cloned to $DIR/<repo-name>/. |
TRACEDECAY_BENCH_REPOS |
Comma-separated subset of repo names to bench, e.g. TRACEDECAY_BENCH_REPOS=emacs,scipy. Defaults to all four. |
TRACEDECAY_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/tracedecay_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 $TRACEDECAY_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 tracedecay 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:
- Regression sweep. New language support, new tool, or a refactor — re-run the matrix and any cell that newly errors, times out, or returns empty results stands out as a 🚩.
- Perf probe. Per-call timings are logged in TSV; the same fixed corpus of repos doubles as a coarse cross-version comparison. The current
tracedecay_inheritance_depthcycle 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 $TRACEDECAY_PROBE_REPOS).
Quick run:
cargo build --release --bin tracedecay
python3 scripts/mcp_probe/probe.py
python3 scripts/mcp_probe/build_matrix.py > matrix.mdOutput 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 70 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 tools also mutate local .tracedecay state and are annotated as non-read-only. The three core tools (tracedecay_context, tracedecay_search, tracedecay_status) are marked anthropic/alwaysLoad so they bypass the client's tool-search round-trip.
Large JSON MCP responses may return a valid envelope with truncated: true, a
preview, and a local response handle. Prefer narrowing the original query
first when that answers the task. If the omitted details are needed, call
tracedecay_retrieve with the required handle argument from the envelope; this
returns the exact cached original response without re-running the source tool.
Handles are stored locally under the project .tracedecay/ directory, expire
automatically after their TTL, and cache the response text in plaintext.
| Tool | Purpose |
|---|---|
tracedecay_context |
Get relevant code context for a task -- entry points, related symbols, code snippets |
tracedecay_search |
Find symbols by name (functions, classes, types) |
tracedecay_node |
Get details + source code for a specific symbol |
tracedecay_files |
List indexed project files with filtering |
tracedecay_module_api |
Public API surface of a file or directory |
tracedecay_similar |
Find symbols with similar names |
tracedecay_status |
Index status, statistics, tokens saved |
| Tool | Purpose |
|---|---|
tracedecay_callers |
Find what calls a function |
tracedecay_callees |
Find what a function calls |
tracedecay_impact |
See what's affected by changing a symbol |
tracedecay_affected |
Find test files affected by source changes |
tracedecay_rename_preview |
All references to a symbol (preview rename impact) |
tracedecay_hotspots |
Most connected symbols (highest call count) |
| Tool | Purpose |
|---|---|
tracedecay_complexity |
Rank functions by cyclomatic complexity, nesting depth, safety metrics |
tracedecay_dead_code |
Find unreachable symbols (no incoming edges) |
tracedecay_god_class |
Find classes with too many members |
tracedecay_coupling |
Rank files by fan-in/fan-out |
tracedecay_inheritance_depth |
Find the deepest inheritance hierarchies |
tracedecay_circular |
Detect circular file dependencies |
tracedecay_recursion |
Detect recursive/mutually-recursive call cycles |
tracedecay_unused_imports |
Import statements never referenced |
tracedecay_doc_coverage |
Public symbols missing documentation |
tracedecay_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 |
|---|---|
tracedecay_health |
Composite quality signal (0-10000) from acyclicity, depth, equality, redundancy, and modularity |
tracedecay_gini |
Gini inequality coefficient for any metric (complexity, lines, fan-in/out, members) -- finds god files and uneven distribution |
tracedecay_dependency_depth |
Longest file-level dependency chains (Lakos levelization) with full chain reconstruction after Tarjan SCC cycle-breaking |
tracedecay_dsm |
Design Structure Matrix in stats, clusters, or matrix form -- reveals layering violations and hidden coupling |
tracedecay_test_risk |
Risk-weighted test-gap analysis combining complexity, fan-in, static test attribution (direct vs. depth-3 closure), and 90-day git churn into a single score. coverage_pct is a static attribution lower bound, not executed coverage |
Snapshot health metrics at the start of an AI coding session, then diff at the end to see what improved or regressed.
| Tool | Purpose |
|---|---|
tracedecay_session_start |
Save current health metrics as a JSON baseline for later comparison |
tracedecay_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 |
|---|---|
tracedecay_str_replace |
Replace a unique old_str with new_str; fails if 0 or >1 matches (protects against multi-edit bugs) |
tracedecay_multi_str_replace |
Apply N (old, new) replacements atomically -- all-or-nothing transaction |
tracedecay_insert_at |
Insert content before or after a unique anchor string or line number |
tracedecay_ast_grep_rewrite |
Structural code rewrite via the ast-grep CLI in --rewrite mode |
| Tool | Purpose |
|---|---|
tracedecay_diff_context |
Semantic context for changed files -- modified symbols, dependencies, affected tests |
tracedecay_commit_context |
Semantic summary of uncommitted changes for commit message drafting |
tracedecay_pr_context |
Semantic diff between git refs for pull request descriptions |
tracedecay_changelog |
Semantic diff between two git refs |
tracedecay_test_map |
Source-to-test mapping at the symbol level, with uncovered symbol detection |
| Tool | Purpose |
|---|---|
tracedecay_type_hierarchy |
Recursive type hierarchy tree for traits, interfaces, and classes |
tracedecay_rank |
Rank nodes by relationship count (most implemented interface, most extended class) |
tracedecay_distribution |
Node kind breakdown per file or directory |
tracedecay_largest |
Rank nodes by size -- largest classes, longest methods |
| Tool | Purpose |
|---|---|
tracedecay_port_status |
Compare symbols between source/target directories to track porting progress |
tracedecay_port_order |
Topological sort of symbols for porting -- port leaves first, then dependents |
| Tool | Purpose |
|---|---|
tracedecay_branch_search |
Search symbols in another branch's graph |
tracedecay_branch_diff |
Compare symbols between branches (added/removed/changed) |
tracedecay_branch_list |
List tracked branches with DB sizes and sync times |
Four resources are exposed via resources/list and resources/read:
tracedecay://status-- graph statistics as JSONtracedecay://files-- indexed file tree grouped by directorytracedecay://overview-- project summary with language distribution and symbol kindstracedecay://branches-- tracked branches with DB sizes and parent info
tracedecay measures the tokens it saves on every MCP tool call. Each tool response includes a tracedecay_metrics: before=N after=M line showing how many raw-file tokens were avoided by that specific call.
tracedecay cost # 7-day cost summary (default)
tracedecay cost today # today only
tracedecay cost --by-model # breakdown by Claude model
tracedecay cost --by-task # breakdown by task category (coding, debugging, exploration, ...)
tracedecay cost --export json # JSON export to stdout
tracedecay cost --export csv # CSV export to stdoutParses 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 ~/.tracedecay/global.db for fast aggregate queries. Pricing is refreshed from LiteLLM every 24 hours and falls back to an embedded table when offline.
The tracedecay status header includes a cost row showing today's spend, 7-day total, and efficiency ratio (tokens saved / total tokens). The tracedecay 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.
tracedecay monitorA global TUI that shows MCP tool calls from all projects in real time, via a shared memory-mapped ring buffer at ~/.tracedecay/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).
tracedecay current-counter # show per-project session counter
tracedecay reset-counter # reset the session counter
tracedecay status # shows project + global lifetime totals + costAll tracedecay users contribute to an anonymous aggregate counter. tracedecay 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 tracedecay disable-upload-counter.
tracedecay 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. tracedecay 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 tracedecay commands without an attached agent (no MCP server), the staleness check is not running between commands. Install a git post-commit hook to keep the index fresh automatically after every commit:
cp scripts/post-commit .git/hooks/post-commit
chmod +x .git/hooks/post-commitThe standalone tokensave daemon command (5.x-era, pre-rename) 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.0 (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 (the artifacts use the historical tokensave name):
- macOS:
launchctl unload ~/Library/LaunchAgents/com.tokensave.daemon.plist && rm ~/Library/LaunchAgents/com.tokensave.daemon.plist - Linux:
systemctl --user disable --now tokensave-daemon && rm ~/.config/systemd/user/tokensave-daemon.service - 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.
tracedecay upgrade # upgrade to latest in current channel
tracedecay channel # show current channel (stable/beta)
tracedecay channel beta # switch to beta channel
tracedecay channel stable # switch back to stabletracedecay upgrade downloads the correct platform binary from GitHub releases and replaces the running binary in place. Supports stable and beta channels independently.
tracedecay init [path] # Initialize a new project (full index)
tracedecay sync [path] # Incremental sync (must be initialized first)
tracedecay sync --force [path] # Force a full re-index
tracedecay sync --doctor [path] # Sync and list added/modified/removed files
tracedecay status [path] # Show statistics + cost summary
tracedecay status [path] --json # Show statistics (JSON output)
tracedecay status --details # Include node-kind breakdown
tracedecay dashboard # Start local web dashboard (default port 7341)
tracedecay dashboard --port 8080 # Start dashboard on custom port
tracedecay dashboard --port 0 # Auto-select a free port
tracedecay dashboard --open # Open the URL in the default browser
tracedecay cost [range] # Token cost summary (default: 7d)
tracedecay cost --by-model # Cost grouped by model
tracedecay cost --by-task # Cost grouped by task category
tracedecay cost --export json|csv # Export cost data
tracedecay query <search> [path] # Search symbols
tracedecay files [--filter dir] [--pattern glob] [--json] # List indexed files
tracedecay affected <files...> [--stdin] [--depth N] # Find affected test files
tracedecay install [--agent NAME] # Configure agent integration
tracedecay reinstall # Refresh settings for all installed agents
tracedecay update-plugin # Refresh generated plugin code/assets only; never writes agent configs
tracedecay uninstall [--agent NAME] [--profile NAME] # Remove agent integration
tracedecay serve # Start MCP server
tracedecay monitor # Live TUI showing MCP calls across all projects
tracedecay upgrade # Self-update to latest version
tracedecay channel [stable|beta] # Show or switch update channel
tracedecay doctor [--agent NAME] # Check installation health
tracedecay branch add|list|remove|removeall|gc # Multi-branch management
tracedecay current-counter # Show per-project token counter
tracedecay reset-counter # Reset per-project token counter
tracedecay disable-upload-counter # Opt out of worldwide counter uploads
tracedecay enable-upload-counter # Re-enable worldwide counter uploadsRun a comprehensive health check of your tracedecay installation:
tracedecay doctorChecks: 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 tracedecay install. Use --agent to check a specific agent only.
Doctor also validates that each installed hook uses the correct tracedecay subcommand and auto-repairs broken hooks.
Once configured, Claude Code automatically uses tracedecay 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 70+ tracedecay_* tools to Claude |
Claude can query the graph directly |
| CLAUDE.md rules | Tells Claude to prefer tracedecay 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; tracedecay returns the relevant symbols, relationships, and code snippets from its pre-built index.
tracedecay'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 | tracedecay 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) | tracedecay 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 tracedecay cost. No data is sent -- it is a plain HTTPS GET. The response is cached at ~/.tracedecay/pricing.json for 24 hours. If the fetch fails, tracedecay uses its compiled-in pricing table.
tracedecay 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.
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 |
| 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 |
| Language | Extensions | Feature flag |
|---|---|---|
| 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 |
| WGSL | .wgsl |
lang-wgsl |
| HLSL | .hlsl, .fx |
lang-hlsl |
| Metal | .metal |
lang-metal |
| 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 |
| Quint | .qnt |
lang-quint |
| TOML | .toml |
lang-toml |
| Lean | .lean |
lang-lean |
Individual languages can also be cherry-picked without a full tier:
cargo install tracedecay --no-default-features --features lang-nix,lang-bashAll 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.
tracedecay 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.
| tracedecay | CodeGraph | |
|---|---|---|
| Runtime | Native binary (Rust) | Node.js 18+ |
| Install | brew install, cargo install, scoop install |
npx @colbymchenry/codegraph |
| Languages | 50+ (3 tiers: lite/medium/full) | 19+ |
| MCP tools | 70+ | 9 |
| Agent integrations | 12+ (Claude, Codex, Gemini, OpenCode, Cursor, Cline, Copilot, Roo Code, Zed, Antigravity, Kilo, Kiro, Kimi, Vibe) | 1 (Claude Code) |
| Index freshness | On-demand staleness check on every MCP call; catch-up sync on connect; multi-agent work expected to use git worktrees | Native OS-level file watcher (FSEvents/inotify/ReadDirectoryChangesW, 2 s debounce); catch-up sync on connect |
| Multi-branch indexing | Yes, opt-in (per-branch DBs, cross-branch diff/search) | No |
| Complexity metrics | AST-extracted (branches, loops, nesting depth, cyclomatic) | No |
| Porting tools | Yes (port_status, port_order) |
No |
| Graph visualizer | Removed (v4.0.1) | Yes |
| Semantic search | Agent-driven keyword expansion (zero-cost) | Local embeddings (nomic-embed-text-v1.5 via ONNX) |
| MCP resources | 4 (status, files, overview, branches) | No |
| MCP annotations | Yes (readOnlyHint, alwaysLoad) | No |
| Dead code detection | Yes | No |
| Circular dependency detection | Yes | No |
| Type hierarchy | Yes | No |
| God class / coupling analysis | Yes | No |
| Commit / PR context | Yes | No |
| Test mapping | Yes | No |
| Rename preview | Yes | No |
| Token tracking | Per-call metrics, live TUI monitor, session + lifetime counters | No |
| Code-health analytics | Composite score, Gini, dependency depth, DSM, risk-weighted test gaps, session deltas | No |
| Edit primitives | 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 | tracedecay 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 (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. tracedecay 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 tracedecay stands apart.
Every alternative requires a runtime: Python, Node.js, or both. tracedecay ships as a single ~25 MB Rust binary with all 50+ tree-sitter grammars bundled. Nothing else to install.
tracedecay 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?" tracedecay's 70+ 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 competitor (code-review-graph) has 22 tools; others have 5-9.
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, tracedecay.md steering loaded as a resource, a managed agent with permissive built-in/tracedecay tool approval, and hooks for delegation guardrails plus post-write sync. Other agents get MCP server registration in their native config format.
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.
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.
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.
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 |
| tracedecay (Rust) | 1.2s | 26x |
The .tracedecay/ directory doesn't exist in your project (a legacy .tokensave/ directory would also be picked up).
tracedecay initThe AI agent doesn't see tracedecay tools.
- Ensure the agent config includes the tracedecay MCP server (run
tracedecay doctor) - Restart the agent completely
- Check that
tracedecayis in your PATH:which tracedecay
- Run
tracedecay syncto update the index - Check that the language is supported (see table above)
- Verify the file isn't excluded by
.gitignore
Large projects take longer on the first full index.
- Subsequent runs use incremental sync and are much faster
- Use
tracedecay sync(not--force) for day-to-day updates - Staleness is checked automatically on every MCP tool call while an agent is connected
| Variable | Effect |
|---|---|
TRACEDECAY_GLOBAL_DB |
Override the path to the global database (used for LCM session storage selection). When set, the dashboard serves this store instead of the project-local sessions.db. |
TRACEDECAY_BIN |
Path to the tracedecay binary (used by Hermes wrapper for spawn mode). |
TRACEDECAY_DASHBOARD_PROJECT |
Project root path for Hermes dashboard spawn mode (defaults to Hermes' cwd). |
TRACEDECAY_DASHBOARD_URL |
Full URL to an already-running dashboard (Hermes external URL mode). |
HERMES_HOME |
Path to Hermes profile directory for profile-scoped plugin installation. |
TRACEDECAY_OFFLINE |
Set to 1 to skip network requests for pricing data (Savings & Cost tab uses bundled fallback). |
DISABLE_TRACEDECAY |
Set to true to disable the MCP server entirely (exits cleanly without initializing). |
Legacy TOKENSAVE_* environment variables (and DISABLE_TOKENSAVE) from before the rename are still honored as a fallback; the TRACEDECAY_* names take precedence when both are set.
If a project is too large and tracedecay uses too much RAM, you can disable it per-project by setting DISABLE_TRACEDECAY=true in the MCP server environment. The server exits cleanly without initializing.
Claude Code — add to your project's .claude/settings.json:
{
"mcpServers": {
"tracedecay": {
"command": "tracedecay",
"args": ["serve"],
"env": {
"DISABLE_TRACEDECAY": "true"
}
}
}
}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 (DISABLE_TRACEDECAY=true claude), but this disables tracedecay for every project in the session.
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.
cargo build --release # full (50+ languages, default)
cargo build --release --features medium # medium tier
cargo build --release --no-default-features # lite (smallest binary)
cargo test # run all tests (requires full)
cargo check --no-default-features # verify lite compiles
cargo clippy --allWindows builds are code-signed with a free Authenticode certificate generously provided by SignPath.io, with a certificate issued by the SignPath Foundation.
MIT License -- see LICENSE for details.
