给 Qwen Code 加记忆

它吃 Gemini 的扩展格式,也吃 Claude 格式的市场

Qwen Code 把每个会话都留在磁盘上,然后把下一个会话开成空的。上周你想明白的事还在那里,当时你开着的另一个智能体里做的事也还在。

Qwen 已经有的部分

会话放在 ~/.qwen/projects/<project>/chats 下,JSONL 格式。完整,但没有任何东西读它——包括 Qwen 自己的下一个会话。

接上召回

qwen extensions install https://github.com/vshulcz/deja-vu

Qwen Code 和 Gemini CLI 共用扩展格式,所以仓库根目录那个 gemini-extension.json 就是全部安装内容。在 Qwen Code 0.20.0 上验过:它会报出 deja MCP 服务器、上下文文件和 deja-search 技能,并装到 ~/.qwen/extensions/deja 下。

另一条路是 CLI 安装,它还会把指引写到 Qwen 真正会读的地方:

deja install qwen-auto

两条路一起跑是安全的,不会变成两份:MCP 服务器按名字索引,所以扩展里的 deja 和 settings.json 里的那个会合成同一个服务器,而不是把每个工具列两遍。

Qwen 也读 Claude 格式的插件市场,而这个仓库正是一个:

qwen extensions sources add https://github.com/vshulcz/deja-vu

无论走哪条路都需要那个二进制,因为扩展交付的是文件,不是运行时:

brew install deja-vu
# 或者
curl -fsSL https://raw.githubusercontent.com/vshulcz/deja-vu/main/install.sh | sh

接好之后有什么

deja install qwen-auto 会往 ~/.qwen/settings.json 里写四个钩子,和里面原有的内容并存:

  • SessionStart 上的项目摘要:在你敲任何字之前,先给出这个项目过去的会话定下了什么。
  • UserPromptSubmit 上的召回,历史给不出答案时保持沉默。
  • PostToolUseFailure 上的修复,只针对 run_shell_command:某条命令报的错以前在这台机器上解决过,上次紧跟其后的做法会直接落在这次失败的工具结果上。
  • PreCompact 上的遗忘,让被压缩的线程刚丢掉的那些块可以再说一遍。

以上在 Qwen Code 0.20.0 上靠读它实际发出的请求量过。PostToolUse 只在工具成功时触发——Qwen 给它加了判断,失败时走 PostToolUseFailure——所以修复以前挂在一个失败时永不触发的事件上;在旧版之上再装一次会把那条记录删掉。PreToolUse 会跑,但输出被丢弃。失败的载荷把命令输出放在 error 字段里,包在 Qwen 自己写的 Command: / Output: / Exit Code: 块中,deja 在匹配之前会把它拆开。

那个版本上的开销,在预置好的索引上:会话开始 2.3 KB,一个修复块 397 字节;无话可说时 0 字节、约 30 毫秒。

和这个 harness 无关的那一半

索引覆盖这台机器上每个智能体的转录——今天是三十四个,各有各的格式——所以在一个工具里找到的修法,能回答在另一个工具里提的问题,包括这一切装上来之前的会话。这就是选择索引、而不是选择边用边记的原因。

这里没有任何东西在写记忆,所以也就没有什么能凭空编进你的历史里;建索引和检索都在本地,凭据在建索引时就被脱敏(隐私说明)。每次提问注入上限 1536 字节,每次工具调用约 4 KB——记忆要花多少 token 里有实测对比。

快速开始 · Qwen 的会话文件是怎么读的 · Memory for Gemini CLI