在 OpenCode 的肩膀上长出记忆
MiMo Code 是 OpenCode 的官方分叉(Fork),由小米 MiMo 团队维护。分叉策略保留 OpenCode 全部能力(多 Provider、TUI、LSP、MCP、插件系统),在其上叠加了自研的记忆与 Agent 管理层。这种「继承 + 增量」模式让 MiMo Code 能持续享受 OpenCode 上游更新,同时独立演进差异化能力。
MiMoCode 的核心价值主张:让 AI 编程助手在多次会话间保持项目记忆的连续性,并在任务执行过程中能够动态调度子 Agent 完成并行工作,最终通过独立裁判模型判定任务是否真正达成。
继承自 OpenCode
多 LLM Provider 接入(OpenAI/Anthropic/OpenRouter/自定义)、终端 TUI 原生界面、LSP 智能补全、MCP 协议支持、插件生态
MiMo 自研增量
SQLite FTS5 持久记忆层、三 Agent 体系(build/plan/compose)、子 Agent 生命周期管理、智能上下文预算重建、Goal/Stop 独立裁判、Compose Skills、Dream & Distill 自改进
TS + Bun + Effect——类型安全的函数式 Agent 运行时
MiMo Code 的核心包是 packages/opencode,使用 TypeScript + Bun 作为运行时,框架层引入 Effect(一个功能强大的 TypeScript 函数式编程库)管理副作用和依赖注入。
// packages/opencode/src/ — 核心源码结构 opencode/src/ ├── agent/ // Agent 配置与 prompt 模板 ├── actor/ // Actor 生命周期管理(含 spawn.ts) ├── memory/ // SQLite FTS5 持久记忆服务 ├── session/ // 会话状态与消息序列化 ├── provider/ // LLM Provider 抽象层 ├── mcp/ // MCP 协议实现 ├── task/ // 树形任务体系(T1/T1.1/T1.2…) ├── bus/ // Actor 间消息总线 ├── inbox/ // 通知渲染 ├── storage/ // Drizzle + SQLite 持久化 └── config/ // .mimocode/mimocode.json 配置
六层架构——从模型到记忆的完整闭环
Plan Agent
Compose Agent] ACTOR[Actor 生命周期
spawn / turn / wait] BUS[Actor Bus
消息总线] end subgraph MEM["【记忆层】 持久化记忆"] MEM_SVC[Memory Service
SQLite FTS5] CHECKPT[Checkpoint
Session State] PROJ_MEM[Project Memory
MEMORY.md] TASKS[Task Progress
tasks/*/progress.md] end subgraph CTX["【上下文层】 智能上下文管理'] CTX_MGR[Context Manager
预算分配] CTX_RC[Context
重建器] end subgraph TOOL["【工具层】"] TOOL_MCP[MCP Tools] TOOL_GIT[Git Tools] TOOL_LSP[LSP Tools] TOOL_FILE[File Tools] end subgraph LLM["【模型层】"] PROVIDER[LLM Provider
OpenAI / Anthropic / OpenRouter] end TUI --> AGENTS AGENTS --> ACTOR ACTOR --> BUS ACTOR --> MEM_SVC MEM_SVC --> CHECKPT MEM_SVC --> PROJ_MEM MEM_SVC --> TASKS AGENTS --> CTX_MGR CTX_MGR --> CTX_RC AGENTS --> TOOL_MCP AGENTS --> TOOL_GIT AGENTS --> TOOL_LSP AGENTS --> TOOL_FILE ACTOR --> PROVIDER
整体呈经典的分层 + 模块化架构。最值得关注的是记忆层(Memory)与上下文层(Context)的协同方式:记忆不只存储,还在上下文紧张时触发基于预算的上下文重建(Context Reconstruction),将记忆内容智能注入当前上下文。
build / plan / compose——按任务类型匹配合适的 Agent
| Agent | 模式 | 权限 | 适用场景 |
|---|---|---|---|
| build | 默认 | 完整工具权限(Git/文件/终端/MCP) | 日常编码任务、快速实现 |
| plan | 只读分析 | 只读(不写文件不执行命令) | 代码探索、方案设计、代码审查 |
| compose | 编排模式 | 完整 + Skills 工作流 | 规格驱动开发(specs-driven)、技能化工作流编排 |
Tab 键切换主 Agent,系统按需动态创建子 Agent(Subagent)。子 Agent 共享当前会话上下文,可并行工作,系统跟踪其生命周期、支持取消与后台执行。
SQLite FTS5 + 四层记忆文件——跨会话知识沉淀
项目知识与架构决策] CKPT[checkpoint.md
结构化状态快照] NOTES[notes.md
临时便笺] TASK_PROG[tasks/<id>/progress.md
任务级日志] end subgraph SQLite["SQLite FTS5 索引层"] FTS[Full-Text Search
FTS5 BM25 ranking] RECONCILE[reconcile.ts
记忆调和(写入新记忆、剪枝旧记忆)] end Files --> RECONCILE RECONCILE --> FTS
记忆服务由 packages/opencode/src/memory/service.ts 实现,核心接口:
// packages/opencode/src/memory/service.ts — Memory Service 接口 export interface Interface { readonly root: () => Effect.Effect<string> // 记忆根目录 readonly reconcile: () => Effect.Effect<{ indexed: number; pruned: number }> // 记忆调和 readonly search: (input: { query: string scope?: string scope_id?: string type?: string limit?: number }) => Effect.Effect<SearchRow[]> }
关键设计点:
- 懒调和(Lazy Reconcile):搜索前自动触发调和,将内存中的记忆变化写入 SQLite FTS5 索引
- 跨 Claude Code 索引:可选集成
~/.claude/projects索引,打通 Claude Code 历史会话 - 预算注入:记忆内容通过 token 预算控制注入量,按重要性排序
- FTS5 BM25 排名:全文搜索使用 BM25 算法,匹配质量优于简单 LIKE
预算驱动的上下文重建——让长程任务不中断
当模型上下文窗口接近上限时,Context Manager 执行「上下文重建」:
- 从最新 checkpoint.md 重建结构化状态快照
- 注入 MEMORY.md 中的项目记忆(按预算裁剪)
- 补充 task progress 中的任务进度日志
- 保留最近的会话消息(按时间序截断)
与记忆层的协同通过 Memory.Service 实现,搜索结果按 scope/scope_id/type 三元组过滤,保证只注入与当前任务相关的记忆片段。
Actor / Spawn / Turn——Effect 驱动的状态机
actor/spawn.ts 是核心实现:
// packages/opencode/src/actor/spawn.ts — 子 Agent 启动 /** Cap on preStop ReAct re-entries per spawn — prevents infinite loops. */ export const MAX_PRE_REACT = 3 /** Cap on postStop ReAct re-entries per spawn. */ export const MAX_POST_REACT = 3 // 子 Agent 通过 renderActorNotification 通知父 Agent const notification = renderActorNotification(actor, event) await Inbox.deliver(notification) // Return format 保证结果格式统一,供父 Agent 解析 // "**Status**: success | partial | failed | blocked"
子 Agent 的生命周期管理使用 Effect 的 Fiber(轻量协程)+ Deferred(异步信号),实现了生命周期跟踪、取消与后台执行三大能力。
独立裁判模型——防止 Agent「乐观停工」
自主工作时,Agent 可能「乐观估计」任务已完成而提前停止(如「代码写完了,虽然还有 3 个测试失败」)。MiMo Code 通过 /goal 命令设置独立裁判模型(Judge Model):
- 用户通过
/goal [条件]设置停止条件 - 当 Agent 尝试停止时,触发器通知 Judge Model
- Judge Model 读取完整对话历史,独立评估条件是否满足
- 返回
success / partial / failed / blocked四级判定
Status 语义:
success — 条件完全满足
partial — 主体完成,有遗留项可接受
failed — 未达到可接受标准,需继续
blocked — 被外部条件阻塞(权限、网络、依赖缺失)
这一设计将「任务执行」与「结果判定」彻底解耦,是防止自主 Agent 偷懒逃逸的核心机制。
规格驱动的 Skills 编排——不只是规则,是最佳实践封装
Compose Agent 内置 Skills,覆盖软件交付全生命周期:
| Skill | 职责 |
|---|---|
planning | 任务拆解与优先级排序 |
execution | 任务执行与进度跟踪 |
code-review | 代码审查与质量把关 |
tdd | 测试驱动开发循环 |
debugging | 问题定位与修复验证 |
verification | 结果验证与集成测试 |
merging | 分支合并与冲突处理 |
Skills 以规范化的 prompt 模板形式存储在 packages/opencode/src/agent/prompt/ 目录,可被用户扩展或替换。这种「技能化」设计让 Compose Agent 能以「有经验的工程师」的方式推进工作流,而非机械地执行单步指令。
让 Agent 从自己的历史中学习
/dream
扫描近期会话轨迹,提取持久性知识写入 MEMORY.md,移除过时条目。Agent 主动反思「这次哪里做得好/不好」,形成结构化记忆。
/distill
发现近期重复的人工工作流,将高置信度候选打包为可复用 Skills / 子 Agent / 命令。Agent 从历史中「蒸馏」最佳实践,自动积累生产力。
这两个命令让 MiMo Code 具备元认知(metacognition)能力——不仅执行任务,还从任务执行历史中提取模式并内化到记忆,形成「越用越懂你」的个性化助手。
关键模块源码分析
11.1 Memory Service(记忆服务)
// packages/opencode/src/memory/service.ts export const layer: Layer.Layer<Service, never, Config.Service> = Layer.effect( Service, Effect.gen(function* () { const config = yield* Config.Service // 记忆根目录:~/.local/share/mimocode/memory 或项目 .mimocode/memory const root = path.join(Global.Path.data, "memory") // 可选:打通 Claude Code 历史会话索引 const ccBase = path.join(os.homedir(), ".claude", "projects") // 懒调和:搜索前自动同步文件系统变化到 FTS5 const reconcile = Effect.fn("Memory.reconcile")(function* () { const cfg = yield* config.get() const cc = cfg.memory?.cc_index ? ccBase : undefined return yield* Effect.promise(() => reconcileMemory({ mimo: root, cc })) }) }) )
11.2 Actor Spawn(子 Agent 启动)
// packages/opencode/src/actor/spawn.ts — 关键流程 // 1. 构建 Return format instruction,约束子 Agent 输出格式 const RETURN_FORMAT_INSTRUCTION = ` --- ## Return format (required) **Status**: success | partial | failed | blocked **Summary**: <one sentence> **Files touched**: <comma-separated paths or "(none)"> ---` // 2. 父子通信通过 Inbox 异步通知(不阻塞主循环) await Inbox.deliver(renderActorNotification(actor, event)) // 3. ReAct 重入上限保护,防止子 Agent 进入无限循环 // MAX_PRE_REACT = 3, MAX_POST_REACT = 3
11.3 Context Reconstruction(上下文重建)
// packages/opencode/src/memory/reconcile.ts — 记忆调和 // reconcileMemory 核心逻辑(伪代码): function reconcileMemory({ mimo, cc }) { // 1. 扫描 .mimocode/memory 目录所有 Markdown 文件 // 2. 解析 frontmatter 中的 scope / scope_id / type 元数据 // 3. 对比 SQLite FTS5 已有索引,判定新增 / 更新 / 删除 // 4. 写入 / 删除 FTS5 行,执行 vacuum 回收空间 // 5. 返回 { indexed, pruned } 统计 }
为什么 MiMo Code 值得关注
| 维度 | 亮点 | 潜在风险 |
|---|---|---|
| 记忆系统 | SQLite FTS5 实现轻量、高性能全文检索,跨会话零冷启动 | Markdown 文件格式对结构化知识的表达能力有限 |
| 子 Agent | Effect Fiber 实现轻量协程,生命周期管理干净 | MAX_PRE/POST_REACT 硬编码上限,缺乏动态调优机制 |
| Goal 裁判 | 独立模型判定,防止自主 Agent 偷懒逃逸 | 额外调用成本,每次停止判断多一次 LLM 调用 |
| Dream/Distill | 从历史中提取知识,形成个性化记忆,稀缺能力 | 知识蒸馏质量依赖会话数据丰富度,冷启动无效 |
| Compose Skills | 最佳实践模板化,降低 Agent 执行的不确定性 | Skill 扩展依赖 prompt 工程,门槛不低 |
| 分叉策略 | 继承 OpenCode 上游,独立自研差异化功能 | 长期需平衡上游合并与自研功能的兼容成本 |