ai-memory解决AI编码CLI的上下文丢失问题,可在Claude Code中断后无缝切换到Codex继续任务,支持Linux/macOS/Windows,适合多工具切换的开发者。

AI 编码智能体的长期记忆。在任务中途退出 Claude Code,数小时后启动 OpenAI Codex 并进入同一目录,无需重新解释架构、失败的尝试或悬而未决的问题,就能继续工作。
LLM 编码智能体在会话结束后会丢失上下文。ai-memory 为它们提供了一个共享的持久化 Wiki,该 Wiki 由经过清理的生命周期观察记录编译而成。当一个会话结束时,相关的观察记录会成为一段连贯的摘要;下一个智能体会收到一个有边界的交接内容。可选的 ai-memory run 启动方式会增加一个便携式可见事件账本,以及原生每个 harness 的恢复功能,以实现更高的跨 harness 连续性。
该 Wiki 是 git 仓库中的纯 markdown——可 grep 搜索、可在 Obsidian 中打开、可通过 rsync 备份。无需维护向量数据库、无需调用 write_note 方法、无需手动加载上下文。完整设计见 docs/ARCHITECTURE.md;影响来源和先例见文末。
零摩擦生命周期捕获。钩子以即发即忘的方式发送有边界的、经清理的 prompt、工具生命周期和会话边界观察记录。直接启动保持这条轻量级路径;它不是完整的原生转录。用户 prompt 和压缩后摘要最多保留 16 KiB;通知和工具摘录最多保留 2 KB,每条观察记录正文有 16 KiB 的持久化后盾。
可选的托管工作流。ai-memory run claude,然后 ai-memory run codex --yolo,然后 ai-memory run command-code,透明地恢复一个逻辑工作流,包含原生每个 harness 的会话、一个便携式可见事件账本和全账本搜索。传递的数据包带有来源标记;Claude 转录导入会拒绝 Claude 持久化并通过工具读回的数据包。不带 harness 的 ai-memory run 会继续最新的可用 Claude Code、Codex、OpenCode、Pi、Crush、Kimi Code、Command Code 或 Kiro CLI v2/v3 会话(针对当前 checkout)。首次明确使用时,交互式启动器可以采用同一 checkout 的先前会话;之后的切换无法选择无关的原生历史记录。原生参数原样透传,但 --yolo 和 --fresh 由包装器拥有;直接命令不受影响。kimi-code 和 kimi-cli 是已安装 kimi 命令的接受别名;commandcode、cmdc 和 cmd 选择跨平台的 command-code 可执行文件(Windows 原生上为 cmdc);kiro-cli 选择已安装的 kiro-cli 命令。Kiro 默认为 v2;ai-memory run kiro --v3 选择 v3,而返回的链接 v3 工作流会透明地选择其引擎。
每个仓库的捕获排除。最近的 [capture] ignore_paths 策略标记会将匹配到的已知文件工具事件在到达本地缓冲池或服务器之前丢弃。见捕获策略参考。
可选的每个算子记忆槽。在共享服务器上,[slots] per_user = true 将引擎写入的 _slots/ 上下文保持在由认证算子派生的有界命名空间中。会话简介和合并 prompt 接收共享槽位加调用者自己的槽位;精确的 wiki 读取和搜索仍然是项目级别的,所以这是上下文注入隔离而非 RBAC。见多用户操作。
跨智能体交接。在任务中途退出 Claude Code,数小时后启动 Codex——下一个智能体会在其第一个 prompt 之前看到一个"上次离开的地方"区块。
项目级隔离。构建。每个项目位于 <wiki_root>/<workspace_id>/<project_id>/…,由稳定的 UUID 键控。工作区默认为"default"。项目派生自 $cwd:bootstrap、write-page、lint 等 CLI 子命令会走到主 git 仓库根目录,因此同一仓库的所有 worktree 共享一个项目标识;钩子路由器默认为 basename($cwd),可选择加入 repo-root 规则。在任意祖先目录中放置一个 .ai-memory.toml 标记文件即可显式覆盖任一字段——非常适合多客户咨询公司、工作/个人分离、mono-repos 或链接的 git worktree。相同页面路径可以存在于两个项目中而不会冲突;重命名是一列更新;清除是一句 rm -rf。
全局偏好范围。持久的用户/团队上下文——技术选型、代码风格、持久的个人规则——存在于保留的 _global 作用域中(memory_write_page 带 scope: "global")。默认的 memory_query 在每次读取时将其合并到每个项目中作为 global_scope_hits,因此偏好会随你进入新项目,而无需命名一个魔法项目或支付全项目 global=true 的扇出成本。事件捕获永远不会写入那里。
实体辅助召回。合并时将每个页面最多 10 个特定名词存储为规范实体:frontmatter。精确匹配、前缀匹配和复合词匹配形成一个项目范围的 RRF 流,因此即使页面的正文使用了不同的措辞,查询也能恢复该页面。该流是词法的,不会在查询时增加 LLM 调用。
权限感知召回。FTS5、实体匹配 RRF、图邻域 RRF 和可选的向量 RRF 按相关性生成候选结果。在截断之前,一个有界的调整会优先保留 _rules/、decisions/、procedures/ 和 gotchas/ 页面,而非紧密匹配的片段化会话证据。层级、固定以及明确的 canonical / active / source-of-truth 或 superseded / historical / test-fixture / do-not-answer-from 标签会有所贡献但不会成为绝对过滤器,因此有针对性的历史搜索仍能找到会话页面。这些信号仅影响检索来源;检索到的文本仍然是不可信的历史证据,永远不会因其命名空间、层级、标签、固定或排名而获得指令权威。
与代码智能工具清晰共存。在结构化 MCP 服务器、LSP 或其他实时代码工具旁边运行 ai-memory,无需同步它们的存储。用 memory 存储先前的决策、理由、失败的尝试、流程和交接;用当前 checkout 和结构化提供者存储符号、调用方、依赖项和影响分析。在行动前根据 checkout 验证历史代码声明,并将源代码、构建、测试和观察到的运行时行为视为操作事实。见历史记忆与实时代码智能。
Karpathy 风格 LLM Wiki。页面在会话结束时(或 PreCompact;没有真正会话结束事件的客户端可使用 ai-memory finalize-session --agent <agent> 进行手动最终关闭)从观察记录编译而来,而非从原始日志中检索。超链链 + git 版本化的 markdown 意味着你可以用 ai-memory checkpoints、restore-page 或原始 git log 进行时间旅行。
内置 /web 浏览器。Wiki 的只读 HTML UI——项目列表、文件夹树、FTS5 搜索、markdown 渲染、暗色模式。挂载在与 MCP 相同的 axum 服务器上。
服务器级 MCP 客户端活动。GET /admin/activity/by-client?since_days=7 显示哪些 MCP 客户端正在调用 memory 工具,分为读取和写入。计数使用有界的 UTC 日桶,因此任意客户端名称无法随请求量增长数据库;共享部署将此端点限制为根级。见 MCP 客户端活动。
多智能体 + 多机器就绪。支持以下客户端:Claude Code、Codex、Command Code、Devin CLI、OpenCode、Cursor、Claude Desktop(通过 mcp-remote)、Gemini CLI、Antigravity CLI、Grok Build CLI、Kimi Code、OpenClaw、Oh My Pi / OMP(omp / oh-my-pi)、Pi(通过生成的桥接扩展)、VS Code GitHub Copilot 智能体模式(仅 MCP,workspace .vscode/mcp.json)、Kiro CLI(MCP + v2 生命周期钩子)和 Zed(仅 MCP,用户 settings.json)。服务器可本地运行(loopback)或在家庭实验室机器上运行(LAN/VPN/云),使用 bearer-token 认证。共享服务器可选择加入 [auto_scope] 模式,实现每用户或会话感知的当前项目路由;Claude Code 有一个内置的可选桥接,通过 install-mcp --session-aware 实现。
Thin-client CLI。ai-memory status、bootstrap、checkpoints、restore-page、purge-project、rename-project、move-project、move-session、audit-contamination、lint、curator、auto-improve、auto-improve-report、pending-writes、embed、forget-sweep、backup、finalize-session 都是运行中服务器的 HTTP 客户端——从不直接操作 SQLite 或 wiki 文件。status 还会从最近一次真实的 Provider 调用中报告 LLM/embedding Provider 的被动健康状态。Server 是唯一的事实来源。finalize-session 通过 GET /admin/open-sessions 列出匹配的开放会话,然后向服务器回传合成会话结束钩子。在共享部署中,它默认使用调用者自身的会话加上无归属会话;root 可以传入 --all-owners 以进行跨操作员的显式恢复。当并发会话共享同一个 Agent 和作用域时,传入 --session-id <uuid> 可以定位一个确切的开放会话;该选项不能与 --all 组合使用。
LLM 是可选启用的。零 LLM 模式下你仍能使用 FTS5、手动声明的实体、图邻居搜索以及基于规则的综合分析。只有当你需要合并页面、lint 矛盾之处或分阶段自动改进提案时,才需要添加 Provider。
"退出 Claude Code,在 Codex 中继续同一项工作。" 当你需要原生会话恢复加上可移植的可视化历史,而不仅仅是一个摘要交接时,使用可选的托管启动器:
cd /path/to/project
ai-memory run claude
# 退出 Claude Code,然后在 Codex 中继续同一个工作流。
ai-memory run codex --yolo
# 在 Command Code 中继续,保留其自身的精确原生会话。
ai-memory run command-code
# 之后省略名称以恢复此处最新的可用托管会话。
ai-memory run
# 在同一个工作流中启动一个新的 Codex 会话,保留可移植历史。
ai-memory run --fresh codex
# Kiro 默认为 v2;显式选择其不兼容的 v3 引擎一次。
ai-memory run kiro --v3
"选择项目而不是记住它在哪里。" 从包含你检出的目录开始,在托管工具链之前先选择检出目标:
ai-memory show
# 不启动任何东西,输出机器可读的发现结果。
ai-memory show --json
每次成功的 ai-memory run 都会保存一个客户端本地的检出链接,以配置的 server 加上 workspace/project 为键。show 将这些链接与服务器的公开活动和页面计数元数据关联起来。还会对当前目录进行快速、有界的深度为 1 的扫描,以查找带有项目标记(.git、Cargo.toml、package.json、go.mod、pyproject.toml 等)的新检出,同时跳过依赖和构建目录。服务器从不暴露检出路径,因此两台客户端机器可以安全地为同一项目在远程家庭服务器上使用不同的本地路径。
列表始终以 + New project: 开头:输入一个名称,ai-memory 验证一个可移植的目录名称,私下暂存新的检出,在 .ai-memory.toml 中固定其 workspace 和 project,并为所选 Agent 安装路由块和托管 Agent Skills。只有当所有设置步骤成功后,最终目录才会出现,然后 show 从中启动。
工具链菜单只展示实际安装在主机上的 Agent,使用 run 在启动时强制执行的相同 PATH 查找规则。--no-scan 只使用保存的链接;--workspace 过滤两个来源;--yolo、--fresh 和尾部的原生参数原样转发。非终端使用必须传入 --json;JSON 模式仅用于发现,不会启动工具链。
首次显式运行可以提供来自此确切检出的现有会话或启动一个新会话。切换工具链会启动或恢复链接到共享工作流的原生会话,因此过时的本地会话无法替换更新的跨工具链历史。正常退出后,下一次启动会在上一个启动器仍在完成收尾时短暂等待;已处理的失败会立即释放工作流。如果链接的原生转录文本被删除,ai-memory 会在启动前检测到孤儿并重新开始;--fresh 强制为该工具链执行一次恢复。当前托管模式覆盖 Claude Code、Codex、OpenCode、Pi、Crush、Kimi Code、Command Code、Kiro CLI v2/v3、OMP、Grok Build CLI 和 Antigravity CLI;直接工具链启动方式保持不变。参见托管跨工具链工作流。
"让我回到刚才的地方。" 从任何目录出发,无需输入名称也无需读取列表:
ai-memory continue
它选择托管启动最近的检出,重新验证路径及其解析后的作用域,然后像裸 ai-memory run 那样在那里继续执行。如果某个链接的目录被移动、被替换、现在解析到不同的项目,或具有损坏的排序时间戳,则会在 stderr 上报告并跳过,因此恢复绝不会悄无声息地落在错误的项目中。--workspace 缩小搜索范围;--yolo 和 --fresh 被转发。
"下午 4 点退出,早上 9 点在不同的 Agent 中继续。" 经典场景。下一个支持的钩子客户端中的 SessionStart 钩子会预先添加一个带有关闭问题、下一步和会话摘要的类型化交接。Grok 捕获生命周期事件但忽略 SessionStart stdout,因此从交接恢复时请让它调用 memory_handoff_accept。Zero 具有相同的 no-stdout 行为,也必须调用 memory_handoff_accept。
"下午4点下班,早上9点在另一个智能体继续。" 经典场景。下一个支持的 hook 客户端中的 SessionStart hook 会 prepend 一个带有开放问题、下一步和会话摘要的类型化交接。Grok 捕获生命周期事件但忽略 SessionStart stdout,所以从交接恢复时要让它调用 memory_handoff_accept。Zero 也有相同的 no-stdout 行为,也必须调用 memory_handoff_accept。
"六周前我们对 X 做了什么决定?" 在智能体中使用 memory_query X 进行 FTS5 融合实体匹配和链接页面扩展的查询(配置了 embedder 时还加上向量相似性)。快速终端-only FTS5 查找用 ai-memory search X;该管理命令不运行混合流。页面由 LLM 合并,所以命中的结果是一个连贯的决策页面,而不是原始聊天日志。传 explain: true 可以看每个命中在项目或显式范围检索中的排名原因。跨项目 global: true 搜索使用其独立的 FTS-only 排序器,并报告该活动流而不提供每个命中的 RRF 详情。
"六周前我们对 X 做了什么决定?" 在智能体中使用 memory_query X 进行 FTS5 融合实体匹配和链接页面扩展的查询(配置了 embedder 时还加上向量相似性)。快速终端-only FTS5 查找用 ai-memory search X;该管理命令不运行混合流。页面由 LLM 合并,所以命中的结果是一个连贯的决策页面,而不是原始聊天日志。传 explain: true 可以看每个命中在项目或显式范围检索中的排名原因。跨项目 global: true 搜索使用其独立的 FTS-only 排序器,并报告该活动流而不提供每个命中的 RRF 详情。
"永久记住这个。" 当有些东西值得超越自动捕获的会话日志而保留时——一个决策、一个约定、一个坑——告诉智能体 "保存一条永久笔记,我们标准化使用 Postgres 做 X" 或 "标注这作为项目规则",它调用 memory_write_page 写一个持久的、git 版本化的 wiki 页面。在终端中是 ai-memory write-page --path decisions/0007-db.md --body $'# Standardised on Postgres\n\n...' --pinned。--pinned 使其免于衰减扫描;--body 第一行的 H1 成为页面标题(省略 --title——它仍被接受,但 LLM 调用者通过它进行 JSON 转义时会遇到困难,见 issue #67)。与交接(一次性)或自动综合的会话页面(在合并时重写)不同,write-page 笔记是你的:它出现在 memory_query 中,在 /web 中渲染,并保留到你修改它为止。
"永久记住这个。" 当有些东西值得超越自动捕获的会话日志而保留时——一个决策、一个约定、一个坑——告诉智能体 "保存一条永久笔记,我们标准化使用 Postgres 做 X" 或 "标注这作为项目规则",它调用 memory_write_page 写一个持久的、git 版本化的 wiki 页面。在终端中是 ai-memory write-page --path decisions/0007-db.md --body $'# Standardised on Postgres\n\n...' --pinned。--pinned 使其免于衰减扫描;--body 第一行的 H1 成为页面标题(省略 --title——它仍被接受,但 LLM 调用者通过它进行 JSON 转义时会遇到困难,见 issue #67)。与交接(一次性)或自动综合的会话页面(在合并时重写)不同,write-page 笔记是你的:它出现在 memory_query 中,在 /web 中渲染,并保留到你修改它为止。
"你找到的那个页面已经过时了。" 智能体调用 memory_feedback 并传入页面路径和一个信号:helpful / not_helpful 调整保留强度来保持扫描符合条件的片段页面(它们移动其显著度,缩放衰减公式的时间项),而 stale / wrong 使显著度降低,使任何当前页面在下次 memory_lint 报告中显示为 feedback_flagged 发现。反馈从不删除任何内容——它降低置信度并标记供审查——并且它附加到记录反馈时的当前版本,所以后续重写会清除标志。检索到的页面文本不受信任,不能单独授权反馈。
"你找到的那个页面已经过时了。" 智能体调用 memory_feedback 并传入页面路径和一个信号:helpful / not_helpful 调整保留强度来保持扫描符合条件的片段页面(它们移动其显著度,缩放衰减公式的时间项),而 stale / wrong 使显著度降低,使任何当前页面在下次 memory_lint 报告中显示为 feedback_flagged 发现。反馈从不删除任何内容——它降低置信度并标记供审查——并且它附加到记录反馈时的当前版本,所以后续重写会清除标志。检索到的页面文本不受信任,不能单独授权反馈。
"记住这个,但只保留到 sprint 结束。" 传 expires_at 给 memory_write_page(RFC3339 或 YYYY-MM-DD = 该天结束,UTC)—— 或手动在页面的 frontmatter 中放 expires_at:。超过 TTL 后,页面从搜索/最近/简报中消失(传 include_expired: true 给 memory_query 仍可查看),下一次 forget 扫描会硬删除文件及其行。TTL 优先于 pin;memory_lint 会警告 pinned+expiring 组合。
"记住这个,但只保留到 sprint 结束。" 传 expires_at 给 memory_write_page(RFC3339 或 YYYY-MM-DD = 该天结束,UTC)—— 或手动在页面的 frontmatter 中放 expires_at:。超过 TTL 后,页面从搜索/最近/简报中消失(传 include_expired: true 给 memory_query 仍可查看),下一次 forget 扫描会硬删除文件及其行。TTL 优先于 pin;memory_lint 会警告 pinned+expiring 组合。
"这个新项目在 ai-memory 之前有数月历史。" cd /path/to/my-project && ai-memory bootstrap 收集 git log、README、docs/、module headers、project rules 并将它们一次性总结为 seed wiki 页面。未来的会话将建立在此基础上。
"这个新项目在 ai-memory 之前有数月历史。" cd /path/to/my-project && ai-memory bootstrap 收集 git log、README、docs/、module headers、project rules 并将它们一次性总结为 seed wiki 页面。未来的会话将建立在此基础上。
"那个会话教会了什么持久教训?" 当配置了 LLM provider 时,ai-memory 在每个项目中为新完成的会话运行后台 auto-improvement scheduler。它在 pending-writes 审计跟踪中记录提议的 wiki 编辑,然后默认通过正常 wiki 写入路径立即批准。Scheduler tick 不重叠:如果审查所有项目的时间比间隔长,下一个 tick 会延迟到当前一个完成。调度和批准是分开的:设置 [auto_improve.scheduler] enabled = false 可停止自动审查,或设置 [auto_improve] require_approval = true 可保持调度和手动提议待人类审查。ai-memory auto-improve --session-id <uuid> 和 MCP memory_auto_improve 仍可用于手动追赶或定向重运行。当其 session_id 是