opencode-working-memory
让 OpenCode 跨会话记住项目决策和用户偏好的插件,零额外 API 调用,结构化衰减记忆机制
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
让 OpenCode 跨会话记住项目决策和用户偏好的插件,零额外 API 调用,结构化衰减记忆机制
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
你有没有过这样的体验:让 AI 编程工具帮你在一个复杂项目里工作,一开始的对话非常顺利,AI 理解了你的代码风格、项目规范、甚至你的个人偏好。但随着对话的推进(OpenCode 会自动压缩对话来控制上下文长度),这些宝贵的信息就像沙子一样从指缝间溜走了——你已经告诉它"这个项目用 Vitest 而非 Jest",但压缩后它又忘了;你说过"用户偏好简洁的实现说明",但下次开新会话,它又回到那套冗长的报告风格。
这就是 上下文记忆丢失问题,是所有长程 AI 编程代理共同面临的痛点。OpenCode Working Memory 正是为解决这个问题而生——它是一个专为 OpenCode 设计的记忆系统,让 AI 代理能够跨会话记住项目决策、用户偏好和重要参考,同时保持活跃文件、待处理错误等短期状态新鲜且轻量。关键在于:整个过程不消耗任何额外的 API 调用。

图1:项目作者 sdwolf4103 的 GitHub 头像
OpenCode 是 opencode.ai 推出的开源 AI 编程代理(类似 Claude Code),支持多模型、多 provider,允许用户通过插件机制扩展功能。OpenCode 内置了一个叫"compaction"(压缩)的机制——当对话长度超过一定阈值时,它会自动将对话历史压缩,只保留关键信息。这是控制上下文长度的必要手段,但也会导致一些重要的上下文被意外丢弃。
作者 sdwolf4103 是 OpenCode 的活跃贡献者,在社区中发现这个痛点后,于 2025 年初开始开发 Working Memory 插件。最初版本只有简单的会话状态追踪(热会话状态),v1.2 版本(2026年初)正式引入跨会话持久化工作区记忆,实现了真正跨越会话边界的记忆能力。
图2:OpenCode AI 官方组织头像
OpenCode Working Memory 的设计非常精妙,它构建了一个三层记忆金字塔:
第一层:工作区记忆(Workspace Memory)—— 持久层
这是最关键的创新层。记忆以结构化的 JSON 文件形式持久化存储在 ~/.local/share/opencode-working-memory/workspaces/{workspace_hash}/workspace-memory.json。记忆条目有四种类型:
feedback(反馈):用户偏好或反复出现的反馈,比如"用户喜欢简洁的总结"project(项目):稳定的项目级事实,比如"这个仓库使用 TypeScript 和 Node.js 测试运行器"decision(决策):重要的实现或架构决策,比如"使用 npm cache 而非 npm link 加载插件"reference(参考):有用的路径、命令或配置引用工作区记忆在每次 OpenCode compaction(压缩)时自动提取——插件在压缩请求的 system prompt 中注入记忆提取指令,让 OpenCode 自己决定哪些信息值得保存为零散的条目,然后写入本地 JSON 文件。整个过程完全不调用额外的 LLM API,完全"蹭" OpenCode 原有的压缩请求。
记忆还有一个精心设计的衰减机制(Retention Decay):每条记忆有"强度"(strength)属性,随着时间推移自动衰减,但被强化(reinforce)的记忆衰减更慢。新记忆通过竞争动态上限(cap competition)来争夺可见空间——这是防止记忆无限膨胀的关键设计。
第二层:热会话状态(Hot Session State)—— 瞬时层
存储在 sessions/{sessionID}.json 中,追踪当前会话的活跃文件、打开的错误和最近决策。关键设计决策:热状态是一个 epoch 起始的快照,不会在活跃文件或错误变化时主动失效。这样做的目的是保护 KV 缓存复用——如果每次文件变化都刷新快照,就会导致 GPU 上的前缀 KV 缓存失效,重新计算代价极高。
第三层:原生 OpenCode 状态——委托层
Todo 和内置状态直接委托给 OpenCode 原生功能,不需要额外存储。
仅有记忆能力还不够,记忆的质量同样重要。OpenCode Working Memory 实现了三层质量保护机制:
选择性(Selective):自动过滤临时进度、原始错误堆栈、git hash、调试碎片和重复陈述。
安全性(Safe):凭证脱敏,保护手动或显式记忆不被不安全地替换。
可诊断性(Diagnosable):跟踪每条记忆的命运——被提升(promoted)、被吸收(absorbed)、被取代(superseded)、被拒绝(rejected)、被强化(reinforced)或被替换(replaced)。用户可以通过 memory-diag CLI 详细查看每种结局的证据。
值得注意的是,插件不会强制删除记忆——即使一条记忆衰减到不再出现在 prompt 中,它仍然保留在文件中,只是暂时"隐退"了。这种保守策略保护了以声明式风格写成的持久记忆。
从用户体验角度看,OpenCode Working Memory 遵循"零摩擦"哲学:安装只需要在 ~/.config/opencode/opencode.json 中添加一行插件配置,重启 OpenCode 即可。没有任何命令行工具需要记忆,没有任何额外配置需要调整。
用户可以通过自然语言触发记忆保存:"Remember this: we prefer Vitest for new frontend tests." 或者中文 "记住:发 release 前要先跑 npm test。"——插件支持多语言触发短语,包括中文(記住/記得)、日文(覚えて)、韩文(기억해)。内置的 /memory TUI 命令提供了本地只读的诊断界面,显示当前活跃的工作区记忆列表,支持搜索和分组显示 [M#] 引用编号。
没有任何工具是万能的。OpenCode Working Memory 有几个值得了解的边界:
随着 AI 编程代理变得越来越强大和自主,如何让它们在长时间跨度的任务中保持"记忆"成为一个核心问题。OpenCode Working Memory 提供了三条有价值的思路:
复用而非新建:不单独调用 LLM 做记忆提取,而是复用 OpenCode 自身的 compaction 调用,将记忆提取指令嵌入已有的压缩 prompt 中。这不仅节省 API 成本,更重要的是保持了记忆提取与原始对话上下文的一致性。
结构化 + 衰减:纯字符串的记忆容易造成 prompt 膨胀,结构化分类(feedback/project/decision/reference)+ 衰减机制可以自然地让低价值信息淡出,同时保护重要决策。
本地优先:所有数据存储在 ~/.local/share/ 下,不上传任何服务器,完全本地化。
| 维度 | 内容 |
|---|---|
| 语言 | TypeScript(编译为 ESM JavaScript) |
| 运行时要求 | Node.js >= 22.6.0 |
| OpenCode 插件 API | >=1.2.0 <2.0.0 |
| 包管理 | npm(发布在 npmjs.com) |
| 构建工具 | TypeScript Compiler(tsc) |
| 存储格式 | JSON(工作区记忆 + 会话状态) |
| 工作区记忆预算 | 3600 字符(~900 tokens)/ 28 条目 |
| 热会话状态预算 | 700 字符(~175 tokens) |
| 诊断工具 | memory-diag CLI(内置 npx 命令) |
| License | MIT |