转录
你过去和 AI 的对话,大概率不只发生在一个地方:Claude Code 里的深夜调试、Codex 里的重构、Kimi Code 里的头脑风暴。这些对话散落在各家的私有格式里,谁也读不懂谁。Previously 相信它们属于同一条时间线——你的整个 AI 生活应该能被一起记住。所以我们写了一个抄写员:scribe 读你其它 agent 的会话日志,把那些对话重建为 Previously 的时间切片,放在和你自己对话完全相同的时间线上。
scribe 是本机(npm)形态的能力——它要读的日志长在你的机器上,云端部署够不着它们。
转录,不劫持
scribe 的第一条纪律写在它的名字里:它是抄写员,不是司机。它对你其它 agent 的会话日志只有读权限——不注入、不回写、不替它们做任何决定。原件一个字节都不会被碰。
这也意味着整个转录过程不调用任何模型:逐行解析、按规则重建、确定性落盘。零 token 成本,你的订阅额度一分不花。
它看着四个目录
- Claude Code —
~/.claude/projects/**/*.jsonl,已用真实会话日志验证。 - Codex —
~/.codex/sessions/**/rollout-*.jsonl,由 fixture 测试覆盖。 - Kimi Code —
~/.kimi-code/sessions/**/wire.jsonl,已对照真实 wire 文件验证,子代理的 wire 也包含在内。 - Gemini CLI —
~/.gemini/tmp/*/chats/*.json,整文件 checkpoint 格式,每次变化全量重新推导。
每家的格式隔离成独立的解析器插件,一家的格式漂移不会传染别家。转录出的切片带 source 和 session_id 来源标签——你随时能看清一段记忆从哪来。
一条无聊的流水线
文件监听器(等写入静默 200ms 再动手)→ 每个文件一条串行队列 → 增量的带版本解析器 → 把事件分组成一问一答的回合 → 确定性的切片写入器 → 攒批提交 git(Scribe: N slice(s) from …)。
写入器产出的是与内核逐字节同构的目录结构:episodic/slices/YYYY/MM/DD/HHMM/timeline/core.md,月度 _index.json 同步更新。对时间线来说,转录来的切片和内核自己写的切片没有区别——这正是目的。
"无聊"在这里是褒义。确定性意味着同一份输入永远产出同一份字节,重复转录不会制造任何文件抖动。
游标:记得自己读到哪
scribe 为每个文件维护一枚游标:字节偏移量 + 行数 + 一条链式 sha256,原子落盘。重启后从游标处接着读;文件变短(被截断或轮换)就从第 0 字节干净重读;解析器版本升级了,旧游标作废,同样干净重读。字节级幂等保证重读永远不产生重复内容。
连游标文件本身损坏都有预案:它会被隔离为 cursors.json.corrupt 并在状态里如实上报——绝不悄悄丢弃。
格式税
各家的日志格式会漂移,这无法避免。scribe 的选择是诚实纳税:解析不了的行不会打断流水线,而是原文降级进切片的 timeline/appendix.md 附录,并如实计入状态里的解析错误数。你看到的是"有 3 行没看懂",而不是一个假装一切正常的沉默系统。
日常怎么用
装好之后你基本不需要想起它:previously start 会把 scribe 作为独立进程一并拉起。previously status 显示每个来源的进度——看到多少文件、处理了多少、事件数、解析错误数、最后一条事件的时间。想盯着它工作,previously watch 在前台运行它;想把历史一次性回填,previously scribe once 做一遍全量扫描。
一句话:scribe 把你和其它 agent 的过去搬进同一条时间线——只读、零 token、绝不碰原件。
相关文档
- 时间切片 —— 转录产物的样子
- 时间线 —— 所有对话汇合的地方
- 写入记忆的唯一一扇门 —— 想主动写入时走的那条通道