Skip to content

v6.1.0

Choose a tag to compare

@aovestdipaperino aovestdipaperino released this 25 May 13:59
· 128 commits to master since this release

[6.1.0] - 2026-05-25

Added

  • tokensave tool <name> — schema-driven CLI dispatcher. Every MCP tool is now reachable from the command line through a single dynamic subcommand that introspects each tool's JSON schema and coerces --key value flags accordingly. tokensave tool (no args) lists tools grouped by category; tokensave tool <name> --help prints schema-derived parameters. Reserved flags: --json (raw response), --project <path>, --args <json>, -h/--help. Positional args bind to required string properties (e.g. tokensave tool search foo). @file values are read from disk for multi-line strings. Replaces seven hand-rolled subcommands (query, context, body, impact, callers, files, affected); query is kept as an alias for the renamed search. New file: src/tool_command.rs (~729 LoC).
  • tokensave_find_exact_symbol MCP tool. Bare-name lookup against idx_nodes_name — a single O(log n) index probe with no BM25 ranking, no fuzzy match, no qualified-name suffix walk. Use this when the symbol name is already known; use tokensave_search for relevance-ranked discovery. ~30–200 µs per lookup vs. ~700 µs for the BM25 path.
  • tokensave_call_chain MCP tool. Finds the shortest directed call chain between two node IDs along outgoing calls edges only. New find_path_directed BFS in graph/traversal.rs (the existing find_path is bidirectional and wrong for "how does A reach B" questions). Bounded by max_depth (default 8, max 20).
  • tokensave_file_dependents MCP tool. Lists every indexed file that imports or otherwise depends on the given file. Thin wrapper around the existing TokenSave::get_file_dependents that was previously only reachable through tokensave_affected's test-rollup path.
  • tokensave_replace_symbol MCP tool. Symbol-aware body replacement: resolves a name via exact qualified-name match, narrows to callable kinds on ambiguity, and refuses the edit rather than picking the wrong site if more than one callable matches. Reads the file, splices the symbol's start_line..=end_line range with new_source, writes back, and reindexes the touched file. Plays the role of token-savior's replace_symbol_source.
  • tokensave_insert_at_symbol MCP tool. Inserts content immediately before or after a named symbol's source range — same resolution semantics as tokensave_replace_symbol. position is "before" or "after" (default after). Plays the role of token-savior's insert_near_symbol.
  • tokensave serve --timings flag. When set, every tools/call response gains a _meta.duration_us field reporting the handler's pure execution time in microseconds. Lets clients (and benchmarks) attribute latency to actual query work vs. JSON-RPC / stdio / Python-parse overhead. Toggleable at runtime through the new McpServer::set_timings_enabled setter so embedders can flip it per-session.
  • Indexer benchmark harness at benchmarks/run_benchmarks.py — adapts Mibayy/token-savior's run_benchmarks.py to drive both tools side-by-side on the same clone of FastAPI, sharing a random symbol sample (seed=42) so per-query rows are directly comparable. tokensave is driven through a long-lived tokensave serve --timings MCP session for the query column. Latest report (benchmarks/comparison-report.md): cold index 2.9× faster, impact analysis 43× faster than token-savior.
  • tsbench fork at benchmarks/tsbench/ — patch + reproduction README + per-run summary for running Mibayy/tsbench (token-savior's own 96-task agent benchmark) against tokensave. First-attempt untuned result: 184/192 = 95.8% vs. token-savior's audited 97.9%. The harness rewrites SYSTEM_PROMPT_TS to map each token-savior tool to its tokensave equivalent and relaxes the --disallowedTools list to allow Read/Edit fallback on the four task categories tokensave has no direct tool for.
  • docs/TOKENSAVE-VS-TOKENSAVIOR.md — full capability + performance comparison document covering parsing strategy (regex annotators vs. tree-sitter grammars), the 11 health-analytics tools that have no token-savior equivalent, query-latency numbers (apples-to-apples find / body / impact), the tsbench 184/192 result with per-task failure analysis, and an honest "when to use which" guide.

Fixed

  • tokensave serve no longer blocks MCP initialize on the watcher's filesystem walk (#84). Constructing the embedded notify_debouncer_full watcher does a synchronous walkdir over every registered subtree to seed its file-id map. On a large JS/TS monorepo with multi-gigabyte node_modules / .next / dist trees this can take 30+ seconds — long enough to blow the client's initialize timeout. Fix: ProjectWatcher::new now runs inside tokio::task::spawn_blocking from a detached tokio::spawn, so McpServer::new returns immediately and the MCP stdio loop can answer initialize / tools/list in milliseconds. The CancellationToken is stored on the server up front so shutdown can cancel mid-walk if the agent disconnects before the watcher finishes initialising. Reported by @ottob with a sample-trace and an FSEvents-sandbox repro that left zero ambiguity about root cause.
  • tokensave serve no longer runs pre-serve maintenance work (#84). Commands::Serve was running try_flush (synchronous HTTP round-trip to the worldwide counter), check_install_stale, and the silent-reinstall loop over every tracked agent before the MCP stdio loop even started. All three are now gated behind should_skip_agent_install_maintenance, alongside Install / Reinstall / Uninstall / Doctor. Same maintenance still runs on the user's next interactive tokensave … invocation.
  • tokensave install --agent antigravity now registers in both the IDE config and the CLI plugin directory (#85). Previously only ~/.gemini/antigravity/mcp_config.json was written, leaving the Antigravity CLI (agy) unable to see tokensave in /mcp. New: also writes ~/.gemini/antigravity-cli/plugins/tokensave.json with the same {"mcpServers": {"tokensave": {...}}} shape. uninstall removes both, doctor reports both, is_detected triggers on either path. Reported by @ottob.
  • MCP last synced N ago warning no longer fires after a no-change sync (#86). The warning was reading MAX(files.indexed_at), which only advances when a file is actually reindexed. On quiet repos a successful tokensave sync (0 added / 0 modified / 0 removed) left indexed_at stuck and the warning fired forever. New: the warning is computed from the last_sync_at metadata key, which sync() writes unconditionally on every successful invocation. Falls back to MAX(indexed_at) only when the metadata key is missing (e.g. a freshly-initialised project that has never been synced). New TokenSave::last_sync_timestamp() helper exposes this for embedders. Reported by @uwe-sure.
  • files_by_language status output now uses real language names instead of bucketing everything as Other. The SQL CASE in Database::get_stats only recognised four languages (Rust / Go / Java / Scala) and dumped everything else — Python, TypeScript, C, Swift, Kotlin, etc. — into "Other". Replaced with a Rust-side bucketing helper covering 46 extractor languages; Python files in the FastAPI benchmark now correctly report as Python instead of Other. Includes special-case basename matching for extensionless Dockerfile / Makefile.
  • Pre-existing breakage in tests/mcp_server_test.rs repaired. The whole test-transport-gated integration suite (31 tests) had been silently failing to compile since McpServer::new switched its return type to Arc<McpServer>setup_server and run_server_with_messages still expected bare McpServer. Switched both helpers to Arc<McpServer> and bumped the resource-count assertion (tokensave://status/files/overview/branches) from 4 to 5 to include the newer tokensave://schema resource. All 31 tests now pass.

Changed

  • Seven hand-rolled CLI subcommands replaced by the unified tokensave tool <name> dispatcher. query, context, body, impact, callers, files, affected were each ~50–150 LoC of clap glue duplicating what the MCP tool already declares in its schema. All seven are gone; the same operations are reached as tokensave tool query …, tokensave tool body …, etc. Drops ~600 LoC of dispatch boilerplate from src/main.rs. query is kept as an alias for the renamed search so muscle memory still works.

Internal

  • New methods on TokenSave: get_call_chain, get_nodes_by_name, replace_symbol, insert_at_symbol, plus a private resolve_symbol_for_edit helper that does qname-first resolution and refuses ambiguous matches rather than silently picking the wrong site.
  • New method on GraphTraverser: find_path_directed (BFS that follows outgoing edges only, with max_depth bound).
  • McpServer now has a timings_enabled: AtomicBool field with set_timings_enabled / timings_enabled accessors, toggleable per-session.
  • The dispatcher in mcp/tools/handlers/mod.rs wraps each handle_tool_call invocation with Instant::now() when timings_enabled is set and injects _meta.duration_us into the JSON-RPC result.