Oh My Pi(omp)入门教程
Oh My Pi(命令行简称 omp)是一个运行在终端里的开源 AI 编程 Agent,由 Can Bölük fork 自 Mario Zechner 的 Pi 并大幅扩展而来。
Oh My Pi 的核心理念是:工具不应该只是「连上去」,而要被打磨到极致——每一个工具都经过基准测试调优,编辑命中率、搜索速度、LSP 集成都力求做到同类最优。
-
官网:omp.sh
omp 是什么?
omp 是一个终端优先的 AI 编程 Agent。它不依赖任何 IDE,在你的终端里以全功能 TUI 运行,集成了 LSP、DAP 调试器、Python/JavaScript 双执行内核、子 Agent 并行、跨会话记忆,以及一套经过基准调优的 32 个工具。
和其他 AI 编程工具的差异
| 维度 | Claude Code / 同类工具 | omp |
|---|---|---|
| 编辑格式 | str_replace(易出错) | Hashline(内容哈希锚点,抗空白差异) |
| 文件读取 | 全文 dump | 结构摘要 + 按需展开 |
| LSP | 无或有限 | 完整 14 个 LSP 操作(含重命名、跳转、代码动作) |
| 调试器 | 无 | 完整 DAP:lldb、dlv、debugpy |
| 子 Agent | 无或有限 | 并行子 Agent,隔离工作区,类型化返回值 |
| 搜索 | shell 调用 ripgrep | in-process ripgrep,无 fork/exec |
| 行为纠正 | 靠 prompt | 流规则:正则命中 → mid-token 注入 → 重试 |
| 跨会话记忆 | 无 | Hindsight 记忆银行(项目级) |
| 代码执行 | Python sandbox | 持久 Python + Bun 双内核,可互相调用 Agent 工具 |
| 技术栈 | 纯 JS/Python | ~55,000 行 Rust 核心 + TypeScript |
安装
本节介绍 omp 在 macOS、Linux、Windows 上的多种安装方式。
macOS / Linux(推荐)
$ curl -fsSL https://omp.sh/install | sh
安装脚本会自动检测 Bun 是否可用:有 Bun(≥ 1.3.14)则优先用 Bun 安装,否则下载预构建二进制。
Homebrew(macOS / Linux)
$ brew install can1357/tap/omp
Bun(推荐,获得最新版)
$ bun install -g @oh-my-pi/pi-coding-agent
Windows(PowerShell)
$ irm https://omp.sh/install.ps1 | iex
Windows 支持原生运行,无需 WSL。
版本锁定(mise)
$ mise use -g github:can1357/oh-my-pi
验证安装
$ omp --version
Shell 自动补全
omp 从 CLI 元数据动态生成补全脚本,因此子命令、Flag 和枚举值永远不会与实际 CLI 脱节:
# zsh(加入 ~/.zshrc) eval "$(omp completions zsh)" # bash(加入 ~/.bashrc) eval "$(omp completions bash)" # fish omp completions fish > ~/.config/fish/completions/omp.fish
从源码构建
$ git clone https://github.com/can1357/oh-my-pi $ cd oh-my-pi $ bun setup # 安装 Bun 工作区依赖并构建 Rust N-API 插件 $ bun dev # 启动开发版 CLI # 修改 Rust 代码后,重新构建原生插件 $ bun run build:native
初次配置:登录模型提供商
首次运行 omp 后,使用 /login 或 /model 配置你的 AI 提供商。
方式一:OAuth 一键登录(无需 API Key)
omp 支持多个提供商通过 OAuth 登录,最简单的方式:
/login # 打开交互式提供商选择器
支持 OAuth 的提供商包括:Anthropic、OpenAI Codex、Google Antigravity(Gemini)、Perplexity、Cursor、GitHub Copilot、GitLab Duo 等。
方式二:API Key(直连提供商)
# 在环境变量里设置(推荐写入 ~/.zshrc 或 ~/.bashrc) export ANTHROPIC_API_KEY="sk-ant-xxxx" export OPENAI_API_KEY="sk-xxxx" export GOOGLE_API_KEY="xxxx"
或在 omp 里直接配置:
/model # 打开模型选择器,可以在这里配置 Key
方式三:Coding Plan 订阅
如果你已经订阅了 Cursor、GitHub Copilot、Kilo、Kimi Code、MiniMax Coding Plan 等服务,可以直接路由到你的订阅:
/login # 选择对应的 Coding Plan 提供商,OAuth 授权
方式四:本地模型(Ollama / LM Studio)
# 先启动 Ollama $ ollama serve # 在 omp 里选择 Ollama 提供商(key 可选) /model # 选择 Ollama,指向 http://localhost:11434
配置路径
所有配置存储在 ~/.omp/ 目录:
~/.omp/ agent/ settings.yml # 主配置文件 models.yml # 自定义模型/提供商 keybindings.yml # 快捷键绑定 rules/ # 流规则(stream rules) skills/ # 技能文档
第一次对话:TUI 基础操作
本节介绍 omp 的全屏 TUI 界面和基本交互方式。
启动 omp
# 在项目目录下启动 $ cd ~/your-project $ omp
omp 启动后进入全屏 TUI(终端用户界面),工具调用以卡片形式渲染,编辑操作在落盘前显示预览。
注意:omp 使用 Kitty 键盘协议,推荐在支持该协议的终端下运行(Kitty、Ghostty、WezTerm、iTerm2)以获得最佳体验。
基本交互
输入你的任务,按 Enter 发送:
> 分析这个项目的目录结构,告诉我主要模块是什么
omp 会自动调用 read、search 等工具扫描代码库,返回结构化摘要。
常用键位
| 按键 | 功能 |
|---|---|
| Enter | 发送消息 |
| Ctrl+J / Shift+Enter | 消息内换行(不发送) |
| Ctrl+P | 循环切换当前角色的可用模型 |
| Shift+Ctrl+P | 反向循环切换 |
| Ctrl+T | 展开/折叠 Todo 面板 |
| Ctrl+C | 中断当前任务 |
| Esc | 取消待确认操作 |
| ↑ / ↓ | 浏览历史消息 / 选项 |
| ? | 在空白输入时插入 ?;用 /hotkeys 查看快捷键列表 |
单次执行(非交互模式)
# 一次性执行任务并退出 $ omp -p "列出所有 .ts 文件里未使用的 export" # 管道输入 $ git diff HEAD~1 | omp -p "给这个 diff 写一个精简的 commit message"
恢复历史会话
$ omp --resume # 打开会话选择器(Tab 补全可用) $ omp --resume <id> # 直接恢复指定会话
核心工具详解
omp 的 32 个工具统一在一个命名空间里,read、search、bash 是日常使用最频繁的三个。
read:统一读取接口
read 是 omp 的杀手工具之一。它不只是读文件——它理解内容结构:
# 读文件(返回结构化摘要,而非全文 dump) read src/auth/login.ts # 读目录(返回树形结构概览) read src/ # 读 URL(返回结构化 Markdown,锚点保留) read https://docs.anthropic.com/en/api/messages # 读 arxiv 论文 PDF read https://arxiv.org/pdf/2604.10739v1 # 读 SQLite 数据库 read data/app.db # 读 GitHub PR(统一路径接口) read pr://can1357/oh-my-pi/1428 # 读 PR 的 diff read pr://can1357/oh-my-pi/1428/diff/1 # 读 GitHub Issue read issue://can1357/oh-my-pi/142
关键设计:read 对文件返回的是 Tree-sitter 生成的结构化摘要(函数名、类名、重要注释),而不是把整个文件 dump 进上下文。这大幅节省 Token 同时保留了关键信息,需要详细内容时 Agent 会再次调用 read 展开具体段落。
search:in-process ripgrep
# 正则搜索(无 fork/exec,直接在进程内跑)
search "useState\(" src/
# 带文件类型过滤
search "TODO:" --type ts
# 在内部 URL 上搜索(如 PR diff)
search "loginUser" pr://can1357/oh-my-pi/1063/diff
edit:Hashline 精确编辑
详见下一节。这是 omp 技术含量最高的工具之一。
bash:持久 Shell 会话
# 执行命令(bash 会话在调用间保持存活) bash: npm test bash: git log --oneline -10 bash: cargo build --release
omp 的 bash 工具嵌入了完整的 brush shell(Rust 实现的 bash),不是每次 fork 一个新进程,而是维持持久会话,环境变量和工作目录跨调用保留。
eval:Python + JavaScript 持久内核
详见后续章节。
lsp:完整 LSP 操作
详见后续章节。
todo:任务管理
omp 内置结构化任务列表,支持阶段(phase)和任务状态跟踪。Ctrl+T 切换 Todo 面板可见性。
ask:结构化问题
Agent 在需要用户决策时调用 ask,弹出带有推荐选项的交互式选择器,而不是在输出里混入问题。
Hashline:更精准的文件编辑
这是 omp 最重要的技术创新之一。本节介绍 Hashline 的工作原理和基准测试结果。
传统 str_replace 的问题
其他 Agent 大多使用 str_replace 格式让模型输出「旧内容」+「新内容」对。问题在于:
- 模型容易把旧内容的空格、换行、引号搞错
- 文件一旦在 Agent 操作后被修改,锚点就失效了
- 错误导致大量重试,消耗更多 Token
Hashline 的解法
Hashline 让模型用内容哈希来标识要修改的行,而不是重新打出那些内容:
# Hashline patch 示例(Agent 内部生成,你不需要手写)
@@{a3f2}
- const result = compute(x)
+ const result = compute(x, options)
@@{b7c1}
- return null
+ return undefined
{a3f2} 是目标行内容的哈希前缀。如果文件改变导致哈希对不上,patch 会被拒绝而不是静默地打错地方。
基准测试结果
来自 README 的实测数据:
| 模型 | 指标 | 效果 |
|---|---|---|
| Grok Code Fast 1 | 编辑成功率 | 6.7% → 68.3%(10 倍提升) |
| Gemini 3 Flash | vs str_replace | +5 个百分点,超过 Google 自己的最佳实现 |
| Grok 4 Fast | Output Token 消耗 | 减少 61% |
| MiniMax | 通过率 | 提升 2.1 倍(权重和 Prompt 完全不变) |
ast_edit:结构化代码重写
比 Hashline 更高层的编辑工具,用 ast-grep 模式匹配后结构化重写:
# 把所有 console.log(...) 替换掉 ast_edit: console.log($X) → logger.debug($X)
ast_edit 先返回一个 proposed(预览)卡片,Agent 确认后调用 resolve 才真正落盘——原子操作,要么全部成功,要么全部不变。
ast_grep:结构化代码查询
支持 50+ 语言的 Tree-sitter 语法匹配:
# 找出所有没有 await 的 async 函数调用 ast_grep: "promise.then($X)"
LSP 集成:IDE 知道的,Agent 也知道
omp 集成了完整的 LSP(Language Server Protocol)客户端,支持 14 种操作。
配置 LSP 服务器
在项目目录的 .omp/ 里配置,或通过 omp 的配置向导:
实例
lsp:
servers:
typescript:
command: typescript-language-server
args: ["--stdio"]
rust-analyzer:
command: rust-analyzer
python:
command: pylsp
14 个 LSP 操作
| 操作 | 说明 |
|---|---|
| diagnostics | 获取文件/工作区的诊断错误(类似 IDE 红波浪线) |
| hover | 获取符号的类型信息和文档注释 |
| definition | 跳转到定义 |
| references | 查找所有引用 |
| rename | 重命名符号(通过 workspace/willRenameFiles,确保 re-export 和 barrel 文件同步更新) |
| code_action | 获取并执行代码动作(如自动导入、修复 lint 错误) |
| completion | 获取补全列表 |
| signature_help | 获取函数签名帮助 |
| document_symbols | 获取文件内所有符号 |
| workspace_symbols | 在整个工作区搜索符号 |
| format | 格式化文件 |
| range_format | 格式化选定范围 |
| implementation | 跳转到接口实现 |
| type_definition | 跳转到类型定义 |
重命名的正确做法
普通 Agent 做重命名:搜索字符串,逐个替换,容易漏掉或误替换。omp 的做法是通过 LSP 协议完成:
> 把 formatBytes 函数重命名为 humanizeFileSize
# omp 内部执行:
lsp.references("formatBytes") → 找到 5 处引用,分布在 3 个文件
lsp.rename("formatBytes", "humanizeFileSize") → 通过 LSP workspace/willRenameFiles
search "formatBytes" → 0 matches ✓ 完成
Re-exports、barrel 文件(index.ts)、aliased imports 全部正确更新,因为重命名走的是 LSP 协议而不是文本替换。
调试器集成(DAP)
omp 实现了完整的 DAP(Debug Adapter Protocol)客户端,支持 28 个调试操作。
支持的调试器
| 语言 | 调试器 |
|---|---|
| C / C++ / Rust | lldb-dap / codelldb |
| Go | dlv(Delve) |
| Python | debugpy |
| Node.js / TypeScript | Node.js built-in inspector |
| 通用 | 任何兼容 DAP 的调试器 |
典型场景:定位 C 程序崩溃
> 这个 C 程序一直 segfault,帮我找原因
# omp 内部执行:
debug.launch("lldb-dap", "./build/demo")
debug.continue() # 运行到崩溃
debug.pause()
debug.stackTrace() # 查看调用栈
debug.scopes(frameId) # 查看局部变量
debug.evaluate("*ptr") # 评估表达式
典型场景:Go 服务死锁排查
> Go 服务挂住了,帮我看看
# omp 内部执行:
debug.attach("dlv", pid)
debug.threads() # 列出所有 goroutine
debug.stackTrace(threadId) # 查看挂住的 goroutine 调用栈
不再需要满代码撒 fmt.Println 或 console.log——omp 直接驱动真正的调试器。
子 Agent(Subagents):并行处理
当一个任务可以被拆分成相互独立的子任务时,omp 用 task 工具生成并行子 Agent,每个子 Agent 在隔离的工作区里运行,最终返回类型化的结果对象。
工作区隔离机制
omp 使用平台原生的文件系统快照来隔离子 Agent 的工作区:
| 操作系统 / 文件系统 | 隔离机制 |
|---|---|
| macOS(APFS) | APFS clone(瞬时,零 copy-on-write) |
| Linux(btrfs/zfs) | reflink |
| Linux(overlayfs) | overlay mount |
| Windows | projfs / rcopy |
每个子 Agent 拿到的是一个独立的工作区副本,互不干扰,不会产生合并冲突。
使用示例
> 我有三个微服务:auth-service、api-service、worker-service。
请同时检查它们的依赖有没有已知的安全漏洞,分别出报告。
# omp 内部执行:
task(workers=[
{name: "auth", workdir: "services/auth"},
{name: "api", workdir: "services/api"},
{name: "worker", workdir: "services/worker"}
])
# 三个子 Agent 并行跑,各自输出结构化 JSON:
# { findings: [...], severity: "high", affected: ["[email protected]"] }
# 父 Agent 合并结果,汇总报告
子 Agent 间通信(IRC)
并行子 Agent 之间可以通过 irc 工具进行短消息通信,协调分工:
# 子 Agent A:
irc.send("ComponentsExports", {exports: ["Button", "Input"]})
# 子 Agent B 收到消息后调整自己的分析范围
拉取子 Agent 结果
父 Agent 可以用路径语法直接访问子 Agent 的结构化输出:
# 读取子 Agent findings 的第一条记录的 path 字段 read agent://<subagent-id>/findings.0.path
Hindsight:跨会话记忆
Hindsight 是 omp 的项目级记忆系统,让 Agent 在会话之间保留对代码库的理解。
工作原理
- retain:Agent 在运行中发现有价值的信息时,主动调用 retain 写入记忆银行
- recall:用关键字搜索记忆银行
- reflect:让 Hindsight 综合记忆银行里的信息,生成一个合成性回答
- 每次会话结束时,omp 自动将会话压缩成「心智模型」,下次会话第一轮就加载
作用域
Hindsight 是项目级别的——在 A 项目学到的东西,不会泄漏到 B 项目。记忆存储在 .omp/ 目录下(或 ~/.omp/ 里按项目分片)。
实际效果
第一次在一个项目里使用 omp,你需要解释项目结构。使用一段时间后,omp 自己就知道:
- 这个项目用什么技术栈
- 主要模块的职责划分
- 曾经做过哪些重构
- 哪些文件是「地雷区」(经常出问题的地方)
代码执行:Python + JavaScript 双内核
大多数 Agent 工具只提供一个 Python 沙箱。omp 运行两个持久内核,并且两者都可以回调 Agent 自己的工具。
Python 内核(eval)
实例
import pandas as pd
df = pd.read_csv(tool.read("data/sales.csv")) # 用 Agent 的 read 工具加载文件
print(df.describe())
result = tool.search("revenue", "src/") # 在代码库里搜索
JavaScript(Bun)内核(eval)
实例
const data = tool.read("data/sales.csv") // 同样可以调用 Agent 工具
const top = data.split('\n').slice(1)
.map(line => line.split(','))
.sort((a, b) => +b[2] - +a[2])
.slice(0, 5)
console.table(top)
双内核共享 Prelude
两个内核共享一个 prelude(预加载上下文),可以在 Python 里处理数据,然后在 JS 里生成图表,整个过程是一个连续的 eval 会话,无需离开工具界面。
流规则(Stream Rules):实时行为纠正
这是 omp 独有的实时行为纠正机制,解决的是「模型不听话」的问题。
传统做法的问题
把所有规范写进 System Prompt,每次对话都要付出全量的 Token 成本,而且模型仍然可能忽略。
流规则的工作方式
规则是睡眠的,直到触发条件出现:
- 正则表达式监听模型的流式输出
- 一旦命中(mid-token 级别),立即中止当前流
- 把规则内容作为系统提醒注入上下文
- 从同一位置重新生成
- 注入的规则在上下文压缩后仍然存活
实例
# ~/.omp/agent/rules/no-box-leak.yml
name: box-leak
pattern: "Box::leak"
reminder: |
不要在生产代码路径中使用 Box::leak。
内存泄漏会导致服务在高负载下 OOM。
改用 Arc<str> 或其他引用计数方案。
效果:模型写到 Box::leak 时,流被中止,规则被注入,模型自动纠正为 Arc
用 /omfg 快速创建规则
omp 提供了一个辅助命令让你用自然语言描述规则,它来生成正则和规则文件:
/omfg 不要在任何地方用 any 类型,要求用具体的类型定义或 unknown
omp 会生成规则、验证、保存,下次起效。
模型路由:40+ 提供商,四个角色
omp 用角色(role)而不是模型名来调度工作,实现「对的任务用对的模型」。
四个模型角色
| 角色 | 用途 | CLI Flag | 环境变量 |
|---|---|---|---|
| default | 常规对话和代码生成 | 默认 | — |
| smol | 廉价子 Agent 探索 | --smol | PI_SMOL_MODEL |
| slow | 深度推理任务 | --slow | PI_SLOW_MODEL |
| plan | 计划模式 | --plan | PI_PLAN_MODEL |
# 启动时指定角色覆盖 $ omp --smol # 整个会话使用 smol 模型(低成本) $ omp --slow # 使用慢速推理模型(高质量) $ omp --plan # 使用计划专用模型
会话中切换模型
/model # 打开交互式模型选择器 /model claude-sonnet-4.6 # 切换到指定模型 Ctrl+P # 循环切换当前角色的可用模型
自定义提供商(~/.omp/agent/models.yml)
实例
providers:
my-company-llm:
type: openai-completions
baseUrl: https://llm.internal.company.com/v1
apiKey: "${MY_LLM_KEY}"
models:
- id: gpt-4o
name: Internal GPT-4o
故障转移链
实例
retry:
fallbackChains:
default:
- anthropic/claude-sonnet-4.6
- openai/gpt-4o
- google/gemini-2.0-flash
路径级模型绑定
实例
models:
enabledModels:
- path: ~/projects/side-project
models: ["deepseek/deepseek-coder"]
证书轮转(多 Key 负载均衡)
实例
providers:
anthropic:
apiKeys:
- "${ANTHROPIC_KEY_1}"
- "${ANTHROPIC_KEY_2}"
- "${ANTHROPIC_KEY_3}"
# 自动轮转,单个 Key 超限后切到下一个
常用斜杠命令速查
在对话输入框里输入 / 触发命令补全。
| 命令 | 功能 |
|---|---|
| /model | 打开模型选择器 |
| /login | 登录提供商(OAuth) |
| /resume | 恢复历史会话 |
| /review | 对当前分支 / 指定 commit / 未提交改动做代码审查 |
| /commit | 智能拆分 commit |
| /omfg | 用自然语言创建流规则 |
| /debug | 打开调试/报告/性能分析工具 |
| /hotkeys | 查看所有快捷键 |
| /reload-plugins | 热重载插件 |
| /compact | 手动压缩上下文(节省 Token) |
| /? | 显示帮助 |
/review:带优先级的代码审查
# 审查当前分支 vs main /review # 审查指定 commit /review abc1234 # 审查未提交的改动 /review --unstaged
omp 生成专门的 reviewer 子 Agent 并行扫描,每个问题按 P0-P3 优先级排序,并给出置信度评分。P0 = 阻止上线,P3 = 可选改进。
/commit:原子提交拆分
$ omp commit
omp 读取整个工作树(git_overview + git_file_diff + git_hunk),把不相关的改动拆分成独立的原子 commit,按依赖顺序排列:
- 源代码 commit 排在测试、文档、配置之前
- 有依赖关系的改动不会被错误分组
- 循环依赖被拒绝,不会写入任何内容
- package-lock.json、Cargo.lock 等 lockfile 不参与分析
插件与扩展
omp 的插件是 TypeScript 模块,使用和内置工具完全相同的 API,没有任何保留接口。
安装插件
$ omp install <plugin-name> # 从 npm 安装 $ omp install github:user/repo # 从 GitHub 安装 $ omp install ./path/to/plugin # 从本地路径安装
创建插件
你可以直接让 omp 帮你写:
> 给我创建一个插件,添加 /deploy 命令, 自动运行测试、构建、然后 SSH 上传到生产服务器
omp 会生成插件代码,你 /reload-plugins 后立即生效。
热重载
修改插件代码后无需重启 omp:
/reload-plugins
ACP:在 Zed 编辑器里使用 omp
$ omp acp
通过 Agent Client Protocol 将 omp 接入 Zed 编辑器。omp 会读取你正在编辑的 buffer,通过编辑器的保存路径写文件,在编辑器的终端里启动 shell,破坏性操作会触发权限弹窗。
从其他工具迁移
omp 的一大优点是开箱即读其他工具已经创建的配置文件,无需迁移脚本:
| 工具 | 配置文件 | omp 读取方式 |
|---|---|---|
| Cursor | .cursor/rules/*.mdc | 自动继承 |
| Claude Code | .claude/settings.json、CLAUDE.md | 自动继承 |
| Cline | .clinerules | 自动继承 |
| GitHub Copilot | .github/copilot/instructions.md(applyTo) | 自动继承 |
| Codex | AGENTS.md | 自动继承 |
| Windsurf | .windsurfrules | 自动继承 |
| Gemini CLI | .gemini/ 配置 | 自动继承 |
第一次运行 omp 时,它扫描工作目录,自动加载检测到的所有格式。
资源与社区
- 官网:omp.sh
- GitHub:github.com/can1357/oh-my-pi(MIT 开源)
- 工具文档:omp.sh/docs/tools
- 提供商文档:omp.sh/docs/providers
- SDK 文档:omp.sh/docs/sdk
- Changelog:github.com/can1357/oh-my-pi/CHANGELOG.md
- npm:@oh-my-pi/pi-coding-agent
- Discord:discord.gg/4NMW9cdXZa