oh-my-pi:把工具调用做到极致的终端 Coding Agent
posts posts 2026-05-20T20:20:48+08:00oh-my-pi(简称 omp)是一个终端 Coding Agent,核心差异不在模型,而在工具链层:hashline 锚定编辑消除格式摩擦、Rust 内联原语去掉 fork 开销、31 个内置工具覆盖读、写、搜、LSP、调试、子 Agent 全流程。本文深入解析其架构设计与 benchmark 数据背后的实质。技术笔记AI Agent, Coding Agent, Rust, TypeScript, LSP, 工具链先说判断
大多数 Coding Agent 的性能瓶颈不在模型,在工具层——格式损耗、fork 开销、上下文税。omp 真正的价值在于把工具链从"调用接口"重新工程化为"格式正确性 + 执行效率 + 记忆协同"三位一体的系统。这就是为什么同样一个 Grok Code Fast 模型,在 omp 里编辑通过率能从 6.7% 跳到 68.3%;MiniMax 相同权重相同提示词,通过率翻倍(2.1×)。
这不是模型升级,是工具链重构。
系统总览
omp 是一个 TypeScript 主体、Rust 内核的交互式 Coding Agent:monorepo 含 16 个 npm 包和 12 个 Rust crate,其中六个核心 crate 承担原生能力(2026-10-03 目录实测)。README 的口径行是 60+ providers · 31 built-in tools · 14 lsp ops · 28 dap ops · ~80k lines of Rust core。仓库当前 34,116 stars(2026-10-03 读数),由 Stencil Labs 维护,MIT 许可。
核心模块分层:
| 层级 | 包/crate | 主要职责 |
|---|---|---|
| Agent Surface | packages/coding-agent | CLI、TUI、会话管理、slash commands、SDK |
| Agent Runtime | packages/agent | 工具分发、状态机、tool calling |
| AI Client | packages/ai | 60+ provider 的模型调用、streaming、auth |
| Rust Core | crates/pi-natives | grep、shell、AST、PTY、image、text 处理(N-API 绑定,25,000 行) |
| Shell Runtime | crates/pi-shell | 嵌入式 bash、持久会话、in-process coreutils 分发(38,000 行) |
| Code Intelligence | crates/pi-ast | tree-sitter 结构摘要、AST 匹配 |
| Isolation | crates/pi-iso | 工作区隔离:APFS clone、btrfs/zfs reflink、overlayfs |
安装方式三选一:
# macOS / Linux
curl -fsSL https://omp.sh/install | sh
# Bun
bun install -g @oh-my-pi/pi-coding-agent
# Windows PowerShell
irm https://omp.sh/install.ps1 | iex工具层:为什么这里是瓶颈
格式损耗问题
传统 agent 调用 edit 时,模型输出 diff 格式,解析器提取行号,内容写入文件。问题在于:模型对行号没有视觉验证,一旦文件在模型上下文之外被修改,行号就指向了错误位置,反复重试消耗 token 和时间。
omp 的解决方案是 hashline(内容哈希锚定编辑)。模型不指向行号,而指向一段内容及其哈希值——文件被修改后,锚点发散,系统在 apply 之前就拒绝这次 patch,而不是把错误内容写入磁盘。Grok 4 Fast 同一个任务,输出 token 下降 61%,不是因为模型变了,是因为 retry loop 消失了。现行语法的完整规则(PUT/CUT、@寄存器、ABORT)见笔者的另一篇 omp 深读,此处不展开。
fork-exec 开销
大多数 agent 在做 grep、rg、find 时会 shell out 到系统二进制,每一次调用都触发一次 fork-exec 周期。omp 把这些能力直接链接进进程:vendored 的 brush-core/brush-parser(bash 实现)、ripgrep 的 grep-regex/grep-searcher 库组件,grep、glob、shell、PTY 全部 in-process,走 libuv 线程池。README 里那 ~80k 行 Rust core 做的事,就是把本来在 shell 层的东西压到更底层。
这在高频工具调用场景(一次完整修 bug 的 session 可能调用几十到上百次工具)下,累积的 fork 开销不可忽略。
工具发现与按需激活
31 个内置工具全部在同一命名空间,--tools read,edit,bash,… 固定激活集;低频工具藏进 xd:// 设备——read xd:// 列出清单,write xd://<tool> 单次执行。对 Anthropic 后端,omp 还会把未激活工具暴露给 Anthropic 的服务端工具检索(tool_search_tool_regex/tool_search_tool_bm25),由模型在会话中期按需发现和调用,不需要在每次调用前重新枚举整个工具列表。
五大核心能力拆解
1. 代码执行 + 双 kernel 桥
多数 harness 给 agent 一个 Python sandbox 就结束。omp 跑持久 Python + Bun worker 两个 kernel,任一 kernel 可以 callback 进入 agent 自己的工具(read、search、task),通过 loopback 桥接。README 的原话场景:agent 从 Python 里用 tool.read 读 CSV,在 JavaScript 里画图,全程不离开 cell。
eval 是共享 prelude 的持久 Python/JavaScript cell,工具在两个 kernel 间可重入调用。
2. LSP 深度集成
LSP(Language Server Protocol)不只是语法高亮。omp 的 lsp 工具走 workspace 协议,rename 操作会先过 workspace/willRenameFiles,re-export、barrel file、aliased import 在文件移动前全部更新——一次回调完成所有关联文件的修改。lsp 覆盖诊断、导航、符号、重命名、code actions 与 raw requests,14 个操作种类。
3. 真实 debugger(DAP)
omp 通过 DAP(Debug Adapter Protocol)驱动真实的调试器:lldb、dlv、debugpy 均支持。README 给的场景:一个 C 二进制 segfault,agent attach lldb、step 到坏指针、读栈帧;一个 Go 服务挂起,attach dlv 遍历 goroutine。从断点设置、线程控制、栈帧遍历到变量检查全部在 agent 控制下,不需要 print 语句。
4. 时间穿越规则注入(Time-Traveling Stream Rules)
规则在模型偏离轨道时触发:regex 匹配到偏离内容,立即 abort 整个 stream(停在 token 中途),把规则作为 system reminder 注入,从同一断点重试。关键点在于注入在 context 压缩时存活,compaction 后修复仍然有效——课程修正不按轮次收上下文税。
5. 子 Agent 与任务分发
task 工具把工作 fan out 到隔离的 worktree,每个 worker 有独立工具表面,最终 yield 是一个 schema-validated 对象,parent 直接读字段,不用解析散文。IRC 机制(源码里的 IrcBus)支持同进程内 live agent 之间的短文本通信,子任务之间的握手不用回传给用户中转。Alt+A 打开 Agent Hub,可以实时看每个 subagent 的活动与开销、读它的 live transcript、发 steering 消息,卡住的 worker 直接杀掉而不动父会话。
记忆系统:三个引擎,默认关闭
omp 的跨 session 记忆不是绑死在某个实现上,memory.backend 三选一:local、Hindsight、Mnemopi。以 Hindsight 为例,工具面是四个:
- retain:session 中途把关键事实排队写入记忆 bank
- learn:沉淀可复用的经验教训
- recall:搜索 bank,拉回原始记忆
- reflect:基于 bank 综合回答
每个 session 末尾,系统将整个对话压缩为一个 mental model,下一个 session 第一轮加载。记忆按项目隔离——对某个 repo 学到的知识不会泄漏到其他项目。
要注意的是:这套记忆工具默认关闭(setting-gated),连同 github、security_scan、generate_image、tts、checkpoint、rewind 一起,都需要在设置里显式打开。评估"omp 记不记得上次"之前,先确认开关。
模型路由:九个角色与四类旋钮
九个角色按意图路由模型:default(常规)、smol(廉价子 agent 扇出)、slow(深度推理)、plan(计划模式)、commit(changelog),再加 vision、task、advisor、tiny。启动时可用 --smol、--slow、--plan 覆盖,Ctrl+P 循环当前角色的候选模型,会话中 /model 随时切换。
路由体系有四个值得知道的旋钮:
- 自定义 provider:在
~/.omp/agent/models.yml里声明任何讲 openai-completions、anthropic-messages、google-vertex 等协议的端点; - Fallback chains:
retry.fallbackChains(在~/.omp/agent/config.yml)按角色或按模型配置链路,主模型 429 或撞配额时自动切到下一个,冷却后恢复; - Path 作用域模型:
enabledModels/disabledProviders条目可限定path:前缀,单个仓库用不同的模型集而不动全局配置; - 凭据轮换:同一 provider 可堆多个 API key,运行时带会话亲和与退避地轮换——单 key 撑不到午饭的场景有解。
四种使用模式
| 模式 | 调用方式 | 适用场景 |
|---|---|---|
| Interactive TUI | omp(默认) | 日常开发、探索性任务 |
| One-shot | omp -p "<prompt>" | 快速单次任务 |
| RPC | omp --mode rpc | 嵌入外部进程,NDJSON over stdio |
| ACP | omp acp | 驱动编辑器(Zed 等),走 JSON-RPC |
Node SDK 方式嵌入:
import { ModelRegistry, SessionManager, createAgentSession, discoverAuthStorage } from "@oh-my-pi/pi-coding-agent";
const auth = await discoverAuthStorage();
const models = new ModelRegistry(auth);
await models.refresh();
const { session } = await createAgentSession({
sessionManager: SessionManager.inMemory(),
authStorage: auth,
modelRegistry: models,
});
await session.prompt("list .ts files");四个导出名均在包的 sdk.ts 中验证存在;createAgentSession 还接受 enableIrc、agentRegistry 等选项控制子 agent 行为。
Benchmark 数据怎么读
文档给出的 benchmark 表不是性能跑分,而是格式损耗对照实验:
| 模型 | 变化 | 实质 |
|---|---|---|
| Grok Code Fast 1 | 6.7% → 68.3% | hashline 锚定消除编辑格式摩擦,retry loop 消失 |
| Gemini 3 Flash | +5 pp over str_replace | 专用格式的提示词工程收益超过 Google 自家最佳尝试 |
| Grok 4 Fast | −61% tokens | hashline 减少模型重输出,降低总 token 消耗 |
| MiniMax | 2.1× | 相同权重相同提示词,通过率翻倍(pass rate more than doubles) |
这些数字测的不是模型能力,而是工具链对模型输出的保真度。模型还是那个模型,但工具层不再吃输出。读的时候注意三点:它们只反映"换 harness 后编辑类任务的通过率与 token 消耗",不能直接推出端到端开发效率的优势;强模型在好 harness 上同样受益,幅度未必相同;全部是作者自报口径,暂无独立第三方复现。
代码导入:现存规则不用迁移
omp 在首次启动时扫描磁盘,继承已有的 agent 配置:.claude、.cursor、.windsurf、.gemini、.codex、.cline、.github/copilot、.vscode 八个目录里的规则、skills 和 MCP server 全部识别,不需要迁移脚本。README 的说法是"Every other agent ships an importer and expects you to convert"——别家给你转换器,omp 直接读原生格式。
支持的格式包括 Cursor MDC、Cline .clinerules、Codex AGENTS.md、Copilot applyTo 等。对已有其他工具配置积累的团队,这是实质性的换用成本降低。
适用边界与采用建议
推荐先上的团队:
- 已有多个 provider API key,希望统一调度而不绑定单一生态
- 高频处理多文件重构(rename across barrel files、跨模块 symbol 追踪)
- 有 native 调试场景(lldb/dlv/debugpy)
- 子 Agent 协调场景较多的工作流
可以等等的:
- 纯 Web/API 开发,不涉及 native 调试,也不需要多 kernel eval
- 已经深度绑定某一特定 coding agent 生态,迁移成本高于收益
- 团队成员偏好 GUI/IDE 集成而非 TUI 操作
从哪个入口开始:
bun install -g @oh-my-pi/pi-coding-agent完成安装omp启动 TUI,跑一个真实任务(改一个 bug、修一个配置错误)感受工具调用的响应速度- 有多个 provider key 的话,在
~/.omp/agent/models.yml声明自定义 provider,在~/.omp/agent/config.yml的modelRoles与retry.fallbackChains里配好路由与降级链 - 会话中用
/model切换九个角色;需要跨 session 记忆时,到设置里打开 memory backend
结尾判断
omp 不是一个"更多模型的 wrapper"。它的核心差异化在于把工具层作为一等公民来设计:hashline 编辑解决格式损耗、Rust 内联原语解决执行效率、可插拔记忆解决跨 session 延续、子 Agent 协调解决并行任务管理。这四件事单独看都不复杂,但组合在一起,模型输出的东西能完整、准确、低损耗地进入磁盘——模型本身并没有变强,变强的是模型与磁盘之间的那一段。
如果你的团队正在评估 Coding Agent 的工具链上限,omp 值得跑一个真实任务试试。
数据核实说明:本文 2026-05-20 首发,2026-10-03 对照 can1357/oh-my-pi main 分支 README(701 行)与浅克隆源码全量复核并刷新读数;omp 迭代极快,工具数、LoC、角色数等硬数字以当期 README 口径行为准。
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。