简体中文 | English
属于项目、不属于任何厂商的本地记忆层。 Memory is always complete. Retrieval is always yours to shape. 记忆始终完整收录;检索边界由你划定。
你和 AI 聊了 3 天的方案,不应该随关窗消失。它属于项目,属于下一个接手的人。
GIF 无声音——完整配音版(中文/英文 + 手机竖版)在 Releases · v0.2.2 页面内可直接播放。
| 痛点 | 会话接力的答案 |
|---|---|
| 跨时间失忆:新会话问"上周讨论的方案?"——AI 不知道 | 按需检索历史会话,带出处 |
| 跨工具断裂:Claude Code 定的方案,ZCode 不知道 | 双源同库,任何 agent 通过 MCP 查同一份记忆 |
| 跨人交接:你和 AI 聊了 3 天,接手的人只能"去看代码" | 导出 .hop 交接包,对方的 AI 立刻拥有全部上下文 |
这是最核心的设计决策,不是功能差异,是存储粒度的架构差异:
| claude-mem | SessionRelay | |
|---|---|---|
| 存储单位 | 记忆片段(压缩摘要,跨会话打散混合) | 会话(完整对话,有标题/时间线/来源/状态/决策) |
| AI 看到的 | 一堆"你之前说过…"碎片 | "根据 8 月 28 日 ZCode 会话《数据库选型》第 12 条…" |
| 幻觉风险 | 高:上下文污染 + 压缩失真 + 无法溯源 | 结构性抑制:出处强制 + 按需查询 + 原文可回跳 |
三个反幻觉设计(不是功能,是架构承诺):
- 出处强制:AI 回答必须带"哪个会话/哪条消息/哪个 agent"——有源可查,不能瞎编
- 按需查询(pull):AI 不问就不查 → 上下文干净,不被无关记忆污染
- 原文可回跳:AI 拿到的是原始对话全文,不是压缩摘要——决策的"为什么"完整保留
你和任何 AI 工具聊的内容,被统一收进一个项目级数据库;你、AI、同事都能查。换工具不丢记忆,换人可交接。
graph TB
subgraph Sources["🖥️ 你的 AI 编程工具(各聊各的)"]
CC["Claude Code<br/>JSONL 文件"]
ZC["ZCode<br/>SQLite 数据库"]
CX["Codex<br/>JSONL 文件"]
QD["Qoder<br/>JSONL 文件"]
TR["Trae<br/>部分支持*"]
end
subgraph Relay["🧠 会话接力(本地记忆层)"]
DAEMON["守护进程 watch<br/>每 30 秒自动同步"]
DB[("relay.sqlite<br/>统一记忆库")]
EXTRACT["结构化提取器<br/>决策 · 话题 · 摘要 · 关键往返"]
end
subgraph Consumers["👥 谁来查询记忆"]
YOU["你(CLI)<br/>search · decisions · history"]
AGENT["AI Agent(MCP)<br/>16 个工具"]
TEAM["同事(HOP 交接包)<br/>export → import"]
end
CC -->|adapter| DAEMON
ZC -->|adapter| DAEMON
CX -->|adapter| DAEMON
QD -->|adapter| DAEMON
TR -.->|仅用户提问| DAEMON
DAEMON --> DB
DB --> EXTRACT
DB --> YOU
DB --> AGENT
DB --> TEAM
style Relay fill:#1a1a2e,color:#e94560
style Sources fill:#16213e,color:#fff
style Consumers fill:#0f3460,color:#fff
* Trae 的 AI 回复端到端加密,仅能采集用户提问。其他工具不在列表里?写一个自定义适配器即可,零改核心代码。
每个会话在记忆库中经历两阶段判定,宁可多等,不固化没聊完的对话:
stateDiagram-v2
[*] --> active: 对话开始/守护捕获
active --> pending_end: 超过10分钟没新消息
pending_end --> active: 你回来继续聊(复活)
pending_end --> confirmed: 安静超过6小时
active --> active: 新消息追加
confirmed --> active: 追加新消息(回滚+摘要重算)
confirmed --> archived: srelay archive(归档)
archived --> active: 新消息到达(复活)
confirmed: ✅ 已固化
confirmed: 提取决策/话题/摘要
confirmed: 进入全文搜索主索引
archived: 📦 已归档
archived: 骨架保留(决策/话题)
archived: 正文已释放(99.4%空间)
为什么需要中间的 pending 状态:对话可以复活(第二天 --resume 继续)。如果直接固化,提取的决策就是残缺的。pending 是 6 小时缓冲带;就算固化了,追加消息也会自动回滚重算。原始会话文件是唯一事实源——库里任何时候都能 srelay rebuild 重建。
- 五源适配:Claude Code · ZCode · Codex · Qoder(完整支持)+ Trae(部分:仅用户提问)+ 自定义适配器(加一个 JS 文件接入新工具,零改核心代码)
- 三档隐私:
full(默认) /meta(只存元数据) /off(仅手动) .sessionrelayignore硬边界:隐私排除对自动捕获、手动 save、导出全部生效- 两阶段判定:
active → pending_end → confirmed,resume 自动回滚,原始会话文件是唯一事实源(库随时可rebuild) - 历史回填:
srelay init默认回填近 30 天;srelay sync --backfill all一条命令全量入库
- jieba 分词 + FTS5 双索引(正文 + 元数据),AND 覆盖度语义,OR 兜底
- 语义检索(可选):
srelay semantic enable一键开启——换一种说法也能命中("登录"↔"认证"、"很卡"↔"性能"),本地 CPU 推理(bge-small-zh),字面命中优先、语义只做补充,未启用时行为与纯字面检索完全一致 - jieba 分词 + SQLite FTS5 双索引(六条中文验收用例门禁)
- 会话级 AND 覆盖 + OR 兜底:连写词拆分("认证方案"→ 认证+方案)、短语精确匹配(
"按月分区") - 每条结果强制携带出处块(会话 ID / 来源 agent / 日期 / 消息序号 / 摘要片段)
任何支持 MCP 的 AI agent 接入后,从此在这个项目里不再是失忆的:
9 个读工具——AI 从此能回答的问题
| 工具 | 回答的问题 |
|---|---|
search_sessions |
"我们之前讨论过 X 吗?"(中文全文 + 元数据过滤) |
get_session_detail |
"那场讨论具体聊了什么?"(完整消息,支持范围) |
list_sessions |
"这个项目都聊过哪些话题?" |
get_decisions |
"为什么决定用 X 而不是 Y?"(全部已确认决策,带出处) |
get_file_history |
"这个文件为什么这么写?"(跨会话文件讨论史) |
suggest_related_sessions |
"还有哪些讨论和这个相关?"(算法发现的同主题会话,可解释理由) |
get_unresolved |
"还有什么没定的?"(未决问题清单) |
get_stats |
"记忆库什么状态?"(会话数/来源分布/体积) |
set_scope |
检索边界逃生口 |
7 个写域工具——AI 不再只是读者
| 工具 | 能力 | 安全边界 |
|---|---|---|
annotate_session |
给会话打标签 / 写人工摘要 | 只改元数据,不改写对话 |
save_note |
AI 把结论写成笔记(决策句式直接入决策库) | source=note,可识别可审计 |
export_handoff |
生成 .hop 交接包 | 只读导出 |
import_handoff |
导入交接包(sha256 校验 + 归化) | 默认隔离模式(正文待放行) |
release_quarantine |
放行隔离会话正文 | 需显式调用 |
link_sessions |
建立会话关联(continues/related/pinned) | 关联可查可撤销 |
get_linked_sessions |
双向查询会话关联(出边/入边) | 只读 |
写域三原则(D21):旁路写入(不碰状态机)· 导入默认隔离 · 笔记可溯源——每条 AI 写入都能被识别、审计、撤销。
- B 档:
scope.json项目契约(CLI 与 MCP 共用),交集语义只能收窄 - A 档:auto-scope 兜底(MCP 侧近 30 天可配),防上下文污染
- attach:开新会话前挂载指定历史会话(最高优先级谓词)
- 热更新:scope 改动下一次调用立即生效
AI(MCP 工具)永远没有删除能力——删除是人的特权。需要时由你亲手执行:
srelay forget a3f8c2d1 # 预览:将删除什么、保留什么
srelay forget a3f8c2d1 --yes # 执行:整条会话彻底消失(含决策),不可逆
srelay forget --history # 审计:什么时候删了什么- 选型口诀:空间与老化用
archive(保留决策骨架);让一条对话彻底消失、永不回来,用forget - 双防复活闸:
.sessionrelayignore精确规则(主,跨 rebuild 存活)+ 墓碑表(次,防 ignore 被清理)——原始文件还在磁盘,但本库永不重新收录 - 前缀歧义防护:前缀命中多个会话时列出候选拒绝执行,绝不静默猜一个
- 注意:forget 是项目级操作;已通过
.hop交接包交出去的记忆不在管辖内(删除权已随包交出)
- 独立协议规格(MIT,产品中立,欢迎第三方实现读取器)
- sha256 逐文件完整性校验(篡改整体拒绝)
- 默认密钥脱敏:AWS key / 私钥 / Bearer / 密码赋值 / 数据库连接串 + 脱敏报告
- 隔离导入(quarantine):只入元数据与摘要,正文经
release逐条放行——反 prompt 注入的结构性防线 - HANDOFF.md 自动生成(决策表 / 涉及文件 / 未解决问题 / 时间线 / 页脚署名)
- 跨项目导入:交接包可导入到任何路径/名称的项目(自动归化,
origin_project溯源)
一次真实的交接是这样流动的:
sequenceDiagram
participant 张三 as 张三(离开)
participant 包 as .hop 交接包
participant 小王 as 小王(接手)
participant AI as 小王的 AI
张三->>包: srelay export --all
Note over 包: 自动:脱敏密钥<br/>生成 HANDOFF.md<br/>逐文件 sha256
包->>小王: 发送文件(微信/邮件均可)
小王->>包: srelay import xxx.hop --from 张三
Note over 小王: 自动:校验完整性<br/>归化 project_id<br/>记入审计
小王->>AI: "为什么数据库选了 PG?"
AI->>包: get_decisions()
包-->>AI: "决定采用 PostgreSQL(出处:张三 08-20 会话)"
AI-->>小王: 带出处的完整回答
要求 Node ≥ 22(Windows / macOS / Linux):
# 方式一:npm 安装(推荐)
npm install -g @ewanjasper/sessionrelay
# 方式二:零安装试用
npx @ewanjasper/sessionrelay init
# 方式三:从源码
git clone https://github.com/EwanJasper/SessionRelay.git
cd SessionRelay && npm install && npm run build && npm linkcd 你的项目
srelay init # 初始化 + 回填近 30 天(1 分钟内可搜到上月讨论)
srelay sync --backfill all # 或全量回填所有历史(旧会话自动确认+提取决策)srelay search 中文关键词 [--topic --source --since --json]
srelay decisions # 全部已确认决策(带出处,可回跳)
srelay history src/db/ # 该文件被哪些会话讨论过
srelay watch --install-service # Windows 注册守护,登录自启
srelay doctor # 环境自检srelay export --all # 交接包(默认脱敏)→ 发给同事
# 同事在他的项目根(任何路径):
srelay import xxx.hop --from 你的名字👉 完整实操指南(五个场景:项目交接/新人入职/安全导入/跨项目迁移/定期归档):导入导出指南
ZCode 在上下文压缩时会物理删除旧消息(实测确认:一个 500 条会话压缩后被删 3976 条)。守护进程每 30 秒自动同步,确保消息在被删之前入库。
不开守护的风险:手动 sync 之间的间隔内,如果 AI 触发上下文压缩,被删的原始消息将永久丢失。
srelay watch --install-service # Windows 注册表自启动(无需管理员)
srelay watch --foreground # macOS/Linux 前台运行(服务注册开发中)timeline
title 不开守护 vs 开守护
不开守护 : 你聊天(消息进 ZCode 库) : AI 触发上下文压缩 : 💥 消息被 ZCode 物理删除 : 你想起来跑 sync : ❌ 只能拿到压缩摘要,原文永久丢失
开守护 : 你聊天(消息进 ZCode 库) : 守护 30 秒内自动入库 : AI 触发压缩 : ZCode 删除消息 : 😌 没关系,原文已在记忆库 : 压缩摘要也被捕获
守护的资源开销:CPU 空闲时 ≈ 0%(事件驱动),内存 ~80MB(Node.js 常驻),磁盘 I/O 增量极低,网络零外呼。
claude mcp add sessionrelay --scope user -- srelay serve注册后在 Claude Code 里输入 /mcp 应看到 sessionrelay 已连接、16 个工具就绪。
在项目的 MCP 配置(.mcp.json 或客户端设置)中添加:
{
"mcpServers": {
"sessionrelay": { "command": "srelay", "args": ["serve"] }
}
}Qoder 用户注意:Qoder 启动 MCP 子进程时不把工作目录设为项目根。0.5.0 起免配置:serve 依次尝试 MCP roots 协议(自动问客户端"工作区在哪")→ 全局项目注册表(恰好一个活跃项目时自动选中);都无法确定时连接照常保持,首次工具调用返回候选项目列表,AI 带
project参数选一次即可(本连接记住)。下面的环境变量仍是最稳的显式钉法。
SRELAY_PROJECT_ROOT 显式指定项目根,不依赖子进程的工作目录——PATH 解析不到 srelay、客户端不设 cwd、或多项目并行想钉死某一个时都能救。
{
"mcpServers": {
"sessionrelay": {
"command": "node",
"args": ["/你的安装路径/SessionRelay/dist/srelay.js", "serve"],
"env": { "SRELAY_PROJECT_ROOT": "/你的项目路径" }
}
}
}新开一个 AI 会话,问它:
"我们之前为什么决定用 PostgreSQL?"
正确的样子:AI 调用 get_decisions 或 search_sessions,回答里带出处(日期、来源 agent、会话 ID、消息序号)。如果它说"不知道",说明 MCP 未接通——检查 srelay doctor。
读工具(8 个)——点击展开
| 工具 | AI 从此能回答 |
|---|---|
search_sessions |
"我们之前讨论过 X 吗?"(中文全文 + 元数据过滤) |
get_session_detail |
"那场讨论具体聊了什么?"(可按角色过滤、分页、截断) |
list_sessions |
"这个项目都聊过哪些话题?" |
get_decisions |
"为什么决定用 X 而不是 Y?"(全部已确认决策,带出处) |
get_file_history |
"这个文件为什么这么写?"(跨会话文件讨论史) |
suggest_related_sessions |
"还有哪些讨论和这个相关?"(算法发现,可解释理由) |
get_unresolved |
"还有什么没定的?"(未决问题清单) |
get_stats |
"记忆库什么状态?"(会话数/来源/体积) |
set_scope |
检索边界逃生口 |
写域工具(7 个)——点击展开
| 工具 | 能力 | 安全边界 |
|---|---|---|
annotate_session |
给会话打标签 / 写摘要 | 只改元数据,不改写对话 |
save_note |
AI 把结论写成笔记 | source=note,可识别可审计 |
export_handoff |
生成 .hop 交接包 | 只读导出 |
import_handoff |
导入交接包 | 默认隔离模式 |
release_quarantine |
放行隔离正文 | 需显式调用 |
link_sessions |
建立会话关联 | 关联可查可撤销 |
get_linked_sessions |
双向查询关联 | 只读 |
get_session_detail默认最多 20 条 × 1000 字 ≈ 20KB,硬顶 50KB- 超出时返回
truncated: true+ 行动建议(role="user"只看提问 /get_decisions()直接拿结论 / 翻页) - 要更多需显式传参——默认安全,不信任 AI 自觉
{
"hooks": {
"Stop": [{ "hooks": [{ "type": "command", "command": "srelay hook session-end --id $CLAUDE_SESSION_ID" }] }]
}
}会话接力支持插件化适配器——加新 AI 工具 = 零改核心代码:
.sessionrelay/adapters/my-agent.js ← 放一个 JS 文件即可
// 最小实现
module.exports = {
id: 'my-agent',
displayName: 'My Agent',
discover(projectRoot, config) {
// 返回属于该项目的会话列表
return [{ source: 'my-agent', sourceSessionId: 'xxx', sourceFile: '...', sizeBytes: 1024, mtimeMs: Date.now() }];
},
async readNew(ds, cursor, config) {
// 增量读取新消息(cursor 是你自己定义的水位对象)
return { messages: [{ role: 'user', content: '...', seqNum: 1 }], badLines: 0, cursor: { offset: 100 } };
},
};完整接口和更多能力(watchRoots / healthCheck / detectCompaction)见 Adapter SDK 文档。
- 本地优先:零云依赖、零运行时网络外呼(遥测 = 本地计数器 + 自愿提交)
- 三档捕获 + ignore 硬边界 + 导出默认脱敏 + 隔离导入,四层防线
- 信任模型:交接包内容是数据不是指令,写入
hop/1.0协议
- 222 个测试(单元 / 集成 / MCP stdio 真握手契约 / serve 根解析 / 守护服务真装 / 端到端),
npm test一键 - CI 三平台 × Node 22/24 常绿(typecheck + test + build + dist 冒烟)
- TypeScript strict,
npm run typecheck零错误 - 每阶段实机验收(含用产品自身记录了自身的诞生过程)
- 规则提取精度约 60-70%(出处块让你逐条回跳核验;
--ai增强在 Phase 4) - 守护服务注册三平台可用(Windows 注册表 Run 键 / macOS launchd / Linux systemd user,均登录自启动)
- 开新会话的"自动关联重要会话"需要会话身份(branch/PID),Phase 4 落地;当前用
attach手动挂载 - 多 agent 同项目并发时 Scope 按 project+cwd 归属
- Trae 仅部分支持:用户提问可读,AI 回复端到端加密(可用
save_note补记结论) - 目录改名/搬迁的历史会话不被自动发现(用交接包迁移)
- DSH / Cursor 等其他工具在路线图(当前可用自定义适配器先行接入)
--ai 摘要与提取增强 · 会话身份(branch/PID)与自动关联 · DSH / Cursor 官方适配 · HOP 协议第三方推广
- 用户手册——从安装到团队交接的完整指南(所有用户必读)
- 导入导出实操指南——项目交接 / 新人入职 / 安全导入 / 跨项目迁移 / 定期归档,五个场景完整命令
- Adapter SDK——如何编写自定义适配器(7 行代码接入新 AI 工具)
- HOP 交接协议规格 hop/1.0——开放格式(MIT),欢迎第三方实现读取器
- 隐私与数据生命周期——三层隐私模型(预防/归档/删除)+ 归档机制设计
MIT © 2026 EwanJasper
