关于 TokenSave
TokenSave 是面向编码 Agent 的本地语义代码索引和 MCP 服务。Agent 可查询代码图中的符号、关系、源码片段及代码健康信息,减少反复扫描文件的需要。
主要功能
- 01对已索引代码进行语义搜索
- 02查询代码图中的符号与关系
- 03分析代码修改影响
- 04支持 50 多种语言
- 05本地增量索引与同步
- 06提供原子化代码编辑工具
适用场景
- 01按概念查找相关代码
- 02修改符号前追踪调用关系
- 03检查代码变更的潜在影响
- 04项目变化时更新代码索引
MCP 相关
TokenSave 通过 MCP 工具向编码 Agent 提供代码图查询、分析和编辑能力。其安装命令可将服务注册到受支持的 Agent 客户端。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
为 AI 编码 Agent 提供语义代码智能
更少的 Token • 更少的工具调用 • 100% 本地运行
Beta 版现已推出: 在 beta 分支试用全新改进的查询功能,包括优化的搜索排序、图分析和索引清理。详情请参阅 Beta 变更日志。
从源代码安装:
cargo install --git https://github.com/aovestdipaperino/tokensave.git --branch beta --locked --force
目录
- 为什么选择 tokensave?
- 主要功能
- 快速开始
- 抗崩溃同步
- 多分支索引(可选)
- 跨会话记忆
- 节省记录
- 可复现的基准测试
- 80 多种 MCP 工具
- Token 跟踪
- 索引时效性
- 自行升级
- 版本管理与升级
- CLI 参考
- tokensave doctor
- 与 Claude Code 配合使用的方式
- 网络调用与隐私
- 50 多种语言
- tokensave 与 CodeGraph 对比
- tokensave 相较其他方案的优势
- 故障排除
- 起源
- 构建
- Star 历史
- 赞助商
- 许可证
为什么选择 tokensave?
AI 编码 Agent 会浪费 Token 来探索代码库。每次 grep、glob 和文件读取都会产生费用。面对复杂任务时,Agent 会启动多个 Explore 子 Agent,扫描数百个文件,只为构建上下文。
tokensave 为 Agent 提供预先索引的语义知识图谱。 Agent 无需扫描文件,只需查询图谱,就能立即获得结构化答案——包括相关符号、符号之间的关系以及源代码,一次调用即可获取。
工作原理
flowchart TB
subgraph agent["AI Coding Agent (Claude Code, Codex, Gemini, Cursor, ...)"]
task["Implement user authentication"]
first["Sub-agent"]
second["Sub-agent"]
task --> first
task --> second
first --- second
end
subgraph server["tokensave MCP Server"]
search["Search: auth"]
callers["Callers: login()"]
context["Context for task"]
db[("libSQL Graph DB<br/>Instant lookups<br/>FTS5 search")]
search --> db
callers --> db
context --> db
end
first --> search
first --> callers
second --> context
不使用 tokensave: Agent 使用 grep、glob 和 Read 扫描文件——API 调用次数多,Token 消耗高。
使用 tokensave: Agent 通过 MCP 工具查询图谱——结果即时返回,在本地处理,Token 消耗更少。
核心功能
| 智能上下文构建 | 语义搜索 | 影响分析 |
| 一次工具调用即可返回 Agent 所需的一切——入口点、相关符号和代码片段。 | 按含义查找代码,而不只是匹配文本。搜索“身份验证”即可找到 login、validateToken、AuthService。 | 更改前准确了解哪些内容会受到影响。追踪任意符号的调用方、被调用方和完整影响范围。 |
| 80 多种 MCP 工具 | 50 多种语言 | 12 种以上 Agent 集成 |
| 功能涵盖调用图遍历、死代码检测、原子编辑原语、代码健康度指标、测试映射和复杂度分析。 | Rust、Go、Java、Python、TypeScript、C、C++、Swift、Svelte、Astro 等,以及另外 43 种语言,包括 WGSL/HLSL/Metal 着色器、CUDA/HIP 和 Markdown。三个档位(lite/medium/full)可控制二进制文件大小。 | 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。 |
| 多分支索引(可选启用) | 100% 本地运行 | 始终保持最新 |
| 可选的分支专属数据库。无需切换当前检出分支,即可跨分支比较差异和搜索。 | 数据不会离开你的设备。无需 API 密钥。无需外部服务。一切都运行在本地 libSQL 数据库上。 | 每次 MCP 调用都会按需检查数据是否过时(冷却时间为 30 s),并在服务连接时进行追赶式同步。多 Agent 协作预计使用 git worktrees——每个 Agent 都有自己的检出目录,索引分歧由 git 合并,而非文件监视器。 |
| 子进程隔离提取 | 代码健康度分析 | 原子编辑原语 |
| 任意 tree-sitter 语法发生原生崩溃(abort、segfault 或其他情况)时,只会终止工作进程;进程池会重新生成该进程,同步继续进行。即使文件格式错误,同步也不会中断。 | 综合健康度评分(0-10000)、基尼不平等指数、文件 DAG 深度、设计结构矩阵、按风险加权的测试缺口,以及会话增量。 | 无需担心正则表达式或 shell 引号问题即可编辑文件:唯一锚点 str_replace、原子多重替换、AST 重写、锚定插入。写入后自动重新索引。 |
快速开始
1. 安装
选择一种安装方式:
| 平台 | 命令 |
|---|---|
| macOS(Homebrew) | brew install aovestdipaperino/tap/tokensave |
| 任何安装了 Rust 的平台 | cargo install tokensave |
| 任何安装了 cargo-binstall 的平台 | cargo binstall tokensave |
在 Windows 上使用 Scoop:
scoop bucket add tokensave https://github.com/aovestdipaperino/scoop-bucket
scoop install tokensave
你也可以下载预构建二进制文件,并将其添加到你的 PATH。
其他安装方式和语言档位
默认的 Cargo 构建包含所有受支持的语言。若要构建更小的版本:
cargo install tokensave --no-default-features --features medium
cargo install tokensave --no-default-features # lite (smallest binary)
预构建发布压缩包:
| 平台 | 压缩包 |
|---|---|
| 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 |
运行设置命令,自动检测已安装的 Agent:
tokensave install
若要选择 Agent,请使用 --agent(例如 codex、claude 或 cursor):
tokensave install --agent codex
支持的 Agent(使用 --agent 指定标识符):
| Agent | 标识符 |
|---|---|
| Antigravity | antigravity |
| AugmentCode | auggie |
| Claude Code | claude |
| Cline | cline |
| Codex CLI | codex |
| GitHub Copilot | copilot |
| Cursor | cursor |
| Factory Droid | droid |
| Gemini CLI | gemini |
| Grok Build | grok |
| Kilo CLI | kilo |
| Kimi CLI | kimi |
| Kiro | kiro |
| Oh My Pi (OMP) | omp |
| OpenCode | opencode |
| Pi | pi |
| Plank(仅限 macOS) | plank |
| Qwen Code | qwen |
| Roo Code | roo-code |
| Mistral Vibe | vibe |
| Zed | zed |
设置过程会注册 MCP 服务和 Agent 集成,还会提供全局 Git 钩子,以确保已初始化的项目保持最新。升级后可以放心再次运行设置。
多个 Agent、项目本地设置和集成详情
每个 Agent 都会以其原生配置格式注册 MCP 服务。此外,Claude Code 还会获得一个 PreToolUse 钩子(用于阻止浪费资源的 Explore Agent)、一个 UserPromptSubmit 钩子、一个 Stop 钩子、写入 CLAUDE.md 的提示词规则,以及自动允许的工具权限。Pi 会在其 MCP 配置项中设置 "exposure": "direct"——Pi 默认会将服务设为 codemode,这不会向模型声明任何工具——还会在 AGENTS.md 中写入提示词规则,并安装一个受管理的 TypeScript 扩展,提供相同的防护措施、节省量重置和会话回执,因为 Pi 没有 shell 钩子。Kiro 会获得全局 MCP 配置、作为资源加载的 tokensave.md 引导文件,以及由 tokensave 管理的默认 Agent,该 Agent 具有宽松的内置工具和 tokensave 工具审批、委派防护钩子和写入后同步;用户管理的 Kiro Agent 会保留不变。
全局 OMP 安装会以直接运行 omp config path 得到的配置文件为目标,将文件写入 <resolved-agent-dir>/mcp.json 和 <resolved-agent-dir>/rules/tokensave.md。安装到指定配置文件时,请导出 OMP_PROFILE 或与 OMP 兼容的 PI_PROFILE;OMP 的解析器还会遵循 PI_CONFIG_DIR 和 PI_CODING_AGENT_DIR。Tokensave 会信任原生解析器,而不会重复实现 OMP 的配置文件逻辑。Tokensave 会为 OMP 安装 MCP 和建议性规则,但不会安装 OMP 钩子强制机制。
所有更改均为幂等操作,升级后可以安全地再次运行。设置好 Agent 后,系统会询问是否安装全局 Git post-commit 和 post-checkout 钩子。tokensave uninstall 会移除这些钩子和 Agent 集成;传入 --keep-git-hooks 可保留钩子,也可以使用 tokensave githooks 单独管理它们。
同时为多个 Agent 安装
重复使用 --agent,即可在一次运行中为多个 Agent 安装。无论列出多少个 Agent,权限授予、Git 钩子提示和全局配置写入操作都只会各执行一次:
tokensave install --agent claude --agent cursor --agent droid
默认情况下,tokensave install 会将 MCP 服务注册到你的全局 Agent 配置中(例如 ~/.claude.json)。若要仅为当前项目注册 tokensave,请添加 --local:
tokensave install --local --agent claude
tokensave install --local --agent omp
这会写入项目级配置,你可以将其提交并与团队共享。对于 Claude,配置文件为 ./.mcp.json、./.claude/settings.json 和 ./CLAUDE.md;对于 OMP,则使用 ./.omp/mcp.json 和 ./.omp/rules/tokensave.md,且不会调用 OMP CLI。支持的 Agent:claude、cursor、droid、gemini、zed、opencode、roo-code、kiro、auggie、omp、plank、pi(每种 Agent 都会写入自己的项目文件,例如 .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、plank 使用的 .mcp.json,以及 pi 使用的 .pi/mcp.json 和 ./AGENTS.md)。其他 Agent 没有项目级配置,使用 --local 时会报错。
使用 tokensave uninstall --local 移除项目级安装。
若要在不显示提示的情况下接受或跳过 Git 钩子,请添加 --git-hook yes 或 --git-hook no。使用 tokensave githooks 查看钩子,或使用 tokensave githooks off 将其移除。
Agent 专属说明请参阅连接到你的 Agent。
3. 为项目建立索引
cd /path/to/your/project
tokensave init
这会创建一个包含知识图谱数据库的 .tokensave/ 目录。初始化和同步是独立的命令:init 是每个项目仅需执行一次的主动选择,而 sync 只会更新已初始化的项目。这可以防止全局 Git 钩子在你无意建立索引的仓库中悄悄创建数据库。执行 init 后,使用 tokensave sync 增量更新——仅重新索引已更改的文件。
从子目录运行
每个命令都会向上查找最近的 .tokensave/,以确定当前目录所属的项目,因此你可以在项目内的任意位置运行命令:
cd repository
tokensave init # creates repository/.tokensave/
cd src/backend/services
tokensave tool search database # searches the repository's index
tokensave init # reports the existing project; exits 0, indexes nothing
cd ../..
tokensave sync # syncs the repository's index
MCP 服务和 Agent 钩子也会以相同方式解析项目。搜索路径相对于项目根目录(src/backend/db.rs)。请注意,从子目录启动的 MCP 服务仍会将该子目录用作列表工具的默认路径筛选条件。
- Git 仓库。 如果项目尚不存在,在 Git 仓库内执行
init会初始化仓库根目录(或关联工作树根目录),而不是当前目录。 - 仓库边界。 Git 仓库根目录是隔离边界。在嵌套的独立仓库(嵌套克隆或子模块)内,命令绝不会使用外层仓库的索引;请在那里运行
tokensave init,为其创建自己的索引。嵌套在主检出目录中的关联工作树仍会借用主索引,并会显示相应的借用工作树提示。 - 非 Git 项目。 位于 Git 仓库之外的文件夹中的
.tokensave/也以相同方式工作,包括该文件夹内的任何仓库。 - 显式根目录。
tokensave init <path>、--path(-p)和tool --project <path>会使用你传入的目录,不进行查找。 - 损坏的安装。 如果
.tokensave/中有config.json却没有数据库,系统会报告此情况,而不会跳过它并改用外层项目。无法解析的配置会报错,并指出需要修复的文件。
Claude Code 安装时写入的内容
MCP 服务
{
"mcpServers": {
"tokensave": {
"command": "/path/to/tokensave",
"args": ["serve"]
}
}
}
PreToolUse 钩子
该钩子运行 tokensave hook-pre-tool-use——这是一个原生 Rust 命令(无需 bash 或 jq)。它会拦截 Agent、Grep、Glob 和 Bash 工具调用:Explore Agent 会被直接阻止;符号形式的 grep/rg/ag 调用(普通标识符、交替项、用 \b 包裹的名称)会被重定向到相应的 tokensave MCP 工具;针对代码扩展名的路径形式发现(Glob、find -name、fd --extension)会被重定向到 tokensave_files。正则表达式模式、git grep、管道命令、非代码扩展名、索引范围外的搜索根目录,以及会改变命令行为的 find 谓词(-exec、-delete、-mtime)均会原样执行;设置 TOKENSAVE_DISABLE_GREP_HOOK=1 可在每个 shell 中选择退出。
筛选条件按具体程度从高到低读取:显式指定的 type 优先,其次是显式文件 glob,最后是搜索路径。因此,像 path: "." 搭配 glob: "**/*.md" 这样的文档搜索会原样执行,而不会因路径范围较广被当作代码搜索;即使路径不是代码路径,仅含代码的 glob(**/*.rs)仍会被重定向。混合 glob(**/*.{rs,md})会原样执行,因为它们可能返回文档。
**无头 / 子 Agent 调度(claude -p)。**由编排会话调度的子进程会继承其 ~/.claude/settings.json,包括此钩子。若要让子进程执行原始搜索,请在子进程的环境中设置 TOKENSAVE_DISABLE_GREP_HOOK=1——原生二进制会遵循该设置,并让所有路径(Grep、Glob、Bash、Agent)原样执行,因此无需使用会移除所有钩子的粗暴方法 --settings '{"hooks": {}}'。此防护机制无状态:它不会查询引用历史,因此只会重定向上述符号形式的搜索,并引导未指定类型的研究任务分发;无论会话是交互式还是无头模式,普通命令都不受影响。
CLAUDE.md 规则
向 ~/.claude/CLAUDE.md 追加指令,告知 Claude 在使用 Explore Agent 或直接读取原始文件之前,先使用 tokensave 工具。
抗崩溃同步
Tree-sitter 语法是编译后的 C/C++ 代码。它们偶尔会触发内部断言,或因 Rust panic 处理无法拦截的路径而终止进程。从 v4.3.0 开始,每个文件都会在短生命周期的工作进程子进程中解析:如果语法解析器发生段错误、调用 abort() 或栈溢出,只有工作进程会退出。进程池会重新启动该进程,记录并跳过出问题的文件,sync 会继续运行。
工作进程是隐藏的 extract-worker 子命令,通过每次启动时生成的 256 位令牌向父进程进行身份验证;该令牌必须同时作为 TOKENSAVE_WORKER_TOKEN 环境变量,以及 stdin 收到的前 32 个字节提供。用户直接调用会失败。工作进程的并发数由 .tokensave/config.json 中的 cpu_usage 控制:low 使用一个工作进程,balanced(默认值)使用可用 CPU 数量的一半并向上取整,performance 使用所有可用 CPU。机器上首次运行 tokensave init 时会进行一次基准测试,并将推荐配置保存到 ~/.tokensave/benchmark.toml;没有自行设置 cpu_usage 的每个项目都会使用该配置。tokensave config benchmark [--force|--show|--reset] 可管理该结果,而 TOKENSAVE_CPU_USAGE 或 ~/.tokensave/config.toml 中的全局 cpu_usage 可覆盖该配置(参见用户指南)。memory_usage 会独立限制同时运行的提取解析器数量:low 使用一个,balanced(默认值)最多使用两个,performance 则沿用 CPU 上限。自动预检还可能在物理内存余量不足时进一步降低解析器并发数,包括处于 performance 模式时。这会减少解析器的内存占用,但可能降低吞吐量;图的总内存仍与项目规模成正比,因此这并非硬性内存上限。TOKENSAVE_WORKERS 可进一步降低子进程上限。这些限制不是 CPU 使用率上限。更改配置后,请重启 MCP 服务;设置 TOKENSAVE_DISABLE_SUBPROCESS=1 可选择退出子进程隔离。
编辑原语(tokensave_str_replace、tokensave_insert_at 等)仍在进程内运行:它们一次只针对一个文件,使用子进程会导致开销占主导,而且其中的提取器崩溃会立即呈现给 Agent。
多分支索引(可选)
tokensave 可选择为每个 git 分支维护单独的代码图。启用后,切换分支不会产生过期结果,也不会重新索引已在其他分支解析过的文件。多分支跟踪为可选功能——未启用时,tokensave 会为所有分支使用同一个数据库。
工作原理
跟踪分支时,tokensave 会复制最近祖先分支的数据库,并仅同步有差异的文件。这意味着跟踪从 main 派生的功能分支几乎是即时完成的——它只会解析你修改过的文件。
CLI 命令
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
跨分支 MCP 工具
以下三个 MCP 工具可在不切换当前检出分支的情况下进行跨分支查询:
tokensave_branch_search—— 搜索另一分支代码图中的符号tokensave_branch_diff—— 比较两个分支的代码图:新增、删除和更改的符号(签名不同)。支持文件和类型筛选。tokensave_branch_list—— 列出已跟踪分支及其数据库大小、父分支和同步时间
分支回退
当 MCP 服务找不到当前分支的数据库时,会使用最近祖先分支的数据库提供服务,并在每个工具响应中附带警告,建议运行 tokensave branch add。
自动跟踪分支(v7.3.0)
多分支模式完成初始化(首次手动运行 tokensave branch add 创建分支元数据)后,就可以自动跟踪新分支,而不再回退到祖先数据库。两种相互独立的机制可实现这一点;单数据库模式下的项目不会受到影响,且这两种机制都不会触碰默认分支的数据库。
Git 钩子(切换分支时)。 tokensave install 设置的 post-checkout 钩子会识别分支切换(而非文件检出),并在后台运行 tokensave branch add。如果分支已被跟踪或是默认分支,该命令不会执行任何操作,因此在已知分支之间正常切换不会产生开销。全新 git clone 和新建 git worktree add 的初始检出也属于分支检出,并且可能落在非默认分支上(git clone -b feature、git worktree add -b feature);此时钩子会先运行 tokensave init,再运行 tokensave branch add。由早期版本写入的钩子会保留安装时的内容——安装程序绝不会重写已有钩子——因此在这些安装中,新工作树仍需使用下文的 auto_track,或手动运行 tokensave branch add。
打开时自动跟踪(选择启用)。 当 TokenSave::open 运行时——无论是 CLI 命令还是 MCP 服务启动——如果当前分支尚未跟踪,tokensave 可以立即通过复制最近的已跟踪祖先分支的数据库并将其记录到分支元数据中来跟踪该分支。此功能由 auto_track 配置字段控制(默认值为 false),也可通过 TOKENSAVE_AUTO_TRACK 环境变量启用;该变量会针对每次运行覆盖配置(除 0、false、no、off 或空值外,任何值都会启用此功能)。复制操作与手动运行 branch add 时复制祖先数据库一样,几乎即时完成;此时不会运行同步——随着你提交更改,post-commit 钩子会使新分支的数据库保持最新;或者运行 tokensave sync 立即刷新。自动跟踪严格遵循尽力而为原则:任何失败都会作为警告报告,且 open() 会继续使用通常的祖先回退逻辑,因此绝不会导致工具调用失败。
自动清理(选择启用)。 在 .tokensave/config.json 中设置 "auto_gc": true
(或通过 TOKENSAVE_AUTO_GC=1 仅对单次运行启用),即可清理本地 Git 分支已删除的索引。项目打开时以及 MCP 服务执行常规新鲜度检查时都会进行清理。清理使用与 tokensave branch gc 相同的收集器,并保留默认分支、现有分支、任何 Git 工作树正在使用的分支,以及正在运行的 TokenSave 服务所服务的数据库。Git 查询失败或同步锁被占用时,会跳过自动清理,不会导致命令失败。
默认值为 false,因此旧项目会保留其索引,直至显式清理。TOKENSAVE_AUTO_GC=0 会覆盖项目中已启用的设置;无论此设置如何,显式运行 tokensave branch gc 都会执行清理。
简而言之:安装钩子后,检出新的功能分支(包括全新克隆或工作树初始检出的分支)会自动为其创建独立的分支图;启用 auto_track 后,即使分支是在检出操作之外创建的,tokensave 首次在该分支上打开项目时也会将其纳入跟踪。
完整指南请参阅 docs/BRANCHING-USER-GUIDE.md。
跨会话记忆
三个 MCP 工具会将决策和代码区域上下文持久化保存,以便在不同会话间使用,数据存储在项目专属的 .tokensave/tokensave.db 中。
| 工具 | 用途 |
|---|---|
tokensave_record_decision | 保存设计/架构决策,可选择附带原因、文件和标签 |
tokensave_record_code_area | 标记 Agent 已处理过的路径(触碰计数器 + last_touched_at) |
tokensave_session_recall | 对已保存的决策执行 FTS5 查询;与两个写入工具搭配使用 |
使用这些工具,让 Agent 无需在每次会话中重复解释架构选择。
节省账本
每次 MCP 调用都会向 ~/.tokensave/global.db(savings_ledger 表)追加一行。使用 tokensave gain 查看:
tokensave gain # current project, last 30 days
tokensave gain --all # all projects
tokensave gain --history --range 7d
tokensave gain --json
美元估算使用现有定价模块(Sonnet 输入定价,每日通过 LiteLLM 刷新)。
可复现的基准测试
tokensave bench 会通过 tokensave_context 运行一组固定查询,并报告相对于完整文件基准的检索节省量(与 CCE 方法一致):
tokensave bench # ships with 10 default queries
tokensave bench --queries my-queries.toml --json
tokensave bench --max-nodes 5
使用随附的通用查询集,在此仓库(tokensave 本身)上测得:
| # | 查询 | 基准 | 上下文 | 节省量 | 文件数 | 节点数 |
|---|---|---|---|---|---|---|
| 1 | 启动时如何加载配置? | 45.3k | 454 | 99% | 4 | 5 |
| 2 | 在哪里解析和分派命令行参数? | 948 | 402 | 58% | 3 | 3 |
| 3 | 主入口点是如何组织的? | 6.1k | 251 | 96% | 3 | 8 |
| 4 | 如何定义、封装和传播错误? | 3.5k | 819 | 77% | 2 | 3 |
| 5 | 在哪里输出日志或诊断信息? | 8.6k | 514 | 94% | 6 | 14 |
| 6 | 测试是如何组织的,使用了什么测试框架? | 3.5k | 818 | 77% | 2 | 3 |
| 7 | 如何将数据持久化到磁盘或数据库? | 11.9k | 330 | 97% | 3 | 6 |
| 8 | 如何启动异步任务或后台工作? | 29.4k | 364 | 99% | 2 | 3 |
| 9 | 构建过程如何连接依赖项并初始化状态? | 10.9k | 1.4k | 88% | 4 | 5 |
| 10 | 如何公开 API 接口(HTTP 端点、库导出或 CLI 命令)? | 22.5k | 235 | 99% | 4 | 5 |
汇总: 平均检索节省量为 88%(10 个查询共计从 142.8k 降至 5.5k 个 token)。
默认查询集针对大多数应用代码库中常见的模式(CLI、守护进程、服务)。运行 tokensave bench,即可在自己的项目上查看结果;也可以编写自定义查询文件(--queries my.toml),以获得更高的召回率。
针对大型真实代码库的 Criterion 基准测试
benches/large_repos.rs 是一个 criterion 微基准测试,它会针对四个固定到指定 ref 的大型开源代码库端到端地运行 MCP 工具。每个工具至少会使用 5 个查询及其参数(节点 ID、限定名称、文件 glob 等),这些参数会从每个代码库的索引图中抽取,因此每次运行的计时结果都可复现。
代码库和固定的 ref(定义在 benches/repos.rs 中):
| 代码库 | 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 |
首次使用时,每个代码库都会浅克隆(git init + git fetch --progress --depth 1 origin <ref> + checkout FETCH_HEAD)并缓存在本地;后续运行会复用已有检出。Git 输出会流式传输到终端,因此可以实时查看数 GB 的获取进度。
覆盖的工具(每个工具 5 个查询)。 读取工具 — 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。写入工具 — str_replace、multi_str_replace、insert_at,以及(如果 ast-grep 在 PATH 中)ast_grep_rewrite。
每次运行都强制同步。 运行任何基准测试之前,测试框架都会对每个代码库执行等效于 tokensave sync --force 的操作(无论 .tokensave/ 是否为最新状态,都会执行 index_all()),确保计时始终基于固定的源代码。
写入基准测试和清理。 写入工具会修改文件。为确保“匹配必须唯一”的前提始终成立,测试框架会使用 Criterion 的 iter_batched——在每次计时迭代之前,都会用已知内容重写 <repo>/.tokensave-bench-scratch/ 下的一个临时文件,然后再针对该文件运行编辑工具。所有基准测试完成后,测试框架会在每个已准备好的代码库中运行 git stash --include-untracked && git stash drop,使工作树恢复到固定的 ref。
Criterion 配置。 此基准测试将 Criterion 的默认配置覆盖为 sample_size = 10 和 measurement_time = 30s(默认值为 100 / 5s),使每个查询的计时都能进行约 30 秒的测量,足以让 tokensave_context 在 polkadot-sdk 上这类较慢工具得出稳定结果。
运行方式:
# Required: a writable cache directory for the cloned repos + their indexes.
<p align="center">
<a href="https://ai.enzolombardi.net/"><img src="https://img.shields.io/badge/built%20with-AI-D97757?style=flat-square&labelColor=101010&logo=anthropic&logoColor=white" alt="Built with AI — part of Enzo Lombardi's AI portfolio"></a>
</p>
# Expect several GB of disk and a long first run (shallow clone + full index of each repo).
export TOKENSAVE_BENCH_REPOS_DIR=~/tokensave-bench-cache
cargo bench --bench large_repos
如果未设置 TOKENSAVE_BENCH_REPOS_DIR,基准测试会打印提示并注册 0 个基准测试(因此贡献者的机器上运行 cargo bench --all 不会产生太大开销)。
配置(全部可选,通过环境变量设置):
| 变量 | 作用 |
|---|---|
TOKENSAVE_BENCH_REPOS_DIR | 必需。 每个代码库克隆到的根目录 $DIR/<repo-name>/。 |
TOKENSAVE_BENCH_REPOS | 要运行基准测试的代码库名称子集,以逗号分隔,例如 TOKENSAVE_BENCH_REPOS=emacs,scipy。默认为全部四个代码库。 |
TOKENSAVE_BENCH_SKIP_CLONE | 如果已设置,对于尚未处于固定 ref 的代码库,基准测试会立即失败,而不会执行获取。适用于 CI / 离线运行。 |
筛选基准测试使用标准的 Criterion CLI——例如,只对 scipy 运行 search 工具:
cargo bench --bench large_repos -- 'scipy/tokensave_search'
报告(HTML + 原始样本)会生成在 target/criterion/ 下。
要更改固定的 ref(例如,使用较新的版本或特定 SHA),请编辑 benches/repos.rs 中的 REPOS,并删除对应的 $TOKENSAVE_BENCH_REPOS_DIR/<repo>/.bench-ref 标记,以便下次运行时重新获取。如果跳过了运行后的清理(例如,在基准测试过程中按下 Ctrl-C),可在每个代码库目录中运行 git stash --include-untracked && git stash drop,手动恢复代码库。
MCP 测试矩阵探测器(scripts/mcp_probe)
scripts/mcp_probe/ 是一个 Python 测试框架,通过标准输入输出驱动 tokensave serve,针对一组可配置的真实代码仓库,使用每种语言的 5 个查询变体测试每个只读 MCP 工具,并生成按工具和代码仓库划分的状态表。该测试框架有两种用途:
- 回归扫描。 新增语言支持、新工具或进行重构后,重新运行矩阵;任何新出现错误、超时或返回空结果的单元格都会以 🚩 标出。
- 性能探测。 每次调用的耗时都会记录到 TSV 中;同一组固定代码仓库也可用于粗略比较不同版本。当前的
tokensave_inheritance_depth循环漏洞就是由该测试框架发现的:在 polkadot-sdk 上,单个工具调用超时超过 60 s。
目录结构——probe.py 是驱动程序(使用 ID 匹配 JSON-RPC,因此缓慢的工具不会影响后续调用);isolated.py 会为每次调用启动全新的服务,重新运行单个工具(避免服务队列阻塞);build_matrix.py 读取 TSV 并生成 Markdown;tools/<lang>.py 模块提供各语言的查询集(已支持 Rust;添加新模块即可支持 Python、Go 等);repos.toml 列出目标代码仓库(通过 $TOKENSAVE_PROBE_REPOS 覆盖)。
快速运行:
cargo build --release --bin tokensave
python3 scripts/mcp_probe/probe.py
python3 scripts/mcp_probe/build_matrix.py > matrix.md
输出单元格为 ✓ 5/5(正常)、🐛 e/N(错误)、⏱ N/N(超时)、∅ E/N(空结果)、🐢 ok/slow(调用超过 10 s)。任何带有错误或超时的单元格都会在最右侧一列标出 🚩。TSV 日志中会记录每次调用的详细信息,以及每条错误的前 100 个字符,便于后续排查。
这与上文的 criterion 基准测试不同:criterion 测量固定引用版本上的一组特定工具的每轮延迟,并在 target/criterion/ 下生成统计报告;mcp_probe 则针对你指定的代码仓库,使用更广泛的查询集测试每个工具,侧重覆盖范围,而非测量精度。
80 多个 MCP 工具
该服务提供 80 多个工具(如果 PATH 中没有可选的 ast-grep 二进制文件,则少一个)。从 7.14.0 起,默认仅列出 11 个核心工具和 tokensave_more;其余工具可通过 tokensave_more 按需列出,仍可按名称调用,并且使用 "tools": "full" 时会全部列出。下表按类别列出最常用的工具。大多数工具为只读,可安全并行调用,并标注了 readOnlyHint。编辑原语仅作用于单个文件,并会就地重新索引;会话基线和记忆记录工具也会修改本地 .tokensave 状态,因此标注为非只读。三个核心工具(tokensave_context、tokensave_search、tokensave_status)标记为 anthropic/alwaysLoad,因此不会经过客户端的工具搜索往返流程。
查询其他已初始化的项目
语义读取工具可以在不重启 MCP 服务的情况下,查询明确选定的本地图谱:
{
"query": "screenGate",
"graph_root": "/absolute/path/to/typewhisper"
}
选定的结果会包含规范的根目录/分支来源信息。节点 ID 以该图谱为命名空间,后续调用时必须重复指定匹配的选择器。例如,对按分支选定的查询进行后续调用时,需包含这两个值:
{
"node_id": "graph:<fingerprint>:function:<raw-id>",
"graph_root": "/absolute/path/to/typewhisper",
"graph_branch": "feature/auth"
}
graph_root 必须是一个已初始化项目的准确绝对路径。graph_branch 为可选项;如果提供,必须是已跟踪的分支。选定的打开操作是只读的:不会初始化、同步、迁移、自动跟踪,也不会写入图谱/源数据。它们也不会计入节省量统计。不带选择器的调用行为与之前完全相同。
只有当你知道另一个项目存在时,graph_root 才有用,因此服务会告知你:与服务根目录直接相邻的已初始化项目,会列在 MCP instructions、tokensave_status 以及无结果的 tokensave_search/tokensave_context 响应中——否则会话可能会就此认定某个符号不存在,而不会继续查找相邻目录(#375)。仅提供直接相邻的项目,最多五个;不会代为打开或索引这些项目;查询其中的项目仍需明确指定 graph_root。
选择器有意不支持用于会写入数据、调用 shell 命令或依赖当前检出内容的工具:编辑原语、VCS 和分支工具、诊断和测试执行、依赖项与运行时自省、工作流和会话记忆工具、持久缓存工具(tokensave_redundancy)以及服务管理工具。这些工具会拒绝选择器,而不会静默忽略。
发现
| 工具 | 用途 |
|---|---|
tokensave_context | 获取与任务相关的代码上下文——入口点、相关符号、代码片段 |
tokensave_search | 按名称查找符号(函数、类、类型) |
tokensave_node | 获取特定符号的详细信息和源代码 |
tokensave_files | 列出已索引的项目文件(源文件和已跟踪的制品),并支持筛选 |
tokensave_module_api | 获取文件或目录的公共 API 概况 |
tokensave_similar | 查找名称相似的符号 |
tokensave_annotations | 属性/注解/装饰器自省——全部注解的直方图,或带目标筛选条件的逐位置列表 |
tokensave_doc | 获取源文件的配套 Markdown 文档——文档内容、涵盖的文件以及过时状态提示 |
tokensave_dependencies | 跨 17 个生态系统检查包清单——工作区概况、按包查询、许可证概况、版本差异 |
tokensave_status | 索引状态、统计信息、节省的令牌数 |
自定义源文件扩展名
在 .tokensave/config.json 中将扩展名映射到已启用的提取器:
"language_aliases": { ".t": "perl", ".ep": "perl" }
这样无需重命名旧版 Perl 测试文件即可对其进行解析。键可以带可选的前导句点,且匹配时不区分大小写;无效、冲突、未知或已禁用的映射会导致同步失败,并报配置错误。别名会覆盖内置扩展名关联和制品跟踪。对于文件/glob 覆盖,请使用现有的 project.json entries 并指定 language;它们的优先级高于别名。编辑映射后运行 tokensave sync(sync -f 也可)。参见配置指南。
非代码制品
tokensave_files 不仅涵盖源代码。扩展名列在
artifact_extensions 中的文件(默认为 .feature、.json、.yaml、.yml、.sql、.toml、
.proto、.graphql、.md、.bnd、.bndrun)会按路径跟踪,因此像“登录流程的 .feature 文件在哪里?”这样的问题可以通过图回答,而不会因 find 受阻(#323)。这些文件绝不会被解析,也不会贡献任何符号;
kind: "artifact" 和 kind: "code" 可用于在两者之间筛选,而只针对“代码”的分析会排除它们。如果某个扩展名已由语言提取器处理,则会在此列表中忽略,因此不能用它来阻止对某种语言进行解析。
此列表也决定了字面搜索可以查找哪些内容(#442)。tokensave_search 上的字面搜索
(literal: true)读取的是字节,而不是符号,因此不需要解析器——但它会遍历已索引的文件,所以只能访问索引中有对应行的文件。已跟踪的 .rst 文档或 .tmpl 模板既没有提取器,也不在默认制品列表中,因此搜索会漏掉其中的匹配项;在此添加相应扩展名并运行 tokensave sync -f 后,其中的行就会像其他文件一样被搜索。由于没有符号上下文,这些结果会报告为 enclosing: null。如果字面搜索响应无法访问所有已跟踪文件,就会在 unscanned 块中说明,并列出未扫描文件的数量和扩展名,因此不会把不完整的答案呈现为完整答案。
调用图与影响分析
| 工具 | 用途 |
|---|---|
tokensave_callers | 查找调用某个函数的内容 |
tokensave_callees | 查找某个函数调用的内容 |
tokensave_impact | 查看更改某个符号会影响哪些内容 |
tokensave_affected | 查找受源代码更改影响的测试文件 |
tokensave_rename | 基于图的重命名:列出每个位置及其置信类别(exact、heuristic、ambiguous、text_only),提供差异预览,并以全有或全无的方式应用更改。不考虑绑定关系 |
tokensave_hotspots | 查找连接最多的符号(调用次数最高) |
代码质量
| 工具 | 用途 |
|---|---|
tokensave_complexity | 按圈复杂度和认知复杂度、嵌套深度、Halstead 指标、可维护性指数、CRAP 和安全指标对函数进行排名 |
tokensave_dead_code | 查找不可达符号(没有入边;被列为歧义候选项的符号除外) |
tokensave_ambiguous_calls | 查找解析器无法确定唯一目标的调用位置,并列出所有并列候选项 |
tokensave_god_class | 查找成员过多的类 |
tokensave_coupling | 按扇入/扇出对文件进行排名 |
tokensave_inheritance_depth | 查找继承层级最深的结构 |
tokensave_circular | 检测循环文件依赖 |
tokensave_imports | 模块级导入依赖、循环和切断模拟 |
tokensave_recursion | 检测递归/相互递归的调用循环 |
tokensave_unused_imports | 查找从未被引用的导入语句 |
tokensave_doc_coverage | 查找缺少文档的公共符号 |
tokensave_simplify_scan | 对更改的文件进行质量分析(重复、死代码、复杂度) |
代码健康度分析
五种工具从现有图中提取结构质量信号。综合评分采用独立维度的几何平均值,因此无法通过操纵单一维度来刷分。
| 工具 | 用途 |
|---|---|
tokensave_health | 综合质量信号(0-10000),基于无环性、深度、相等性、冗余度和模块化程度 |
tokensave_gini | 任意指标的基尼不平等系数(复杂度、行数、入度/出度、成员数)——用于发现上帝文件和分布不均 |
tokensave_dependency_depth | 文件级依赖链的最长路径(Lakos 层级划分),在通过 Tarjan 强连通分量算法打破循环后重建完整链路 |
tokensave_dsm | 以 stats、clusters 或 matrix 形式呈现设计结构矩阵——揭示分层违规和隐藏耦合 |
tokensave_test_risk | 风险加权的测试缺口分析,将复杂度、入度、覆盖率和过去 90 天的 Git 变更频率合并为单一评分 |
会话
在 AI 编码会话开始时快照健康度指标,然后在结束时进行差异比较,查看哪些方面有所改善或退步。
| 工具 | 用途 |
|---|---|
tokensave_session_start | 将当前健康度指标保存为 JSON 基线,以便稍后进行比较 |
tokensave_session_end | 重新计算并与基线比较——显示各维度的变化、通过/失败状态,并自动清理 |
编辑原语
四种写入工具,让 Agent 无需正则表达式或处理 Shell 引号风险即可修改文件。每种工具仅操作单个文件、基于锚点定位,并在写入后原地重新索引,确保图始终保持最新。
| 工具 | 用途 |
|---|---|
tokensave_str_replace | 将唯一的 old_str 替换为 new_str;匹配 0 次或超过 1 次时失败(防止多重编辑错误) |
tokensave_multi_str_replace | 原子性地应用 N 组 (old, new) 替换——要么全部成功,要么全部回滚 |
tokensave_insert_at | 在唯一锚点字符串之前或之后,或指定行号处插入内容 |
tokensave_ast_grep_rewrite | 通过 ast-grep CLI 的 --rewrite 模式进行结构化代码重写 |
Git 与工作流
| 工具 | 用途 |
|---|---|
tokensave_diff_context | 获取变更文件的语义上下文——修改的符号、依赖项和受影响的测试 |
tokensave_commit_context | 对未提交变更进行语义摘要,用于起草提交消息 |
tokensave_pr_context | 获取 Git 引用之间的语义差异,用于撰写拉取请求说明 |
tokensave_changelog | 获取两个 Git 引用之间的语义差异 |
tokensave_test_map | 在符号级别建立源代码与测试的映射,并检测未覆盖的符号 |
tokensave_test_coverage | 汇总每个文件/符号/测试函数的覆盖率,并扩展传递调用边 |
类型系统
| 工具 | 用途 |
|---|---|
tokensave_type_hierarchy | 为 trait、接口和类生成递归类型层级树 |
tokensave_rank | 按关系数量对节点排名(实现接口最多的类、被扩展最多的类) |
tokensave_distribution | 按文件或目录统计节点类型分布 |
tokensave_largest | 按大小对节点排名——最大类、最长方法 |
移植
| 工具 | 用途 |
|---|---|
tokensave_port_status | 比较源目录和目标目录中的符号,以跟踪移植进度 |
tokensave_port_order | 对待移植符号进行拓扑排序——先移植叶节点,再移植其依赖项 |
多分支
| 工具 | 用途 |
|---|---|
tokensave_branch_search | 在另一个分支的图中搜索符号 |
tokensave_branch_diff | 比较不同分支中的符号;quality: true 用于比较结构质量 |
tokensave_branch_list | 列出受跟踪的分支及其数据库大小和同步时间 |
分支质量退步
比较 Git 最新提交所对应的两个现有分支索引:
tokensave quality-diff --base master --target feature/example
tokensave quality-diff --base master --target HEAD --json --fail-on regression
tokensave quality-diff --base origin/master --target feature/example --cyclomatic 15 --min-increase 5
每个引用都必须解析为一个提交,并指定一个已跟踪的 Tokensave 分支。
HEAD 会解析为当前符号分支;如果 HEAD 处于分离状态,则必须显式指定
分支。接受完整的 refs/heads/... 和 refs/remotes/... 名称。进行比较前,请按照现有的 tokensave branch add / sync
工作流,分别显式创建并同步每个索引。比较不会切换分支或重建
索引。缺少索引和分析数据为空均视为错误,包括将分支与自身进行比较。
比较基准是分支尖端对分支尖端,而非合并基点。对于已分叉的分支, 报告的差异可能源自任一分支;这并不能证明某项功能自分支以来引入了该差异。
支持的诊断会复用已提取/编入索引的数据:
| 代码 | 指标/标识 | 默认阈值 |
|---|---|---|
Q_COMPLEXITY_CYCLOMATIC | 函数分支数 + 1 | >10 |
Q_COMPLEXITY_COGNITIVE | 提取的认知复杂度 | >15 |
Q_FUNCTION_LINES | 函数跨度(含首尾行) | >100 |
Q_FILE_FAN_OUT / Q_FILE_FAN_IN | 经解析调用/使用所涉及的不同文件数,或指向此文件的不同文件数 | >10 |
Q_CYCLIC_DEPENDENCY_EDGE | 循环强连通分量内的有向文件边 | 存在 |
使用 --cyclomatic、--cognitive、--function-lines 和
--fan-out(后者同时适用于扇入和扇出)更改阈值。已有的超阈值
问题在其指标至少增加 --min-increase(默认为 3)时会变为 worsened;较小的增幅在门禁判断中仍为
unchanged。跨越阈值属于 new;降至阈值以下或被删除属于 resolved;仍高于阈值但数值下降则属于 improved。已有的循环边保持不变。已有边变为循环边时属于 new,即使该边本身早于本次比较就已存在。循环会以循环分量中的边报告,而非列举循环路径。
JSON 包含确定顺序的诊断、代码、类别、警告严重性、标识、基准/目标值、位置(函数位置从 1 开始)、置信度、分类计数和限制。--fail-on regression 在存在 new 或 worsened 发现时退出 1,否则退出 0。操作错误和明确接受的不完整结果均退出 2,且不受 --fail-on 影响。不带该标志时,完整比较退出 0。JSON 模式会将单个 JSON 文档写入 stdout,操作错误时也如此。
现有 MCP 工具接受相同的比较参数:
{"base":"master","head":"feature/example","quality":true,"limit":20,"thresholds":{"cyclomatic":10,"min_increase":3}}
MCP report 与 CLI 使用相同的架构。计数涵盖所有发现;详情默认显示 20 项(最多 500 项),truncated 和 total_findings 位于报告之外。使用 limit: 0 仅获取计数。thresholds 接受表中的选项名称(cyclomatic、cognitive、function_lines、fan_out),以及 min_increase 和 allow_stale;未知选项会被拒绝。质量模式下不接受文件/种类筛选,因为判断循环性和耦合需要全局证据。不会额外提供 MCP 工具。质量调用会跳过每次调用时的自动同步/版本重新编制索引;已在运行的服务中其他独立活动仍按正常方式进行。
新鲜度验证使用与索引相同的源解码器,将已索引文件与 Git blob 进行哈希比对,并接受 Git 检出或提交规范化导致的 LF/CRLF 换行转换。不匹配或已删除的文件,以及未索引的源文件候选项,都会报告为过期/不完整。候选项发现会遵循已配置的排除规则、隐藏文件规则和大小规则;分支特定的忽略规则或清单策略可能解释某个候选项,因此会将其描述为不确定。--allow-stale(MCP thresholds.allow_stale)允许在 complete: false 且退出码为 2 的情况下进行检查;它绝不会在 CI 结果中悄然将过期证据视为干净。complete 表示这些索引内容检查已通过,并不表示已分析所有语言或依赖项。已配置的排除项和不受支持的语言仍不在范围内;提取器指标为零并不能证明复杂度低。索引必须使用可比较的分析版本/配置。验证不会认证解析器的完整性,也不会检测图数据行中任意的手动编辑。
位置不参与身份判定。Git 检测到的文件重命名会规范化函数和依赖项的身份,而限定符号名用于标识函数。符号重命名、Git 未检测到的移动,以及有歧义的重载都无法可靠匹配:未匹配的发现会明确标记 confidence: "unmatched";有歧义的同名/同类型/同签名指标会从两个快照中排除,并导致结果不完整。重载使用签名来区分其他方面完全相同的限定名称。在将未匹配的新旧配对作为缺陷处理之前,请先进行审查;它们仍可能影响 CI。函数大小发现使用源代码跨度,而非可执行语句数。架构策略、死代码、测试可达性/覆盖率和模块大小回归暂不支持。
快照会在数据库读取事务中按顺序读取。符号主体一次只加载一个已索引文件;比较过程中只保留精简的指标记录。文件邻接关系和现有的迭代式 SCC 算法在环分析中需要 O(files + resolved file dependencies) 的空间/时间复杂度。不会枚举各个环。验证对每个快照使用一个 Git 批处理进程,并一次处理一个解码后的 blob(最大 64 MiB);它会读取已索引内容和 Git 树元数据,不会扫描工作树。总成本也随已索引源代码字节数和符号数量增长;这种设计有意以一定的 I/O 开销换取无需提交来源信息也能验证新鲜度。比较过程不会创建缓存、工作线程池或后台任务。大型 JSON 报告可能占用大量空间;令牌预算有限时,请使用 MCP 计数或限制详情。
MCP 资源
通过 resources/list 和 resources/read 暴露四项资源:
tokensave://status-- 图统计信息(JSON 格式)tokensave://files-- 按目录分组的已索引文件树tokensave://overview-- 项目摘要,包含语言分布和符号类型tokensave://branches-- 已跟踪分支及数据库大小和父级信息
Token 跟踪
tokensave 会统计每次 MCP 工具调用节省的 Token。每个工具响应都包含一行 tokensave_metrics: before=N after=M,显示该次调用避免读取的原始文件 Token 数。
关闭报告。 指标行以及 MCP instructions 中的一句话会要求 Agent 向你报告节省量——这意味着模型会花费 输出 Token 来叙述 tokensave 在 输入 Token 上节省的量。输出 Token 成本更高,因此如果 Agent 几乎每轮都提到 tokensave,这些叙述可能抵消节省的收益(#356)。在 .tokensave/config.json 中将 report_savings 设为 false,或使用环境变量 TOKENSAVE_REPORT_SAVINGS 按运行覆盖(除 0、false、no、off 或空值外,任何值都会启用该功能)。指标行和指令都会消失;tokensave install 也会停止向 Agent 提示词文件写入报告规则。无论如何,测量不会受影响——每次调用仍会记录到节省账本中,因此 tokensave gain、tokensave list、status 和 monitor 的报告与以往完全相同。默认值仍为 true。
默认仅列出核心工具。 MCP 客户端会在调用任何工具之前,每轮都发送所有已列出工具的架构。tokensave 的完整工具集架构约为 89 KB,对于上下文较小的模型,可能占据窗口的一半以上(#576)。因此,tools/list 只会发送核心工具:context、search、status、read、body、files、callers、callees、impact、str_replace 和 multi_str_replace(启用 tokensave_more 时约为 17 KB)。initialize 指令会列出这些工具以及 tokensave_more 可以列出的工具类别,因此,即使客户端延迟获取工具架构,也知道其他工具的存在。此设置决定服务列出哪些工具,而非它能运行哪些工具:未列出的工具仍可按名称响应调用,因此 Agent 权限列表和钩子仍能正常工作。若要列出所有工具,请在 .tokensave/config.json 中设置 "tools": "full",或在 MCP 服务的环境中设置 TOKENSAVE_TOOLS=full;环境变量优先于文件。7.13.0 写入的 "tools": "full" 会被视为旧默认值,因为该版本会将它写入每个保存的配置中;升级后需重新设置,才能保留完整列表。
使用核心工具集时,服务还会列出 tokensave_more。调用时传入一个 area(analysis、edit、git、memory、navigate 或 all),即可在本次会话剩余时间内列出该类别的工具;服务还会发送 notifications/tools/list_changed,以便客户端重新获取列表。会话只需为实际使用的类别付费:git 类别会增加约 6 KB。忽略 list_changed 的客户端会继续使用核心列表。tokensave install 会授予 tokensave_more 及所有其他工具的权限,因此不会提示;在此版本发布前安装的版本会提示一次,直到运行 tokensave reinstall 或升级后重新同步权限列表。
成本可观测性
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
解析 Claude Code 会话记录(~/.claude/projects/**/*.jsonl),并根据模型定价为每轮 API 调用计算费用;读取 Pi 会话(~/.pi/agent/sessions/**/*.jsonl),采用 Pi 已按消息报告的费用;并以 credits 为单位导入 Factory Droid 会话设置。每轮都会被归入 13 个任务类别之一,并存储在 ~/.tokensave/global.db 中,以便快速进行汇总查询。每 24 小时从 LiteLLM 刷新定价,离线时则回退到内置定价表。
tokensave status 标题区域包含一行费用信息,显示今日支出、过去 7 天的总支出和效率比(节省的 token 数 / token 总数)。tokensave monitor TUI 会在节省信息流旁显示实时费用面板。每次 Claude Code 会话结束时,hook_stop 处理程序会在终端打印一行结算信息;在 Pi 中,已安装的扩展也会通过 agent_settled 处理程序执行相同操作。
任务分类包括:编码、调试、功能开发、重构、测试、探索、规划、委派、Git 操作、构建/部署、头脑风暴、对话、通用。分类采用确定性方式(根据工具名称和 Bash 命令进行模式匹配),无需调用大模型,改编自 AgentSeal/codeburn。
实时监控
tokensave monitor
这是一个全局 TUI,通过共享的内存映射环形缓冲区 ~/.tokensave/monitor.mmap,实时显示所有项目中的 MCP 工具调用。每个条目显示项目名称、工具名称和 token 变化量。顶部的费用面板显示今日支出、节省量、效率和使用量最高的模型(每 30 秒刷新一次)。
内存诊断
tokensave memory [--clean]
通过共享的内存映射表 ~/.tokensave/memory.mmap,生成涵盖每个 tokensave 进程(MCP 服务、同步任务、索引运行)的整机内存报告。每个实例会在启动时、每次 MCP 工具调用时以及同步/解析阶段前后尽力采样自身的 RSS,因此报告会显示当前和峰值 RSS 以及产生峰值的阶段——这些数据可用于判断高内存占用的来源(参见 #253)。各行会标记为 alive、dead(被 OOM 终止的进程会留下其峰值/阶段信息作为取证记录)或 orphan(仍在运行,但已重新挂到 init 进程)。--clean 会清除已结束的条目。
PEAK PHASE 表示产生最高 采样值 的阶段,因此其精确度取决于采样情况。增量同步按顺序记录:sync:extract、sync:resolve:load_nodes、sync:resolve:build_caches、sync:resolve:refs、sync:variants、sync:done。完整索引记录:index:extract、index:resolve:build_caches、index:resolve:refs、index:resolve:done、index:insert、index:done。
每个阶段都在其对应工作完成后记录。 过去是在工作开始前记录,因此每次采样都会把上一步的 RSS 记在下一步的标签下——这导致 73 MiB 被归到了节点加载阶段,但实际上这部分内存来自加载尚未解析的引用;该步骤完全没有采样,也因此数月来都把内存排查引向了错误的子系统(#409)。如果要添加阶段,请在工作完成后采样,并为任何可能达到峰值的大步骤添加采样。
会话和生命周期计数器
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 会显示项目索引统计信息、语言分布、费用行(今日 / 7 天 / 效率),以及项目和全球生命周期总量:
全球计数器
所有 tokensave 用户都会为匿名汇总计数器贡献数据。tokensave status 会显示你的项目总量和全球总量。上传内容仅包含一个数字(例如 4823),不含任何身份信息。使用 tokensave disable-upload-counter 退出上传。
索引新鲜度
tokensave 无需后台守护进程或操作系统级文件监视器,即可保持图谱最新。
按需检查过期状态。 每次调用 MCP 工具时,都会检查自上次同步后是否有已索引文件被修改。如果发现过期文件,会在返回工具响应前重新提取。30 秒冷却时间可避免连续调用时每次按键都重新遍历目录树。
连接时追赶同步。 MCP 服务启动时,会立即运行非阻塞式追赶同步,拾取没有 Agent 连接期间发生的所有更改——例如 git pull、IDE 编辑或构建步骤——因此会话中的首次工具调用就能使用最新索引。
多 Agent 协作与 git worktree。 多个 Agent 同时处理同一项目时,我们强烈建议每个 Agent 都在自己的 git worktree 中运行。Worktree 是同一仓库相互独立的文件系统检出:Agent A 和 Agent B 各自拥有每个文件的副本,因此不会覆盖彼此正在进行的编辑。tokensave 会自动检测查询是否来自嵌套在主检出目录中的 worktree,并从正确的分支图谱中提供结果。更改会独立累积,最终通过 git merge 或 rebase 协调——与任何其他并行开发所采用的流程相同。这种设计避免了在共享可变目录上进行跨 Agent 锁定所带来的复杂性和故障模式。
仅使用命令行的工作流。 如果你在没有连接 Agent(没有 MCP 服务)的情况下运行 tokensave 命令,各命令之间不会运行过期状态检查。安装 git hooks,即可在每次提交或克隆后自动保持索引最新:
cp scripts/post-commit scripts/post-checkout .git/hooks/
chmod +x .git/hooks/post-commit .git/hooks/post-checkout
从 5.x 升级
独立的 tokensave daemon 命令以及其 launchd/systemd/Windows Service 自动启动功能已在 6.0.0 中移除。用于替代守护进程的嵌入式操作系统级文件监视器也在 6.1.1 中移除(在包含深层 node_modules 或 target 目录的大型 monorepo 中,它会导致 CPU 和内存持续飙升)。上文介绍的按需过期状态检查模式是当前设计。
如果你仍然保留了 5.x 的守护进程自动启动配置,请将其移除:
- 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(在提升权限的终端中运行)
如果你不记得确切名称: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 会从 GitHub releases 下载适用于当前平台的二进制文件,并原位替换正在运行的二进制文件。稳定版和 beta 版频道可分别使用。
版本管理与升级
tokensave 的版本号看起来像 SemVer,但并不遵循它:变化的版本位表示更新需要执行的维护操作,tokensave 会在下次启动时自动完成——你无需手动重新安装或重建索引。
| 升级类型 | 示例 | 更新要求 | 自动操作 |
|---|---|---|---|
补丁版本(x.y.Z) | 7.2.0 → 7.2.1 | 无 | 无——无需重新安装或重建索引 |
次版本(x.Y.0) | 7.2.0 → 7.3.0 | 重新安装(新增的 harness、新工具、新配置) | 全局重新安装所有已安装的 Agent 集成(刷新权限、钩子和 MCP 配置) |
主版本(X.0.0) | 7.2.0 → 8.0.0 | 重新安装并完整重新同步 | 全局重新安装,并且对每个项目强制重建索引(相当于 sync -f) |
全局重新安装。 首次运行新的次版本或主版本时,tokensave 会为每个已注册的 Agent 静默重新运行 install,确保 Agent 配置始终指向当前二进制文件,并启用当前工具集。补丁版本升级会跳过此步骤——只会更新运行版本标记。
重新安装确实是静默执行的:此处会抑制显式运行 tokensave install 时看到的每个 Agent 的设置输出,因此这些输出不会出现在常规的 tokensave init 或 tokensave sync 前面。如果某个 Agent 的配置无法刷新——应用未安装,或其配置位于只读位置——你会看到一行提示,其中列出失败的 Agent:
warning: could not refresh tokensave config for: copilot.
Run tokensave install to see the error.
运行 tokensave install 查看底层错误。无论结果如何,版本标记都会更新,因此无法写入的配置路径每次升级只会报告一次,而不会在后续每条命令中重试。
按项目强制重建索引(仅限主版本)。 主版本升级意味着必须重建项目索引。tokensave 会按需逐个项目执行:主版本升级后,在某个项目中首次调用 MCP 工具时,tokensave 会在后台启动完整的索引重建(相当于 tokensave sync --force),且不会阻塞工具响应。
Brew / cargo 备用方案。 如果通过 tokensave upgrade 以外的方式在外部替换二进制文件(例如运行 brew upgrade tokensave 或 cargo install tokensave),tokensave 也会以相同方式检测:如果当前运行版本比上次执行安装的版本更新,则会在下次启动时重新安装,就像自行升级后的处理方式一样。
参阅 TOKENSAVE-VERSIONING.md,了解 tokensave 为何偏离 SemVer(在版本号中编码维护操作,才能实现零操作升级)、标记机制、独立的数据库架构版本,以及维护者发布版本时的规则。
CLI 参考
tokensave init [path] # Initialize a new project (full index); without a path, the git root
# (a no-op inside an existing project)
tokensave init --cpu-usage low # Initialize with a fixed CPU profile (skip the benchmark)
tokensave config benchmark # Run or reuse the machine-level hardware benchmark
tokensave config benchmark --show # Show the saved benchmark and settings (never measures)
tokensave config benchmark --force # Measure this machine again
tokensave config benchmark --reset # Delete the saved benchmark
tokensave tune [path] [--dry-run] # Re-benchmark, save globally, update a pinned cpu_usage
tokensave sync [path] # Incremental sync (must be initialized first)
tokensave sync --force [path] # Force a full re-index
tokensave sync --doctor [path] # Sync and list added/modified/removed files
tokensave verify [path] # Read-only index integrity and source-stat checks
tokensave verify [path] --deep --json # Full SQLite checks and bounded source hashing
tokensave status [path] # Show statistics + cost summary
tokensave status [path] --json # Show statistics (JSON output)
tokensave status --details # Include node-kind breakdown
tokensave cost [range] # Token cost summary (default: 7d)
tokensave cost --by-model # Cost grouped by model
tokensave cost --by-task # Cost grouped by task category
tokensave cost --export json|csv # Export cost data
tokensave query <search> [path] # Search symbols
tokensave files [--filter dir] [--pattern glob] [--json] # List indexed files
tokensave affected <files...> [--stdin] [--depth N] # Find affected test files
tokensave install [--agent NAME] # Configure agent integration
tokensave reinstall # Refresh settings for all installed agents
tokensave uninstall [--agent NAME] # Remove agent integration
tokensave serve [--idle-timeout-secs N] # Start MCP server (N: exit after N idle seconds)
tokensave servers [--json] # List running servers and the index each one holds
tokensave monitor # Live TUI showing MCP calls across all projects
tokensave memory [--clean] # Per-instance RSS report for all tokensave processes
tokensave upgrade # Self-update to latest version
tokensave channel [stable|beta] # Show or switch update channel
tokensave doctor [--agent NAME] # Check installation health
tokensave githooks [on|off] [--local] # Manage git hooks (--local: this repo only, no core.hooksPath)
tokensave branch add|list|remove|removeall|gc # Multi-branch management
tokensave current-counter # Show per-project token counter
tokensave reset-counter # Reset per-project token counter
tokensave disable-upload-counter # Opt out of worldwide counter uploads
tokensave enable-upload-counter # Re-enable worldwide counter uploads
tokensave doctor
对 tokensave 安装执行全面的健康检查:
tokensave doctor
检查内容:二进制文件位置、项目索引、全局数据库、用户配置、Agent 集成(MCP 服务、钩子、权限、提示词规则)和网络连接。如果升级后缺少任何工具权限,它会提示你运行 tokensave install。使用 --agent 仅检查指定的 Agent。
Doctor 还会验证每个已安装的钩子是否使用正确的 tokensave 子命令,并自动修复损坏的钩子。
与 Claude Code 的协作方式
配置完成后,当 Claude Code 需要理解代码库时,会自动使用 tokensave,而不是读取原始文件。三层机制相互配合:
| 层 | 功能 | 重要性 |
|---|---|---|
| MCP server | 向 Claude 提供 80 多个 tokensave_* 工具 | Claude 可以直接查询图 |
| CLAUDE.md rules | 告诉 Claude 优先使用 tokensave,而不是 Agent 或读取文件 | 防止模型退回到开销较大的模式 |
| PreToolUse hook | 原生 Rust hook 会拦截 Explore Agent | 在模型忽略 CLAUDE.md 规则时进行拦截 |
| UserPromptSubmit hook | 在提交提示词时运行 | 用于令牌计量的生命周期跟踪 |
| Stop hook | 在会话结束时运行 | 刷新令牌计数器 |
结果:Claude 可以用少得多的令牌实现同等的代码理解能力。典型的 Explore Agent 会读取 20–50 个文件;tokensave 则从预构建索引中返回相关符号、关系和代码片段。
网络调用与隐私
tokensave 的核心功能(索引、搜索、图查询、MCP 服务)100% 在本地运行——你的代码绝不会离开你的设备。
| 调用 | 发送的数据 | 时机 | 选择退出 |
|---|---|---|---|
| 全球计数器上传 | 令牌数量(一个数字)+国家/地区(根据 IP 获取) | sync、status、MCP 会话 | tokensave disable-upload-counter |
| 全球计数器读取 | 无(GET 请求) | status | N/A(只读,超时为 1s) |
| 版本检查 | 无(GET 请求) | status(缓存 5 分钟),sync(并行) | N/A(超时为 1s,失败时不执行任何操作) |
| 模型定价刷新 | 无(GET 请求) | tokensave cost(缓存 24 小时) | N/A(超时为 5s,失败时使用内置定价) |
全球计数器上传会发送一个包含 JSON 正文的 HTTP POST,例如 {"amount": 4823}。没有 Cookie、跟踪信息或用户 ID。Cloudflare Worker 会记录你的 IP 地址所在国家/地区(根据请求标头推导),用于汇总地理统计数据——不会存储你的实际 IP 地址。
模型定价刷新会从 GitHub 获取一个公开 JSON 文件(raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json),以便为 tokensave cost 更新 Claude 模型定价。不会发送任何数据——这只是一个普通的 HTTPS GET 请求。响应会在 ~/.tokensave/pricing.json 中缓存 24 小时。如果获取失败,tokensave 会使用编译时内置的定价表。
支持 50 多种语言
tokensave 支持 50 多种编程语言,分为三个由 Cargo 功能标志控制的层级。每个层级都包含其下方层级的所有语言。Markdown 标题会被提取为 Module 节点,并通过分层的 Contains 边连接,使文档结构也能与源代码一同参与图查询。
Lite -- --no-default-features
始终编译。为最热门的语言提供体积最小的二进制文件,还包括 Svelte 和 Astro(通过 TypeScript 提取器提取脚本块,不需要额外的语法依赖)。
| 语言 | 扩展名 |
|---|---|
| Rust | .rs |
| Go | .go |
| Java | .java |
| Scala | .scala、.sc |
| TypeScript | .ts、.tsx |
| JavaScript | .js、.jsx |
| Python | .py |
| C | .c、.h |
| C++ | .cpp、.hpp、.cc、.cxx、.hh |
| Kotlin | .kt、.kts |
| C# | .cs |
| Swift | .swift |
| Svelte | .svelte |
| Astro | .astro |
Medium(Lite + 9 种语言)-- --features medium
| 语言 | 扩展名 | 功能标志 |
|---|---|---|
| Dart | .dart | lang-dart |
| Pascal | .pas、.pp、.dpr | lang-pascal |
| PHP | .php | lang-php |
| Ruby(包括 ERB 和 Slim 模板) | .rb、.rake、.erb、.slim | 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 |
ERB 和 Slim 模板使用 Ruby 语法,无需在索引时安装 Ruby 或模板 gem。模板调用属于文件节点,并保留其原始行号和字节列号。ERB 支持代码/输出标签、修剪标记、注释和转义标签。Slim 支持控制/输出行、基于缩进的块、属性(包括多行属性列表)、文本插值和 ruby: 块。
不支持自定义 Slim 快捷写法和嵌入式语言编译。无法区分 Rails 在渲染时提供的局部变量与裸助手调用;模板中赋值或绑定的名称会被保守地排除。控制器与视图之间的关系以及局部模板渲染关系需要单独的 Rails 语义接线。
Full(Medium + 其余全部)-- 默认
| 语言 | 扩展名 | 功能标志 |
|---|---|---|
| ActionScript | .as | lang-actionscript |
| Lua | .lua | lang-lua |
| Zig | .zig | lang-zig |
| Objective-C | .m、.mm | lang-objc |
| Perl | .pl、.pm | lang-perl |
| Batch/CMD | .bat、.cmd | lang-batch |
| Fortran | .f90、.f95、.f03、.f08、.f18、.f、.for | lang-fortran |
| COBOL | .cob、.cbl、.cpy | lang-cobol |
| MS BASIC 2.0 | .bas | lang-msbasic2 |
| GW-BASIC | .gw | lang-gwbasic |
| QBasic | .qb | lang-qbasic |
| QuickBASIC 4.5 | .bi、.bm | lang-qbasic |
| Dockerfile | Dockerfile、.dockerfile | lang-dockerfile |
| GLSL | .glsl、.vert、.frag、.comp | lang-glsl |
| Godot Shader | .gdshader、.gdshaderinc | lang-glsl |
| Minecraft Function | .mcfunction | lang-mcfunction |
| WGSL | .wgsl | lang-wgsl |
| HLSL | .hlsl、.fx | lang-hlsl |
| Verilog / SystemVerilog | .v、.vh、.sv、.svh | lang-systemverilog |
| VHDL | .vhd、.vhdl | lang-vhdl |
| Metal | .metal | lang-metal |
| CUDA / HIP | .cu、.cuh | lang-cuda |
| Markdown | .md、.markdown | lang-markdown |
| R | .r、.R | lang-r |
| SQL | .sql | lang-sql |
| Julia | .jl | lang-julia |
| Haskell | .hs、.lhs | lang-haskell |
| OCaml | .ml、.mli | lang-ocaml |
| Clojure | .clj、.cljs、.cljc | lang-clojure |
| Erlang | .erl、.hrl | lang-erlang |
| Elixir | .ex、.exs | lang-elixir |
| F# | .fs、.fsi、.fsx | lang-fsharp |
| F* | .fst、.fsti | lang-fstar |
| Quint | .qnt | lang-quint |
| Terraform | .tf、.tfvars | lang-terraform |
| TOML | .toml | lang-toml |
| Lean | .lean | lang-lean |
| HTML | .html、.htm | lang-html |
| CSS | .css | lang-css |
也可以单独选择个别语言,无需启用完整层级:
cargo install tokensave --no-default-features --features lang-nix,lang-bash
所有提取器都具有相同的深度:函数、类、方法、字段、导入、调用图、继承链、文档字符串、复杂度指标、装饰器/注解提取以及跨文件依赖跟踪。
HTML 和 CSS 是例外,因为这两种语言都没有可调用符号。HTML 会记录带有 id 的元素、自定义元素,以及页面引入的样式表和脚本;CSS 会记录类和 id 选择器、自定义属性、@keyframes 名称和 @import。两者都不会将 class="..." 属性解析为样式表规则:类名只是普通词语,在整个项目中按名称直接匹配会凭空创建关系,而非发现真实关系。
tokensave 与 CodeGraph 对比
tokensave 是对 CodeGraph(Node.js/TypeScript)进行全面重写的 Rust 版本。两者都为 AI 编码 Agent 构建语义代码图,但在范围和功能上存在显著差异。
| tokensave | CodeGraph | |
|---|---|---|
| 运行时 | 原生二进制文件(Rust) | Node.js 18+ |
| 安装 | brew install、cargo install、scoop install | npx @colbymchenry/codegraph |
| 语言 | 50+(3 个层级:lite/medium/full) | 19+ |
| MCP 工具 | 80+ | 9 |
| Agent 集成 | 12+(Claude、Codex、Gemini、Qwen、OpenCode、Cursor、Cline、Copilot、Roo Code、Zed、Antigravity、Kilo、Kiro、Kimi、Vibe、Grok、OMP、Pi、Plank、Factory Droid) | 1(Claude Code) |
| 索引时效性 | 每次 MCP 调用时按需检查陈旧状态;连接时追赶同步;预计多 Agent 协作使用 git worktree | 原生操作系统级文件监视器(FSEvents/inotify/ReadDirectoryChangesW,2 s 防抖);连接时追赶同步 |
| 多分支索引 | 支持,可选启用(每个分支使用独立数据库,支持跨分支差异比较/搜索) | 不支持 |
| 复杂度指标 | 从 AST 提取(分支、循环、嵌套深度、圈复杂度与认知复杂度、Halstead、可维护性指数、CRAP) | 不支持 |
| 移植工具 | 支持(port_status、port_order) | 不支持 |
| 图可视化工具 | 已移除(v4.0.1) | 支持 |
| 语义搜索 | Agent 驱动的关键词扩展(零成本) | 本地嵌入(通过 ONNX 使用 nomic-embed-text-v1.5) |
| MCP 资源 | 4 个(状态、文件、概览、分支) | 不支持 |
| MCP 注解 | 支持(readOnlyHint、alwaysLoad) | 不支持 |
| 死代码检测 | 支持 | 不支持 |
| 循环依赖检测 | 支持 | 不支持 |
| 类型层级 | 支持 | 不支持 |
| 上帝类 / 耦合分析 | 支持 | 不支持 |
| 提交 / PR 上下文 | 支持 | 不支持 |
| 测试映射 | 支持 | 不支持 |
| 重命名预览 | 支持 | 不支持 |
| Token 跟踪 | 每次调用的指标、实时 TUI 监视器、会话及生命周期计数器 | 不支持 |
| 代码健康分析 | 综合评分、Gini、依赖深度、DSM、按风险加权的测试缺口、会话差异 | 不支持 |
| 编辑原语 | 4 个原子写入工具(str_replace、multi_str_replace、insert_at、ast_grep_rewrite),并自动重新索引 | 不支持 |
| 崩溃韧性 | 在子进程中隔离提取过程;原生语法解析器中止时跳过该文件,同步继续 | 不支持 |
| 自行升级 | 使用稳定版 / 测试版渠道运行 tokensave upgrade | npm update |
| 数据库引擎 | libsql(SQLite 分支、WAL、异步) | better-sqlite3 / wa-sqlite(WASM) |
| 索引速度 | 1,782 个文件约需 1.2s | 1,782 个文件约需 4s |
| 二进制大小 | 压缩下载约 25 MB(内置所有语法) | 约 80 MB(node_modules + WASM) |
CodeGraph 开创了这一方法,若你偏好 npm 工具且只需要集成 Claude Code,它仍是一个可靠的选择。tokensave 在此基础上扩展了更深入的分析、更多 Agent、多分支支持,以及无需运行时依赖的原生二进制文件。
如需了解与 CodeGraph、Dual-Graph (GrapeRoot)、code-review-graph 和 OpenWolf 的详细比较,请参阅 docs/COMPARABLE-TOOLS.md。
并列对比页面(每个页面都会说明另一款工具在哪些方面更胜一筹): Serena · code-review-graph · Graphify · CodeGraph · token-savior · GrapeRoot · LeanCTX · OpenWolf — 索引见 tokensave.dev/vs。
tokensave 为何优于其他选择
有几种工具可以减少 AI 编码 Agent 的 Token 用量。以下是 tokensave 脱颖而出的原因。
单个原生二进制文件,零依赖
大多数替代方案都需要运行时:Python、Node.js,或两者兼有。tokensave 以单个 Rust 二进制文件的形式发布,内置 50 多种 tree-sitter 语法(压缩下载约 25 MB)。无需安装其他任何内容——与 Serena 等依赖 LSP 的工具不同,它无需为每种语言安装、启动或预热语言服务器。在打包方式上,如今有两个工具与 tokensave 不相上下:CodeGraph 内置了自己的运行时,LeanCTX 也是单个 Rust 二进制文件。
最深入的代码智能
tokensave 在符号层级运行:函数、结构体、字段、调用边、类型层次结构、复杂度指标。Dual-Graph(GrapeRoot)等替代方案在文件层级运行——它们知道有哪些文件,却无法回答“谁调用了这个函数?”或“如果我更改这个结构体,哪些内容会受影响?”tokensave 的 80 多种专用 MCP 工具涵盖调用图遍历、影响分析、死代码检测、测试映射、重命名预览、类型层次结构、循环依赖检测、复杂度排序、代码健康度分析(Gini、DSM、依赖深度、风险加权测试缺口)、原子编辑基元等。最接近的同类图工具 code-review-graph 提供 30 种工具;其他一些工具则出于有意的设计选择,提供不到 10 种。
最广泛的 Agent 支持
支持十多种 AI 编码 Agent 集成,并提供各 Agent 原生的配置格式。没有其他工具能以如此深入的集成覆盖这么多 Agent。Claude Code 可使用钩子、提示词规则和自动允许的工具权限。Kiro 支持全局 MCP 配置、作为资源加载的 tokensave.md 指引、内置宽松工具审批的托管 Agent,以及用于委派防护措施和写入后同步的钩子。Pi 支持 MCP 注册,并开放其规则所依赖的工具;还提供托管扩展,用于防护措施、节省量重置和会话回执。其他 Agent 则使用各自的原生配置格式注册 MCP 服务。
多分支索引
这是该领域中唯一支持按需为每个分支建立图数据库,并支持跨分支差异比较和搜索的工具。启用后,切换分支即刻完成——无需重新索引。
逐次调用的令牌跟踪
这是唯一能准确报告每次 MCP 工具调用节省了多少令牌的工具,还提供实时 TUI 监视器,可查看所有项目的数据和生命周期计数器。
完全开源
采用 MIT 许可的 Rust 项目,端到端均可审计。Dual-Graph 的核心引擎(PyPI 上的 graperoot)是专有软件——你无法查看它如何处理代码图。OpenWolf 使用 AGPL-3.0 许可证,要求衍生作品也必须开源。
性能
在包含 1,782 个 Rust/Java/Scala 混合代码文件的代码库上进行完整索引基准测试(57K 个节点,103K 条边):
| 工具 | 耗时 | 加速比 |
|---|---|---|
| CodeGraph (TypeScript) | 31.2s | 1x |
| tokensave (Rust) | 1.2s | 26x |
故障排查
“tokensave not initialized”
项目中不存在 .tokensave/ 目录。
tokensave init
MCP 服务无法连接
AI Agent 看不到 tokensave 工具。
- 确保 Agent 配置中包含 tokensave MCP 服务(运行
tokensave doctor) - 完全重启 Agent
- 检查
tokensave是否位于 PATH 中:which tokensave
搜索结果缺少符号
- 运行
tokensave sync更新索引 - 检查是否支持该语言(见上表)
- 确认该文件未被
.gitignore排除
索引速度慢
大型项目首次完整索引需要更长时间。
- 后续运行会使用增量同步,速度快得多
- 日常更新请使用
tokensave sync(不要使用--force) - Agent 连接期间,每次调用 MCP 工具时都会自动检查索引是否过时
为特定项目禁用 tokensave
如果项目过大,tokensave 占用的 RAM 过多,你可以在项目的环境中设置 TOKENSAVE_DISABLE_SERVER=true,以按项目禁用 MCP 服务。服务会在未初始化的情况下正常退出。
Claude Code — 添加到项目的 .claude/settings.json 中:
{
"mcpServers": {
"tokensave": {
"command": "tokensave",
"args": ["serve"],
"env": {
"TOKENSAVE_DISABLE_SERVER": "true"
}
}
}
}
其他 Agent — 在 Agent 用于启动 MCP 服务的配置中设置环境变量。
你也可以通过 shell 全局设置(TOKENSAVE_DISABLE_SERVER=true claude),但这会在整个会话中为所有项目禁用 tokensave MCP 服务。
DISABLE_TOKENSAVE=true 仍受支持,作为弃用的兼容别名,适用于在此变量加上命名空间之前创建的配置。
起源
本项目是对 @colbymchenry 编写的原始 CodeGraph TypeScript 实现的 Rust 移植版。移植版保留了相同的架构和 MCP 工具接口,同时借助 Rust 提升性能,并使用原生 tree-sitter 绑定。
构建
cargo build --locked --release # full (50+ languages, default)
cargo build --locked --release --features medium # medium tier
cargo build --locked --release --no-default-features # lite (smallest binary)
cargo test --workspace --locked # run all tests (requires full)
cargo check --locked --no-default-features # verify lite compiles
cargo clippy --workspace --all-targets --locked
开发命令使用调试构建;安装时仅使用优化后的发布产物(cargo install --path . --locked)。target/debug 绝不会作为安装输入。
Star 历史
赞助商
|
| Windows 免费代码签名由 SignPath.io 提供,证书由 SignPath Foundation 提供 |
许可证
MIT License——详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。