TL;DR:omp 是 Claude Code 的 fork,基础能力相同。差异在于:(1) 会话从线性变成树形,支持分支和时间旅行;(2) 规则从静态加载变成 TTSR 实时中断;(3) Memory 从文件系统变成 SQLite + 向量索引;(4) 多 Agent 从 parent-child 变成 YAML pipeline 编排。
这是「omp 编程工具使用探讨」专栏的最后一篇。前面 8 篇讲了 omp 的机制,这篇从源码层面对比 omp 和 Claude Code 的设计差异——不是功能列表,是实现层面的取舍。
共同起点:omp 是 Claude Code 的 fork
先摆事实:omp 最初 fork 自 badlogic/pi-mono(一个基于 Claude Code 衍生的开源项目),核心能力——终端交互、工具调用、子 agent、MCP 支持——都是继承的。
所以问题不是”谁更强大”,而是在相同基础上,各自做了什么差异化。
差异一:会话管理
Claude Code:线性 + LLM 摘要
Claude Code 的会话是线性消息序列,上下文快满时触发 SessionMemory:
sessionMemory.ts:134-181 → shouldExtractMemory() 双阈值判断sessionMemory.ts:318-325 → runForkedAgent() 调 LLM 生成摘要prompts.ts:11-41 → 9 个 section 模板,总量上限 12000 tokens压缩方式是文本摘要——用 LLM subagent 把历史浓缩成 markdown 文件,存在 ~/.claude/session-memory/。
跨会话记忆靠 memdir(src/memdir/):
memdir.ts:34 → MEMORY.md 索引文件,200 行/25KB 限制memoryScan.ts → 扫描 frontmatter headerfindRelevantMemories.ts:77-141 → Sonnet selector 选 top 5 相关记忆问题:线性结构意味着走错路没法回头,只能开新会话或等 compact 丢细节。
omp:Session Tree + 图像化压缩
omp 把会话建成树,每条记录有 id + parentId:
session-entries.ts:207-222 → 14 种 SessionEntry 类型的 unionsession-manager.ts:255-257 → setLeaf(id) 切换活跃分支session-manager.ts:289-318 → tree() 构建完整树结构session-entries.ts:105 → BranchSummaryEntry 记录分支摘要/tree 命令打开树选择器,setLeaf() 跳到任意分支——等于 git checkout 任意 commit。
压缩方式是 Snapcompact——纯本地、不调 LLM:
什么是”图像化压缩”?简单说:把对话历史渲染成高密度 PNG 图片。文本中的关键词被压缩成像素点,两端保留完整文本(方便读上下文),中间高度压缩(节省空间)。好处是完全本地、速度极快;坏处是丢失语义细节,不如 LLM 摘要精准。
snapcompact.ts:707-885 → 消息序列化,截断 tool resultssnapcompact.ts:1030-1168 → ANSI 剥离、NFKD 折叠、stopword dimmingsnapcompact.ts:1437-1505 → 纯文本渲染成密集 PNG 帧snapcompact.ts:1729-1820 → foveated 布局(两端高质量 + 中间高密度)切分支时,被离开的路径自动生成摘要(branchWithSummary()),新分支知道”之前试过什么”。
核心差异:Claude Code 用 LLM 生成文本摘要(语义精准、但慢、要调 API),omp 用纯本地图像编码(快、本地、但丢失细节)。Claude Code 是线性链,omp 是树形图。
差异二:规则系统
Claude Code:CLAUDE.md 静态加载
Claude Code 读 CLAUDE.md,在会话开始时注入 system prompt:
context.ts:169-187 → getUserContext → getMemoryFiles → getClaudeMds规则是纯文本,支持目录级 CLAUDE.md(项目/子目录),但没有条件触发和运行时中断机制。加载一次,整个会话有效。
omp:三层规则 + TTSR 实时中断
omp 兼容多种规则格式(.cursor/rules、CLAUDE.md、.omp/rules/),但加了结构化字段:
src/discovery/agents.ts:89-114 → loadRules,支持 condition/astCondition/scope/interruptModesrc/capability/rule-buckets.ts:33-66 → bucketRules() 自动分三层三层:
| 层级 | 条件 | 行为 |
|---|---|---|
| TTSR | 有 condition 或 astCondition | 注册到 TtsrManager,实时监控 |
| always-apply | alwaysApply: true | 每轮注入 system prompt |
| rulebook | 有 description | 按需通过 rule:// URL 加载 |
TTSR(实时规则中断) 是 omp 独有的:
src/export/ttsr.ts:72-593 → TtsrManager 类ttsr.ts:303-346 → addRule(),编译 regex,注册 scopettsr.ts:354-365 → checkDelta(),追加 stream delta,regex 匹配ttsr.ts:401-449 → checkAstSnapshot(),ast-grep 结构化匹配ttsr.ts:155-212 → scope 隔离(text/thinking/tool + path glob)工作流程:agent 输出流式生成 → 每段检查是否匹配规则 → 匹配则 abort → 注入规则 → 重试。
核心差异:Claude Code 的规则是”建议”(开头加载一次),omp 的规则是”强制”(运行时实时中断)。
差异三:Memory
Claude Code:文件系统 + LLM 召回
memdir.ts:34 → MEMORY.md 索引,始终注入 system promptmemoryScan.ts → 扫描 ~/.claude/memory/ 下的 .md 文件findRelevantMemories.ts:77-141 → Sonnet sideQuery 选 top 5memoryAge.ts:33-42 → mtime 计算年龄,>1 天附加 staleness 警告记忆是手动写文件——LLM 用 Write tool 写 markdown,格式自由。没有遗忘机制,只有”新鲜度提醒”。
omp:SQLite + 多信号召回 + 自动提取
packages/mnemopi/src/core/memory.ts → Mnemopi 类 facadepackages/mnemopi/src/core/beam/store.ts → remember/forget/updatepackages/mnemopi/src/core/beam/recall.ts → 多信号加权召回packages/mnemopi/src/core/beam/consolidate.ts → Sleep Consolidationpackages/mnemopi/src/core/extraction.ts → background LLM 事实提取存储是 SQLite(working_memory、episodic_memory、facts、triples 等表),支持 FTS5 + 向量索引。
召回策略是多信号加权:
recall.ts → FTS5(0.3) + 向量相似度(0.5) + importance(0.2) + temporal boost + veracity + MMR生命周期有 Sleep Consolidation:working_memory → episodic_memory tier 1→2→3,30 天/180 天衰减压缩。
记忆提取是自动的——extraction.ts 调 background LLM 结构化提取 facts/instructions/preferences/timelines/kg。
核心差异:Claude Code 是”文件系统 + 手动写 + LLM 语义召回”,omp 是”SQLite + 自动提取 + 多信号加权召回 + 衰减遗忘”。
差异四:多 Agent
Claude Code:parent-child 单向
src/tasks/LocalAgentTask/LocalAgentTask.tsxClaude Code 的 LocalAgentTask 管理后台 agent:
registerAsyncAgent()创建后台 agentqueuePendingMessage()/drainPendingMessages()实现 parent → child 消息传递backgroundAgentTask()将前台 agent 转后台abortController支持取消
通信是单向的——parent 给任务,child 返回结果。子 agent 之间不能直接通信。
omp:YAML pipeline + DAG 编排
packages/swarm-extension/src/extension.tspackages/swarm-extension/src/swarm/dag.tspackages/swarm-extension/src/swarm/pipeline.tspackages/swarm-extension/src/swarm/state.tsomp 的 swarm 扩展用 YAML 定义 pipeline:
# 示例:review + fix pipelineagents: reviewer: prompt: "review this PR" fixer: prompt: "fix all issues" depends_on: [reviewer]dag.ts 构建依赖图、检测循环、计算执行波次。PipelineController 按 DAG 拓扑顺序执行,支持并行。
通过 /swarm run <file.yaml> 触发,/swarm status 查看状态。
核心差异:Claude Code 是”parent spawn child,单向等结果”;omp 是”YAML 定义依赖,DAG 编排,支持并行和条件”。
差异五:Approval 细粒度
两者都有 approval 机制(控制 agent 自主权),但 omp 更精细:
Claude Code:全局模式为主
src/types/permissions.tsClaude Code 的 approval 以全局模式为主:ask(每步确认)、auto(读写自动)、yolo(全自动)。也支持部分 per-tool 配置,但粒度较粗。
omp:三层分级 + per-tool + 动态判断
src/capability/approval/omp 的 approval 更精细:
三层工具分级:
| 等级 | 语义 | 典型工具 |
|---|---|---|
read | 只读数据 | read、grep、glob、lsp |
write | 改变工作区 | edit、write、todo |
exec | 执行代码 | bash、eval、browser、task |
逐工具覆盖:可以单独设 bash: prompt——agent 自由读写文件,但跑命令要你确认。
动态判断:bash 工具内置 CRITICAL_BASH_PATTERNS,匹配 rm -rf / 等危险命令时强制弹框,即使 yolo 模式。
核心差异:Claude Code 是”全开或全关”,omp 是”按工具分级 + 逐工具覆盖 + 运行时动态判断”。
怎么选
基于源码分析,结论很清晰:
| 痛点 | Claude Code 的局限 | omp 的解法 |
|---|---|---|
| 走错路没法回头 | 线性会话,只能 compact | Session Tree + /tree 时间旅行 |
| 规则总是被违反 | 静态加载,无法干预 | TTSR 实时中断 |
| 经验无法持久 | 手动写 .md 文件 | Mnemopi 自动提取 + 多信号召回 |
| 子 agent 间需要协调 | 单向 parent-child | YAML pipeline + DAG 编排 |
| yolo 模式太危险 | 全开或全关 | per-tool + 动态 approval |
如果你用 Claude Code 觉得够用——继续用。基础能力相同,学习成本低。
如果你遇到上面的痛点——试试 omp。它不是”更强”,是设计取舍不同。
这个专栏的回顾
9 篇文章,从源码层面拆开了 omp 的核心机制:
- omp 是什么 —— 定位、技术栈、在工具坐标里的位置
- Session —— 树形会话,支持分支和时间旅行
- Rules —— 多格式兼容,三层规则系统
- TTSR —— 实时规则中断,agent 输出过程中被规则打回
- Skill —— 工程化知识固化,触发条件 + 可复用流程
- 多 Agent —— YAML pipeline + DAG 编排
- Memory —— SQLite + 多信号召回 + 衰减遗忘
- Approval —— per-tool + 动态判断
- 对比 —— 源码级差异分析(本文)
如果你想深入了解某个机制,直接读源码——每个差异点都标注了文件和行号。
本文是「omp 编程工具使用探讨」专栏第 9 篇(完结)。查看专栏目录浏览全部文章。文中的源码引用来自 Claude Code 和 oh-my-pi 的当前版本,两者都在快速迭代,具体实现可能有变化。