oh-my-pi (omp) is the terminal coding agent that answers a blunt question: why do agents keep failing edits that should work? Built by Can Bölük as a fork of Mario Zechner's Pi, omp adds the harness engineering missing from most agent surfaces—hash-anchored edits that eliminate whitespace battles, LSP integration so renames propagate correctly, DAP-driven debugging against live binaries, 40+ model providers with per-role routing, and subagent orchestration across isolated worktrees. The repository has climbed to 5.5k+ stars in months, with a 458-fork ecosystem and 177 contributors—signals that teams want production-grade tools, not demo prompts.
This article is a field guide: what problem it solves, the core architecture, installation paths, feature comparison, and when to choose omp over Claude Code, Cursor, or a custom harness.
TL;DR
| Question | Short answer |
|---|---|
| What is it? | A batteries-included terminal coding agent forked from Pi, adding hashline edits, LSP/DAP, 40+ providers, 32 tools, and subagent fan-out. |
| Primary source | github.com/can1357/oh-my-pi (MIT). |
| Attribution | Fork of Pi by Mario Zechner; maintained by Can Bölük. |
| Install (macOS/Linux) | curl -fsSL https://omp.sh/install | sh |
| Install (Bun) | bun install -g @oh-my-pi/pi-coding-agent |
| Install (Windows) | irm https://omp.sh/install.ps1 | iex |
| Key differentiator | Hash-anchored edits (hashline format) eliminate string-not-found loops; LSP provides IDE-grade intelligence; DAP drives real debuggers. |
| Related ecosystem | Pairs with agent skills, MCP servers, and harness engineering patterns. |
The official site and docs provide installation, provider configuration, and tool reference.
The problem: why agents fail at edits
The upstream README quotes a harsh truth from production usage:
- String replacement fails — Whitespace, line endings, or stale context make
old_stringnot match, so the edit is rejected or corrupts the file. - Renames are incomplete — The agent renames a symbol in one file but misses re-exports, barrel imports, or aliased references.
- No debugging story — When a binary segfaults or a service hangs, the agent sprinkles
console.logorprint()instead of attaching a real debugger. - Search is slow — Every
greporfindforks a subprocess; on large monorepos, this adds seconds per call. - One provider, one bill — Most harnesses lock you into a single API; if that provider hits quota or throws 429s, the session dies.
oh-my-pi addresses all five with harness engineering: structural changes that make the failure mode impossible, not one-off prompt patches.
Core architecture: ~27k lines of Rust doing the work other harnesses shell out for
omp ships three Rust crates compiled into a single N-API addon:
| Crate | What it does | ~LoC |
|---|---|---|
| pi-shell | Embedded bash (brush-shell fork), persistent sessions, timeout/abort, custom builtins | 3,700 |
| pi-grep | Regex search, parallel/sequential, glob & type filters, fuzzy find | 1,900 |
| pi-ast | tree-sitter structural summaries and ast-grep pattern matching/rewrites | 1,040 |
Plus keys (Kitty keyboard protocol), text (ANSI-aware width/truncation), highlight (syntect), pty (portable-pty), glob (ignore + globset), image (decode/encode/resize), tokens (tiktoken BPE), html (HTML→Markdown), and more—all in-process on the libuv thread pool. No fork/exec on the hot path.
Platform targets: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64. The same omp binary runs on macOS, Linux, and Windows—no WSL bridge.
Feature 01: Hash-anchored edits (hashline format)
Problem: str_replace diffs fail when whitespace, line endings, or model hallucination makes old_string not match.
Solution: The model references content hashes as anchors instead of retyping lines. If anchors diverge (the file changed since the agent read it), the patch is rejected before it corrupts anything.
Impact: Grok 4 Fast spends 61% fewer output tokens on the same work. Gemini 3 Flash gains +5 pp over str_replace. MiniMax doubles its pass rate—same weights, same prompt, different edit format.
Example:
✓ AST Edit: console.log($X) (proposed) 3 replacements · 1 file
✓ Accept: 3 replacements in 1 file (AST Edit)
Applied 3 replacements in src/auth.ts.
The replacement count previews before apply; the change is staged, then accepted with a reason.
Feature 02: LSP integration—everything your IDE knows, the agent knows
Problem: The agent renames a symbol in one file but misses re-exports, barrel files, or aliased imports.
Solution: The lsp tool exposes diagnostics, navigation (go-to-definition, references), symbols, renames, code actions, and raw LSP requests. When the agent renames, it goes through workspace/willRenameFiles, so downstream updates happen correctly.
Example workflow:
✓ LSP references: formatBytes → 5 hits across 3 files
✓ LSP rename: formatBytes → formatFileSize
- format.ts: 2 edits
- report.ts: 2 edits
- cli.ts: 1 edit
✓ Search formatBytes → 0 matches
Rename complete.
Supported operations:
- Diagnostics (errors, warnings, hints)
- Navigation (definition, references, implementations, type-definition)
- Symbols (document, workspace)
- Renames (with
willRenameFilespropagation) - Code actions (quick fixes, refactors)
- Raw requests (custom LSP methods)
Feature 03: Drives a real debugger (DAP)
Problem: When a binary segfaults, a Go service hangs, or a Python process wedges, the agent sprinkles print() instead of inspecting state.
Solution: The debug tool speaks DAP (Debug Adapter Protocol). It attaches lldb (native), dlv (Go), debugpy (Python), and other DAP-compatible adapters—breakpoints, stepping, threads, stack inspection, variable evaluation.
Example session (lldb-dap):
✓ Debug attach: /tmp/omp-native/demo
Adapter: lldb-dap
Status: stopped
Frame: xorshift32
Instruction pointer: 0x10000055C
Location: demo.c:6:10
✓ Debug scopes: locals
x = 57351
✓ Debug evaluate: 7 ^ (7 << 13)
= 57351
Agent: "x went from 7 → 57351 (= 7 ^ (7<<13)), confirming the xorshift step."
Supported operations:
- Launch or attach
- Breakpoints (line, conditional, logpoints)
- Stepping (step, next, step-in, step-out, continue)
- Threads and stack frames
- Scopes and variables
- Evaluate expressions
- Pause, restart, disconnect
Feature 04: 40+ providers, one interface
Problem: Most harnesses lock you into one API. If that provider hits quota, throws 429s, or has a model outage, the session dies.
Solution: omp routes by role (default, smol, slow, plan, commit). Each role can have a fallback chain; when the primary throws 429s, the next entry takes the rest of the turn—restored on cooldown. Round-robin credentials per provider rotate with session affinity and per-credential backoff.
Provider categories:
| Category | Examples |
|---|---|
| Frontier APIs | Anthropic (oauth), OpenAI, Google Gemini (oauth), xAI, Mistral, Groq, Cerebras, Fireworks, Together, Hugging Face, NVIDIA, OpenRouter, Perplexity (oauth) |
| Coding plans | Cursor (oauth), GitHub Copilot (oauth), Codex (oauth), Kimi Code, Moonshot, MiniMax Coding Plan, Alibaba Coding Plan, Qwen Portal, Z.AI/GLM |
| Self-hosted | Ollama (local), LM Studio (local), llama.cpp (local), vLLM (local), LiteLLM |
Custom providers: Declare anything that speaks openai-completions, anthropic-messages, google-generative-ai, or google-vertex in ~/.omp/agent/models.yml.
Role-based routing example:
modelRoles:
default: anthropic/sonnet-4.5
smol: groq/llama-3.3-70b-versatile
slow: openai/o1
plan: anthropic/opus-4.5
commit: anthropic/haiku-4
Feature 05: 32 tools, one namespace
omp ships 32 tools in the same namespace as read and bash. The active set is controlled by --tools read,edit,bash,...; the rest stay hidden but indexed—search_tool_bm25 pulls them back mid-session when tools.discoveryMode allows.
Tool categories:
| Category | Tools |
|---|---|
| Files & search | read, write, edit, ast_edit, ast_grep, search, find |
| Runtime | bash, eval (Python + JavaScript), recipe (task runners), ssh |
| Code intelligence | lsp (LSP operations), debug (DAP sessions) |
| Coordination | task (subagent fan-out), irc (inter-agent prose), todo_write, job (background job control), ask (structured questions) |
| Outside the box | browser (Puppeteer), web_search (14 providers), github (gh CLI), generate_image, inspect_image, render_mermaid |
| Memory & state | checkpoint, rewind, retain (Hindsight), recall, reflect |
| Misc | calc, resolve (preview apply/discard), search_tool_bm25 |
read handles 10+ internal schemes:
pr://,issue://— GitHub PRs and issuesagent://<id>/findings.0.path— pull fields from subagent outputconflict://N— each merge conflict becomes a URL; write@theirs,@ours, or@baseskill://,rule://— walk skills and rules transparently
Example (conflict resolution):
✓ Read src/session.ts (⚠ 1 conflict)
✓ Write conflict://1 · 1 line
Content: @theirs
Resolved.
Feature 06: Subagent orchestration (task tool)
Problem: Fan-out work across isolated contexts without merge conflicts or orphaned edits.
Solution: The task tool spawns subagents in parallel, each running in an isolated workspace:
- APFS clones (macOS)
- btrfs reflinks (Linux)
- zfs clones (Linux/BSD)
- overlayfs (Linux)
- projfs (Windows)
- rcopy (fallback)
Each worker runs its own tool surface and yields a schema-validated object the parent reads directly—no prose to parse.
Example:
✓ Task: ComponentsExports (in-progress)
✓ Task: RoutesExports (in-progress)
Constraints:
- IRC DM between peers required
Results:
ComponentsExports → { exports: [...], duration: 12.3s, cost: $0.04 }
RoutesExports → { exports: [...], duration: 11.8s, cost: $0.03 }
Findings:
- 47 component exports
- 23 route exports
- IRC coordination note: one-sided handshake (ComponentsExports sent, RoutesExports did not reply)
Feature 07: web_search with 14 providers and site-aware extraction
Problem: Generic web fetch returns stripped HTML; the agent loses link structure and can't cite or follow anchors.
Solution: web_search chains 14 providers (auto mode walks the chain; pin one by name). Site-aware extraction turns GitHub, arXiv, Stack Overflow, npm, PyPI, crates.io, docs.rs, and more into structured markdown with anchors and link targets intact.
Providers: auto (chain), exa, brave, jina, kimi, zai, anthropic (oauth), perplexity, gemini (oauth), codex (oauth), tavily, parallel, kagi, synthetic, searxng (self-hosted).
Example:
✓ web_search: "inference-time compute scaling"
Provider: perplexity
10 ranked sources
✓ read https://arxiv.org/pdf/2604.10739v1
Extracted: structured markdown with sections, equations, citations
Agent: "The paper reports a 3.2× improvement on MATH with 64 test-time samples vs greedy decoding (Table 2, page 5)."
Feature 08: Time-traveling stream rules
Problem: The model goes off-script; you want to inject a correction mid-stream without paying context tax on every turn.
Solution: Stream rules sit dormant until a regex match aborts the stream mid-token, injects the rule as a system reminder, and retries from the same point. Injections survive compaction, so the fix sticks.
Example:
✓ Reading src.rs
Agent: "Let me use Box::leak to..."
⚠ Request aborted
⚠ Injecting rule: box-leak
"Don't reach for Box::leak in production code paths."
Agent: "On second thought, Arc<str> is safer here. Should I proceed?"
Feature 09: Hindsight—memory the agent curates
Problem: The agent forgets codebase facts between sessions.
Solution: Hindsight lets the agent write facts mid-run with retain, pull them back with recall, and compress each session into a mental model that loads on the first turn of the next one. Project-scoped by default.
Tools:
- retain — queue durable facts into the active Hindsight bank
- recall — search the bank for raw memories
- reflect — ask Hindsight to synthesize an answer over the bank
Feature 10: Four entry points—interactive, one-shot, RPC, ACP
Same engine, four wrappers:
| Mode | When to use |
|---|---|
| Interactive (TUI) | Default. Tool calls render as cards, edits preview before apply, ambiguity routes through the ask tool. |
One-shot (omp -p) | Single prompt, exit. Useful in CI or scripts. |
| Node SDK | Embed the session in a Node/TypeScript process. @oh-my-pi/pi-coding-agent exposes ModelRegistry, SessionManager, createAgentSession. |
RPC (omp --mode rpc) | NDJSON commands over stdio. For non-Node embedders or process isolation. |
ACP (omp acp) | Agent Client Protocol (JSON-RPC). When the editor advertises capabilities, tool I/O routes through it and writes are gated by session/request_permission. |
SDK example:
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");
Installation
| Platform | Command |
|---|---|
| macOS / Linux | curl -fsSL https://omp.sh/install | sh |
| Bun (recommended) | bun install -g @oh-my-pi/pi-coding-agent |
| Windows (PowerShell) | irm https://omp.sh/install.ps1 | iex |
| mise (pinned versions) | mise use -g github:can1357/oh-my-pi |
Requirements: Bun ≥ 1.3.14.
Configuration: ~/.omp/agent/models.yml for provider routing, ~/.omp/agent/settings.yml for tool defaults, rules, and extensions.
When to choose omp over Claude Code / Cursor / Codex
| Factor | oh-my-pi (omp) | Claude Code / Cursor / Codex |
|---|---|---|
| Edit accuracy | Hash-anchored (hashline) format eliminates string-not-found loops | String replacement or unified diff (subject to whitespace battles) |
| Code intelligence | LSP integration (diagnostics, references, renames with propagation) | IDE-provided intelligence (not directly accessible to agent in most cases) |
| Debugging | DAP-driven (lldb, dlv, debugpy) | No debugger integration |
| Provider flexibility | 40+ providers with per-role routing, fallback chains, round-robin credentials | Locked to vendor (Claude, OpenAI, GitHub, etc.) or limited multi-provider support |
| Subagent orchestration | task tool with isolated worktrees (APFS/btrfs/overlayfs) | No native subagent fan-out |
| Terminal-first | TUI, one-shot, RPC, ACP | IDE-integrated (VS Code, JetBrains, web) |
| Web search | 14 providers with site-aware extraction | Limited or no web search |
| Extensibility | TypeScript extensions, MCP servers, skills, hooks | Plugin marketplaces (Cursor), limited extension model |
| Use case | Terminal workflows, CI, custom harness, multi-provider, subagent fan-out | Interactive IDE workflows, fast prototyping, single-provider simplicity |
Bottom line: Use Claude Code/Cursor for interactive IDE workflows with strong UX. Use omp when you need terminal workflows, edit accuracy, LSP/DAP integration, custom provider routing, or subagent orchestration.
Monorepo structure
omp is a TypeScript + Rust monorepo. Key packages:
| Package | Description |
|---|---|
| @oh-my-pi/pi-ai | Multi-provider LLM client with streaming and model/provider integration |
| @oh-my-pi/pi-agent-core | Agent runtime with tool calling and state management |
| @oh-my-pi/pi-coding-agent | Interactive coding agent CLI and SDK |
| @oh-my-pi/pi-tui | Terminal UI library with differential rendering |
| @oh-my-pi/pi-natives | N-API bindings for grep, shell, image, text, syntax highlighting |
| @oh-my-pi/pi-utils | Shared utilities (logging, streams, dirs/env/process helpers) |
| @oh-my-pi/omp-stats | Local observability dashboard for AI usage statistics |
Rust crates:
- pi-natives — aggregates shell, AST, grep, etc.
- pi-shell — embedded bash (brush-shell fork) + PTY
- pi-ast — tree-sitter + ast-grep
- pi-iso — workspace isolation (APFS/btrfs/zfs/overlayfs/projfs)
Full source: github.com/can1357/oh-my-pi
Extensibility: config, hooks, extensions
omp inherits config from eight formats on disk:
- Cursor
.cursorrules - Cline
.clinerules - Codex
AGENTS.md - GitHub Copilot
applyTo - Claude Code
CLAUDE.md - And more
No migration script. The config your team wrote last quarter works tonight.
Extensions: TypeScript modules loaded from ~/.omp/extensions or project-local .omp/extensions. Same tool API, same slash-command registry, same hotkey table the built-ins use.
Example: Ask omp to write the piece you're missing, then /reload-plugins.
Benchmarks and evidence
| Model | Metric | What changed |
|---|---|---|
| Grok Code Fast 1 | 6.7% → 68.3% | Tenfold lift when hashline format stops eating the model alive |
| Gemini 3 Flash | +5 pp | Over str_replace—beats Google's own best attempt at the format |
| Grok 4 Fast | −61% tokens | Output collapses once the retry loop on bad diffs disappears |
| MiniMax | 2.1× pass rate | Pass rate more than doubles—same weights, same prompt |
read tool: summarized snippets, ideal defaults, selector hit rate search tool: fastest in the west (in-process ripgrep) lsp tool: everything your IDE knows, the agent knows prompts: adjusted relentlessly for each model
Full post: omp.sh blog
Related on ExplainX
- Agent harness engineering: when the model stays fixed and the scaffolding wins — harness-only lifts on Terminal-Bench 2.0
- What are agent skills? Complete guide — portable instruction packs
- MCP explained — tool protocol for agents
- Karpathy-inspired Claude Code guidelines — Think Before Coding, Simplicity First, Surgical Changes
- Terminal-Bench 2.0: AI agent benchmark — evaluation framework
Sources
- oh-my-pi repository: github.com/can1357/oh-my-pi
- Official site: omp.sh
- Documentation: omp.sh/docs
- Pi (upstream fork source): github.com/badlogic/pi-mono by Mario Zechner
- Agent Client Protocol (ACP): acp.sh
- Discord community: discord.gg/oh-my-pi (check repo for live invite)
Repository stats, model support, and CLI features change frequently. Treat this as May 21, 2026 context—verify installation commands and provider lists before production deployment. oh-my-pi is MIT-licensed; contributions welcome.