关于 Aletheia
Aletheia 为编码 Agent 提供项目记忆,将记忆声明关联到源代码证据,并在每次回忆时重新检查。它帮助团队避免依赖过时的代码事实,还可提供相关文件地图和行号。
主要功能
- 01为每条记忆关联代码证据
- 02每次回忆时重新验证证据
- 03隐藏过时声明并标记已移动代码
- 04生成含相关文件和行号的项目地图
- 05以 Markdown 文件保存共享记忆
适用场景
- 01在编码会话之间保留经验证的项目事实
- 02查找回忆内容对应的当前源码行
- 03避免使用已被代码变更推翻的记忆
- 04在团队中共享项目记忆
MCP 相关
通过 stdio 提供 recall、remember、get 和 verify 四个 MCP 工具。不支持 MCP 的 Agent 可使用命令行界面。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
4收录的工具列表 · 更新于 4 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| tag | string | 否 | |
| full | boolean | 否 | |
| query | string | 否 | |
| stale | boolean | 否 | |
| budget | number | 否 | |
| session | string | 否 |
详细介绍
让编码 Agent 能验证的记忆。
每条记忆都附有来自代码的证据。Aletheia 每次召回时都会重新检查,
为 Agent 指明确切的代码行,并阻止过时事实进入上下文。
问题
编码 Agent 会忘记不同会话之间的一切,因此每次都会重新阅读相同的文件。记忆工具能解决遗忘问题,但它们按相似度对记忆排序,而过时的记忆看起来和取代它的事实同样相关。于是 Agent 会基于几周前就已不再成立的信息继续工作。一条看似可信却错误的记忆,比没有记忆更糟。
工作原理
- 记忆附有证据。 每条记忆都是一项声明及其锚点:必须仍然存在的函数、必须仍然匹配的代码行,以及必须仍然存在的文件。
- 每次召回都会检查证据。 检查是机械式的:不调用模型、不使用嵌入、不访问网络。证据失效的记忆会对 Agent 隐藏,并附上一行说明。
- 跟踪移动的代码。 当 Go 声明原样移至另一个文件时,其记忆会以
[moved]状态返回,并显示新位置,而不会变得过时。 - 召回结果会指向代码行。
builtin_test.go:263这样的指针会根据当前文件计算得出,因此 Agent 可以直接打开正确的代码行,无需搜索。 - 地图会自动生成。 Agent 停止时,Aletheia 会读取会话记录,并记录任务改动过的文件。同类下一项任务会从这些文件开始,Agent 无需花回合记录这些内容。
- 不会删除任何内容。 被取代的记忆会标记为已取代,长期过时的记忆则由
aletheia lethe(Lethe,遗忘之河)归档。
快速开始
1. 安装,选择适合你的方式即可。每种方式都会提供同一个独立二进制文件:
npm install -g @firatmio/aletheia # Node 18+, any OS
go install github.com/firatmio/aletheia/cmd/aletheia@latest # Go 1.24+
scoop bucket add firatmio https://github.com/firatmio/scoop-bucket; scoop install aletheia # Windows
brew install --cask firatmio/tap/aletheia # macOS, Linux
Linux、macOS 和 Windows 的预编译压缩包见发布页面。
2. 连接你的 Agent。
Claude Code,使用插件(推荐)。 插件包含 MCP 服务和两个钩子。接着运行 /aletheia:setup 初始化项目:
/plugin marketplace add firatmio/aletheia
/plugin install aletheia@aletheia
/aletheia:setup
Claude Code,不使用插件。 自行设置项目并添加两个钩子。之后每次提交提示词时都会触发回忆,且不会消耗 Agent 的资源:
cd your-project
aletheia init --agents --claude-hooks # .aletheia/, usage notes in CLAUDE.md and AGENTS.md, hooks in .claude/settings.json
aletheia hook --dry-run # what an agent would get (add a prompt to try one); changes nothing
请自行运行 --claude-hooks。通常不允许 Agent 修改自己的钩子,这是有意为之。如果已安装插件,请勿添加这些钩子:插件已包含相同的两个钩子。init 会检测到插件并提示你。若要改为手动编辑文件,请使用:
{
"hooks": {
"UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "aletheia hook" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "aletheia hook" }] }]
}
}
其他 Agent。 Cursor、VS Code、Claude Desktop 和 Codex 通过 MCP 连接;不支持 MCP 的 Agent 则使用命令行。请参阅下方的其他 Agent。使用 npx 配置的 MCP 客户端无需安装:{"command": "npx", "args": ["-y", "@firatmio/aletheia", "serve"]}。
Agent 也可以按照Agent 指南自行完成设置。指南会将钩子步骤交给你,只需运行这一条命令。
记忆以纯 Markdown 文件的形式存放在 .aletheia/memories/*.md 中。提交这些文件后,你的团队和每个 Agent 都能共享同一份记忆,并在每台机器上验证其有效性。
**升级:**运行 npm update -g @firatmio/aletheia、scoop update aletheia 或 brew upgrade --cask aletheia。使用 Go 时,再次运行相同的 go install 命令。使用 claude plugin update aletheia@aletheia 更新插件。
- **运行的版本:**钩子会立即使用新版二进制文件。MCP 服务会继续使用旧版,直到 Agent 重启。
- **在 Windows 上使用
go install时,**运行中的 Agent 会通过 MCP 服务保持aletheia.exe打开,因此安装会因“文件正在使用”而失败。请先退出 Agent,或将旧二进制文件移到一旁;Windows 允许移动正在运行的 exe 文件。
每次升级都可以使用以下方法。它会删除不再使用的旧副本,随机名称也不会与仍在运行的副本冲突:
$bin = "$(go env GOPATH)\bin"
Remove-Item "$bin\aletheia-old*.exe" -ErrorAction SilentlyContinue
Rename-Item "$bin\aletheia.exe" "aletheia-old-$(Get-Random).exe"
go install github.com/firatmio/aletheia/cmd/aletheia@latest
结果
我们在真实代码仓库上使用无头 Claude Code(Opus 5.5)进行了测量。每项任务分别在使用和不使用 Aletheia 的情况下运行,并通过相同的隐藏验收测试判定是否成功。
| 代码仓库 | 任务 | 成本 | 另外 | 通过的任务 |
|---|---|---|---|---|
| gohugoio/hugo,大型站点生成器(23.3 万行 Go 代码) | 5 种类型的任务各 14 项,每项运行一次 | −15%:其中一种类型的 7 项任务降低 22%,混合任务降低 7% | 输入令牌 −27%,轮次 −21% | 14/14,与未使用时相同 |
| expr-lang/expr,中型表达式语言 | 7 项任务,运行两次 | 两次均为 −9% | 首次编辑前读取的代码 −48% | 14/14,与未使用时相同 |
| go-chi/chi,小巧整洁的路由器 | 7 项小任务,运行两次 | +5% 和 −5%:持平 | 14/14,与未使用时相同 |
在中型和大型代码库中,找到合适位置的成本较高,因此 Aletheia 更有帮助;当相同类型的改动再次出现时,效果最明显。日常工作可参考混合任务的结果。对于 Agent 一两次调用就能读完的小型包,节省空间不大。测量方法、原始数据和未奏效的做法见 docs/dogfood-4.2.md。
参考
锚点
| 锚点 | 在什么情况下有效 | 示例 |
|---|---|---|
symbol:PATH::NAME | 文件仍声明该函数、方法(Type.Method)、类型、变量或常量时 | symbol:store.go::Store.Get |
contains:PATH::REGEX | 文件仍匹配该正则表达式时 | contains:go.mod::^go 1\.23$ |
exists:PATH | 路径仍存在时 | exists:src/auth |
file:PATH | 文件内容未更改时(保存时会封存哈希值) | file:go.mod |
- 对单个声明的主张使用
symbol,对文件中的单个事物使用contains。只有在任何更改都应触发重新检查时,才使用file。 - Recall 会显示
symbol和contains证据当前所在的位置,例如(store.go:15-21)。Go 声明的完整范围由go/parser获取。在其他语言中,symbol锚点会根据关键字(如function、class、def、fn等)找到声明所在行;它并非密封锚点,因此无法跟随代码移动。 - 移动代码。 Go 的
symbol锚点会使用声明的指纹进行密封(symbol:store.go::Store.Get@3f9a…)。指纹会忽略注释和排版。- 原地编辑: 永远不会使锚点失效。只要声明仍在原文件中,就根本不会检查指纹。
- 声明被移动: 如果声明离开原文件,Aletheia 会在项目中搜索它。如果恰好有一个同名声明的指纹与之相同,记忆会以
[moved: old.go → new.go]的形式返回,并附上新行号;verify <id> --reseal会记录新路径。 - 无法确定的情况仍会过期并隐藏: 代码在移动过程中发生变化、存在多个匹配副本,或主张点名了旧文件。
- Go 代码中的
contains锚点: 如果某个锚点在单个声明中匹配,remember会为该声明添加一个密封的symbol锚点。随后contains锚点会随声明移动,但只有当其模式在新位置仍与该声明内的内容匹配时才会如此。
- 在
contains模式中,一串空格可以匹配任意数量的空格或制表符,因此重新排版不会使其失效。 - 主张中提到的文件会自动获得一个
exists:锚点。 - 让锚点指向路径:描述代码的作用(“Tokens are issued by IssueToken”),而不是代码的位置。点名符号所在文件的主张会在代码移动时失效,保存时
remember会说明这一点。 - 如果
contains锚点只匹配到注释,remember会发出警告,因为注释可能保持不变,而代码已经发生变化。 - 没有锚点的记忆会以
[?]形式返回,排序低于已验证的事实,并会在 90 天后过期,除非再次确认。
记忆过期时,重新检查主张,然后:
aletheia verify 3f9a1c --reseal # still true: refresh the evidence
aletheia remember "…new claim…" --anchor … --supersedes 3f9a1c # changed: replace it
如果 contains、exists 或 symbol 锚点不再成立,--reseal 会拒绝操作,因此错误主张无法在无提示的情况下被认可。
代码地图
aletheia map "<topic>" 会列出与某个主题最相关的文件,并附上各文件中的关键声明及其当前行号:
optimizer/fold.go: fold.Visit 15-311, fold 10-13, toFloat 329-335
builtin/builtin.go: Builtins 35-1081, Index 18
文件首先按照其路径和声明名称与主题的匹配程度排序,排序方式与 Aider 的仓库地图相同。隐藏文件、依赖文件和生成文件会被跳过。对于有关构建、测试或发布的问题,以及不指定主题的概览,地图会从构建文件开始:build and CI: go.mod, Makefile, scripts/, .github/workflows/ci.yml。钩子会在会话的第一个提示词中发送地图,大小根据项目而定:源文件少于 25 个时不发送,之后发送 300 或 600 个令牌(可通过 --map-budget N 覆盖)。
其他 Agent:Claude Desktop、VS Code、Cursor、Codex、Aider
Aletheia 通过标准输入输出使用 MCP,提供四种工具(recall、remember、get、verify),也可作为普通 CLI 使用,因此任何能够运行 shell 命令的 Agent 都可以使用它。
{
"mcpServers": {
"aletheia": { "command": "aletheia", "args": ["serve", "--dir", "/absolute/path/to/your-project"] }
}
}
如果没有全局安装,请使用 "command": "npx", "args": ["-y", "@firatmio/aletheia", "serve", "--dir", "…"]。服务会从 --dir 指定的位置,或从客户端启动它的目录查找 .aletheia/。如果项目中没有该目录,这些工具会说明如何设置,而不会报错;运行 aletheia init 后即可开始工作。
记忆文件
---
id: "3f9a1c"
claim: "Auth tokens are issued by IssueToken, HS256 with a 15 minute expiry"
confidence: 0.8
status: "active"
source: "claude-code"
created: "2026-10-21T09:12:44Z"
updated: "2026-10-21T09:12:44Z"
tags:
- "auth"
anchors:
- "symbol:src/auth/jwt.go::IssueToken@7370a7fe3669256c"
- "contains:src/auth/jwt.go::jwt\\.SigningMethodHS256"
---
Refresh tokens are handled separately, by RefreshToken.
@7370a7fe3669256c 后缀是经过封存的指纹;如果 IssueToken 移动,它能让这条记忆跟随其移动。
可以手动编辑记忆,在拉取请求中审查,也可以用 grep 搜索。它们只是文件。
CLI
aletheia init [dir] [--agents] [--claude-hooks]
aletheia remember <claim> [--anchor SPEC]... [--body TEXT|-] [--tag T]... [--ttl 30d]
[--confidence 0.8] [--supersedes ID]... [--source NAME] [--force]
aletheia remember - [--source NAME] [--force] # several at once: one JSON object per line on stdin
aletheia recall [query] [--budget N] [--limit N] [--full] [--stale] [--tag T] [--session ID] [--json]
aletheia get <id> [--json]
aletheia verify [id] [--reseal] [--ttl 30d] [--json] # exits 1 if anything is stale (CI-friendly)
aletheia map [topic] [--budget 600]
aletheia hook [--budget N] [--map-budget N] [--dry-run [prompt]] # Claude Code hook; every command takes --help
aletheia lethe [--days 30] [--apply] [--json] # archive superseded and long-stale memories
aletheia stats [--json]
aletheia serve [--dir DIR] # MCP server on stdio
aletheia version
每个命令都支持 --help,也支持 --dir DIR(或 ALETHEIA_DIR),以便从其他位置指定项目。
如果声明与现有记忆重复或高度相似,remember 会以退出码 3 退出,并指出对应记忆,让 Agent 可以用 --supersedes 取代它。
remember - 可在一次调用中保存多条记忆。每行标准输入都是一个 JSON 对象,包含 MCP 工具所需的键;每条记忆会单独保存:
aletheia remember - <<'EOF'
{"claim": "Builtins are registered in builtin/registry.go", "anchors": ["symbol:builtin/registry.go::Builtins"]}
{"claim": "go.mod targets Go 1.18", "anchors": ["contains:go.mod::^go 1\\.18$"], "tags": ["toolchain"]}
EOF
它会按顺序逐行打印结果。全部保存成功时退出码为 0;只有冲突导致失败时退出码为 3;其他情况退出码为 1。正则表达式在经过 shell 时即使其中的 \\ 变成了 \(1\.18),仍会被接受。MCP remember 工具接受与 memories 相同的对象。
安全
- **绝不执行任何内容。**锚点只读取文件;没有“运行此命令以验证”的锚点。
- **操作范围不超出项目。**锚点路径均为相对路径,无法逃出根目录,包括通过符号链接逃出。
- **记忆是数据,不是指令。**MCP 服务会告知 Agent 这一点,
CLAUDE.md/AGENTS.md中的说明也会再次强调。 - **无网络、无遥测、无依赖。**这是一个仅使用 Go 标准库的静态二进制文件。它启动的唯一程序是在
init期间运行的git check-ignore,用于检查 CLAUDE.md 是否被忽略。 - **隐私:**Aletheia 不收集任何信息。钩子会在你的机器上读取提示词和会话记录,代码地图记忆会在
.aletheia/中保留提示词的缩短副本。详见隐私政策。
路线图
- 以证据为锚点的记忆,每次召回时都会检查
- 召回钩子、实时行指针、代码地图,以及由 Stop 钩子生成的任务地图
- 基准测试工具,可在真实代码仓库中进行配对运行
- 跟随指纹移动的 Go 代码(
[moved]) - 预编译二进制文件、npm、Homebrew 和 Scoop;Claude Code 插件;已列入 MCP Registry
- 封存的
symbol锚点,以及 Go 之外的[moved]:优先支持 TypeScript/JavaScript 和 Python -
aletheia doctor:查找持续失效的锚点,并建议更稳固的锚点 - 使用更多代码仓库和重复变更类型进行更长时间的基准测试
- 用于个人偏好的全局跨项目记忆
每个版本的变更内容见 CHANGELOG.md。
贡献
欢迎提交问题和拉取请求。请参阅 CONTRIBUTING.md 和行为准则。如果 Aletheia 误导了你的 Agent,填写“An agent was misled”问题表单是最有用的反馈方式。请按照 SECURITY.md 中的说明,私下报告安全问题。
许可证
Apache-2.0 © Fırat Tuna Arslan
ἀ-λήθεια:真理,字面意思是“未被遗忘”
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。