`** — merge-conflict regions captured by a prior read
+
+Resolution is process-global so parents and subagents see each other's outputs without explicit wiring.
+
+### + Recipe Tool (Project Task Runner)
+
+Run project tasks through one tool that auto-detects every common runner in the working directory:
+
+- **Auto-detection**: `package.json` scripts (including workspace packages), `Cargo.toml` bin/example/test targets, `Justfile`, `Makefile`, `Taskfile.yml`
+- **Single `op` argument**: `op: "test"` or `op: "build --release"`; monorepo namespacing uses `/` (`pkg-a/test`, `crate/bin/server`)
+- **Runner-qualified syntax**: `runnerId:task` disambiguates identical task names across multiple runners
+- **Auto-availability**: Requesting `bash` automatically pulls in `recipe` when a supported manifest is detected; `bash` stays independently available
+- **Unified output**: Same shape as `bash` — exit code, stdout/stderr merged, artifact spillover for long output
+
### + Model Roles
@@ -171,6 +276,8 @@ Configure different models for different purposes with automatic discovery:
- **Role-based routing**: `default`, `smol`, `slow`, `plan`, and `commit` roles
- **Configurable discovery**: Role defaults are auto-resolved and can be overridden per role
- **Role-based selection**: Task tool agents can use `model: pi/smol` for cost-effective exploration
+- **Generic OpenAI-compat discovery**: Any provider exposing `/v1/models` (llama.cpp, Ollama, LM Studio, vLLM, OpenRouter forks) is auto-enumerated; keyless-by-design providers are treated as authenticated
+- **Explicit prefixes are honored**: `/` no longer silently falls back to a different provider when the exact pair isn't in the bundled catalog
- CLI args (`--smol`, `--slow`, `--plan`) and env vars (`PI_SMOL_MODEL`, `PI_SLOW_MODEL`, `PI_PLAN_MODEL`)
- Configure roles interactively via `/model` selector and persist assignments to settings
@@ -178,13 +285,15 @@ Configure different models for different purposes with automatic discovery:
Structured task management with phased progress tracking:
-- **Phased task lists**: Organize work into named phases with ordered tasks
-- **5 operations**: `replace` (setup), `add_phase`, `add_task`, `update` (status changes), `remove_task`
+- **Phased task lists**: Organize work into named phases with ordered tasks; the renderer numbers phases visually (Ⅰ. Ⅱ. Ⅲ. …)
+- **Content-addressed identity**: Tasks are identified by their `content` text and phases by their `name` — no synthetic IDs
+- **5 operations**: `init` (setup), `add_phase`, `add_task`, `update` (status changes), `remove_task`, plus `note` for follow-up text
- **4 task states**: `pending`, `in_progress`, `completed`, `abandoned`
- **Auto-normalization**: Ensures exactly one task is `in_progress` at all times
- **Persistent panel**: Todo list displays above the editor with real-time progress
+- **`/todo` slash command**: `edit`, `copy`, `start`, `done`, `drop`, `rm`, `append`, `replace`, `export`, `import` operations with fuzzy phase/content matching
+- **Markdown export/import**: `/todo export [path]` and `/todo import [path]` round-trip through `TODO.md`
- **Completion reminders**: Agent warned when stopping with incomplete todos (`todo.reminders` setting)
-- **Toggle visibility**: `Ctrl+T` expands/collapses the todo panel
### + Ask Tool (Interactive Questioning)
@@ -197,6 +306,7 @@ Structured user interaction with typed options:
- **Multiple choice questions**: Present options with descriptions for user selection
- **Multi-select support**: Allow multiple answers when choices aren't mutually exclusive
- **Multi-part questions**: Ask multiple related questions in sequence via `questions` array parameter
+- **No default timeout**: `ask.timeout` defaults to `0` (wait indefinitely); set to a non-zero seconds value to auto-select the recommended option
### + Custom TypeScript Slash Commands
@@ -239,6 +349,7 @@ Full Model Context Protocol support with external tool integration:
- **OAuth support**: Explicit `clientId` and `callbackPort` in MCP server config, manual OAuth callbacks via slash commands
- **Browser server filtering**: Automatically filters browser-type MCP servers to prevent conflicts with built-in browser tool
- **Automatic Exa filtering**: Extracts Exa API keys and prefers the native Exa integration
+- **Stable tool ordering**: Reconnects no longer reshuffle the tools array, preserving Anthropic prompt caching across MCP transport flaps
- **Config schema + setup guide**: [`docs/mcp-config.md`](./docs/mcp-config.md) and [`packages/coding-agent/src/config/mcp-schema.json`](./packages/coding-agent/src/config/mcp-schema.json)
- Plugin CLI (`omp plugin install/enable/configure/doctor`)
- Hot-loadable plugins from `~/.omp/plugins/` with npm/bun integration
@@ -264,23 +375,26 @@ Remote command execution with persistent connections:
- **Project discovery**: Reads SSH hosts from `ssh.json` / `.ssh.json` in your project
- **Host management**: Add, remove, and list hosts via `omp ssh` CLI or `/ssh` slash command
-- **Persistent connections**: Reuses SSH connections across commands for faster execution
+- **Persistent connections**: Reuses SSH connections across commands for faster execution; OpenSSH `%C` ControlMaster sockets so different user/port/jump-host combos don't share a master
- **OS/shell detection**: Automatically detects remote OS and shell type
- **SSHFS mounts**: Optional automatic mounting of remote directories
-- **Compat mode**: Windows host support with automatic shell probing
+- **Compat mode**: Windows host support with automatic shell probing; native Windows callers skip multiplexing (Win32-OpenSSH does not support it)
### + Browser Tool (Puppeteer with Stealth)
Headless browser automation with 14 stealth scripts to evade bot detection:
-- **Automation actions**: Navigate, click, type, fill, scroll, drag, screenshot, evaluate JS, and extract readable content
-- **Accessibility snapshots**: Observe interactive elements via the accessibility tree with numeric IDs for reliable targeting
-- **14 stealth plugins**: Custom scripts covering toString tampering, WebGL fingerprinting, audio context, screen dimensions, font enumeration, plugin/mime-type mocking, hardware concurrency, codec availability, iframe detection, locale spoofing, worker detection, and more
-- **User agent spoofing**: Removes `HeadlessChrome` identifier, generates proper Client Hints brand lists, applies overrides via CDP Network and Emulation domains
+- **`open` / `run` / `close` flow**: Named tabs survive across `run` calls and across subagents; `run` executes async JavaScript with `page`, `browser`, `tab`, `display`, `assert`, `wait` in scope
+- **Shared runtime with `eval`**: Tab JS exposes the same helper globals (`read`, `write`, `display`, `tool.`) and supports top-level `await` plus static ESM imports rewritten against the session cwd
+- **Tab helpers**: `tab.observe()` accessibility snapshot with stable element ids, `tab.id(n)`, `tab.click`, `tab.fill`, `tab.type`, `tab.select`, `tab.uploadFile`, `tab.drag`, `tab.scrollIntoView`, `tab.waitForUrl`, `tab.waitForResponse`, `tab.evaluate`, `tab.screenshot`, `tab.extract`
+- **Drive Electron desktop apps**: Same tool, same selectors — point it at any CDP-enabled Electron binary and the agent can click buttons, fill forms, run JS in the renderer, screenshot, and observe the accessibility tree. `app.path: "/Applications/Cursor.app/Contents/MacOS/Cursor"` spawns (or reuses) the app with `--remote-debugging-port`; `app.cdp_url: "http://127.0.0.1:9222"` attaches to an already-running instance; `app.target: "Settings"` substring-matches a `BrowserWindow` title/URL when the app exposes several. Used in practice to debug VS Code, Cursor, Slack, Discord, Spotify, and any Electron / NW.js / CEF wrapper that exposes CDP
+- **14 stealth plugins**: toString tampering, WebGL fingerprinting, audio context, screen dimensions, font enumeration, plugin/mime-type mocking, hardware concurrency, codec availability, iframe detection, locale spoofing, worker detection, and more
+- **User agent spoofing**: Removes `HeadlessChrome`, generates proper Client Hints brand lists, applies overrides via CDP Network and Emulation domains
- **Selector flexibility**: CSS, `aria/`, `text/`, `xpath/`, `pierce/` query handlers for Shadow DOM piercing
-- **Reader mode**: `extract_readable` action uses Mozilla Readability for clean article extraction
+- **Reader mode**: `tab.extract()` uses Mozilla Readability for clean article extraction
- **Headless/visible toggle**: Switch modes at runtime via `/browser` command or `browser.headless` setting
-- **NixOS support**: Automatically detects NixOS (`/etc/NIXOS`) and resolves a system Chromium (`chromium` on PATH, `~/.nix-profile/bin/chromium`, or `/run/current-system/sw/bin/chromium`) since Puppeteer's bundled binary cannot run on a non-FHS system
+- **One-command Chromium fetch**: `omp setup browser` downloads a known-good Chromium; prebuilt binaries embed the tab worker entry via `with { type: "file" }` so single-file binaries no longer fail with `Timed out initializing browser tab worker`
+- **NixOS support**: Automatically detects NixOS (`/etc/NIXOS`) and resolves a system Chromium since Puppeteer's bundled binary cannot run on a non-FHS system
### + Cursor Provider
@@ -299,6 +413,7 @@ Distribute load across multiple API keys:
- **Usage-aware selection**: For OpenAI Codex, checks account limits before credential selection
- **Automatic fallback**: Switches credentials mid-session when rate limits are hit
- **Consistent hashing**: FNV-1a hashing ensures stable credential assignment per session
+- **Disable events**: Extensions can subscribe to `credential_disabled` to react when an OAuth token is soft-disabled (e.g. `invalid_grant`) without regex-matching error messages
### + Image Generation
@@ -318,18 +433,32 @@ Modern terminal interface with smart session management:
- **Powerline footer**: Model, cwd, git branch/status, token usage, context %
- **LSP status**: Shows which language servers are active and ready
- **Hotkeys**: `?` displays shortcuts when editor empty
-- **Persistent prompt history**: SQLite-backed with `Ctrl+R` search across sessions
+- **Persistent prompt history**: SQLite-backed with `Ctrl+R` search across sessions; substring fallback for FTS5-missed infix queries
- **Grouped tool display**: Consecutive Read calls shown in compact tree view
- **Streaming text preview**: Real-time delta updates during agent output
+- **`/context` panel**: Estimated context-usage breakdown for the active session
- **Overlay UI**: Custom hooks can display components as bottom-centered overlays
- **Configurable tab width**: `display.tabWidth` setting with `.editorconfig` integration
+- **Ctrl+D draft persistence**: Pressing Ctrl+D with editor text saves it as a per-session draft; resuming the session restores it
- **Scrollback preservation**: Uses home+erase-below instead of clear-screen
- **Emergency terminal restore**: Crash handlers prevent terminal corruption
+- **Power assertions**: macOS `power.preventIdleSleep` / `preventSystemSleep` / `declareUserActive` / `preventDisplaySleep` settings keep the machine awake only while a prompt is in flight
-### + Hashline Edits
+### + Hashline Edits (v3)
Hashline gives every line a short content-hash anchor. The model references anchors instead of reproducing text — no whitespace reproduction, no "string not found", no ambiguous matches. If the file changed since the last read, hashes won't match and the edit is rejected before anything gets corrupted.
+Hashline v3 adds:
+
+- **Atom mode**: Compact patch language with `+`/`-`/`=`/`<` ops, range-delete (`-LidA..LidB`), range-replace (`LidA..LidB=TEXT`), and continuation lines (`\TEXT` / `\`) for multi-line replacements
+- **`splice_block`**: Bracketed `(anchor)`, `[anchor]`, `[anchor`, `anchor]` locators target whole nodes or block bodies with auto-inferred delimiters (`{` for C-family, `(` for Lisp-family)
+- **Structural ordinals**: Anchor a single repeated symbol on a line via ordinal disambiguation
+- **Multiline sed**: `sed` as an object (`{pat, rep, g?, i?}`) with sequential chaining when multiple `sed` ops target the same anchor; global by default
+- **Stale-anchor recovery**: When anchors no longer match, edits replay against a session-scoped read/search snapshot and 3-way-merge onto the current file; success output flags when recovery was used
+- **Brace-shape heuristics**: Auto-absorb of duplicated structural-closing lines (`}`, `);`, `]`) when keeping them would unbalance brackets; warnings when `@Lid` lands on an opener at sibling indent (likely off-by-one foot-gun)
+- **Inline syntax**: `< ANCHOR>TEXT` and `+ ANCHOR>TEXT` (separator configurable via `PI_HL_SEP`, default `>`) for one-line prepends/appends without a payload block
+- **`\*** Abort` recovery marker\*\*: Stream corruption mid-patch aborts safely instead of applying partial edits
+
Benchmarked across 16 models, 180 tasks, 3 runs each:
- **Grok Code Fast 1**: 6.7% → 68.3% — a _tenfold_ improvement hidden behind mechanical patch failures
@@ -340,43 +469,60 @@ Benchmarked across 16 models, 180 tasks, 3 runs each:
### + Native Engine (Rust N-API)
-~7,500 lines of Rust compiled to a platform-tagged N-API addon, providing performance-critical operations without shelling out to external commands:
+~27,000 lines of Rust across three crates (`pi-natives`, `pi-shell`, `pi-ast`) compiled to a platform-tagged N-API addon, providing performance-critical operations without shelling out to external commands:
-| Module | Lines | What it does | Powered by |
-| ------------- | -----: | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
-| **grep** | ~1,300 | Regex search over files and in-memory content, parallel/sequential modes, glob/type filtering, context lines, fuzzy find for autocomplete | `grep-regex`, `grep-searcher`, `grep-matcher` (ripgrep internals) |
-| **shell** | ~1,025 | Embedded bash execution with persistent sessions, streaming output, timeout/abort, custom builtins | [brush-shell](https://github.com/reubeno/brush) (vendored) |
-| **text** | ~1,280 | ANSI-aware visible width, truncation with ellipsis, column slicing, text wrapping that preserves SGR codes across line breaks — all UTF-16 optimized | `unicode-width`, `unicode-segmentation` |
-| **keys** | ~1,300 | Kitty keyboard protocol parser with legacy xterm/VT100 fallback, modifier support, PHF perfect-hash lookup | `phf` |
-| **highlight** | ~475 | Syntax highlighting with 11 semantic color categories, 30+ language aliases | `syntect` |
-| **glob** | ~340 | Filesystem discovery with glob patterns, type filtering, mtime sorting, `.gitignore` respect | `ignore`, `globset` (ripgrep internals) |
-| **task** | ~350 | Blocking work scheduler on libuv thread pool, cooperative/external cancellation, timeout, profiling hooks | `tokio`, `napi` |
-| **ps** | ~290 | Cross-platform process tree kill and descendant listing — `/proc` on Linux, `libproc` on macOS, `CreateToolhelp32Snapshot` on Windows | `libc` |
-| **prof** | ~250 | Always-on circular buffer profiler with folded-stack output and optional SVG flamegraph generation | `inferno` |
-| **image** | ~150 | Decode/encode PNG/JPEG/WebP/GIF, resize with 5 sampling filters | `image` |
-| **clipboard** | ~95 | Text copy and image read from system clipboard — no `xclip`/`pbcopy` needed | `arboard` |
-| **html** | ~50 | HTML-to-Markdown conversion with optional content cleaning | `html-to-markdown-rs` |
+| Module | Lines | What it does | Powered by |
+| -------------- | -----: | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
+| **grep** | ~1,900 | Regex search over files and in-memory content, parallel/sequential modes, glob/type filtering, context lines, fuzzy find for autocomplete | `grep-regex`, `grep-searcher`, `grep-matcher` (ripgrep internals) |
+| **shell** | ~3,700 | Embedded bash execution with persistent sessions, streaming output, timeout/abort, custom builtins, command minimizer (`pi-shell` crate) | [brush-shell](https://github.com/reubeno/brush) (vendored) |
+| **text** | ~1,450 | ANSI-aware visible width, truncation with ellipsis, column slicing, text wrapping that preserves SGR codes across line breaks — all UTF-16 optimized | `unicode-width`, `unicode-segmentation` |
+| **keys** | ~1,490 | Kitty keyboard protocol parser with legacy xterm/VT100 fallback, modifier support, PHF perfect-hash lookup | `phf` |
+| **summarize** | ~1,040 | Tree-sitter structural source summaries with configurable body / comment elision; backs `read`'s default code summary output (`pi-ast` crate) | `tree-sitter`, `ast-grep-core` |
+| **ast** | ~1,000 | ast-grep pattern matching and structural rewrites driving the `ast_edit` / `ast_grep` tools | `ast-grep-core` |
+| **fs_cache** | ~840 | Mtime-keyed file cache shared by read/grep/lsp so repeated reads of the same file are zero-IO | — |
+| **highlight** | ~470 | Syntax highlighting with 11 semantic color categories, 30+ language aliases | `syntect` |
+| **pty** | ~455 | Native PTY allocation for `bash` `pty: true` (sudo, ssh interactive prompts) | `portable-pty` |
+| **workspace** | ~385 | Workspace tree walker with gitignore + AGENTS.md discovery in one pass | `ignore`, `git2` |
+| **glob** | ~410 | Filesystem discovery with glob patterns, type filtering, mtime sorting, `.gitignore` respect | `ignore`, `globset` (ripgrep internals) |
+| **appearance** | ~270 | Mode 2031 detection + native macOS dark/light appearance via CoreFoundation FFI | `core-foundation` |
+| **power** | ~270 | macOS power-assertion API for idle/system/display-sleep prevention during in-flight prompts | `IOKit` FFI |
+| **task** | ~260 | Blocking work scheduler on libuv thread pool, cooperative/external cancellation, timeout, profiling hooks | `tokio`, `napi` |
+| **iso** | ~245 | ISO 8601 / RFC 3339 datetime parsing and formatting | `time` |
+| **prof** | ~240 | Always-on circular buffer profiler with folded-stack output and optional SVG flamegraph generation | `inferno` |
+| **fd** | ~250 | Filesystem walker for `find`-tool replacement | `ignore` |
+| **ps** | ~195 | Cross-platform process tree kill and descendant listing — `/proc` on Linux, `libproc` on macOS, `CreateToolhelp32Snapshot` on Windows | `libc` |
+| **image** | ~190 | Decode/encode PNG/JPEG/WebP/GIF, resize with 5 sampling filters | `image` |
+| **clipboard** | ~80 | Text copy and image read from system clipboard — no `xclip`/`pbcopy` needed | `arboard` |
+| **tokens** | ~65 | O200k / Cl100k BPE token counting for context budgets; both tables embedded | `tiktoken-rs` |
+| **html** | ~50 | HTML-to-Markdown conversion with optional content cleaning | `html-to-markdown-rs` |
Supported platforms: `linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`, `win32-x64`.
### ... and many more
+- **`omp acp` subcommand**: Run as an Agent Client Protocol server over stdio
- **`omp config` subcommand**: Manage settings from CLI (`list`, `get`, `set`, `reset`, `path`)
-- **`omp setup` subcommand**: Install optional dependencies (e.g., `omp setup python` for Jupyter kernel)
-- **`omp stats` subcommand**: Local observability dashboard for AI usage (requests, cost, cache rate, tokens/s)
+- **`omp setup` subcommand**: Install optional dependencies (`omp setup python`, `omp setup browser`)
+- **`omp stats` subcommand**: Local observability dashboard for AI usage (requests, cost, cache rate, tokens/s) with input/output token totals
+- **`omp jupyter` was removed**: the Python `eval` backend now runs as a subprocess (no Jupyter dependency)
- **`xhigh` thinking level**: Extended reasoning for Anthropic models with increased token budgets
+- **Hide-thinking toggle**: `Ctrl+T` instructs the provider to omit reasoning summaries entirely, not just hide them client-side
- **Background mode**: `/background` detaches UI and continues agent execution
- **Completion notifications**: Configurable bell/OSC99/OSC9 when agent finishes
- **65+ built-in themes**: Catppuccin, Dracula, Nord, Gruvbox, Tokyo Night, Poimandres, and material variants
- **Automatic dark/light switching**: Mode 2031 terminal detection, native macOS appearance via CoreFoundation FFI, COLORFGBG fallback
- **Auto environment detection**: OS, distro, kernel, CPU, GPU, shell, terminal, DE in system prompt
- **Git context**: System prompt includes branch, status, recent commits
+- **Workspace tree in system prompt**: Recency-sorted depth-≤3 tree of recent files / directories with truncation notices
+- **AGENTS.md context discovery**: gitignore-aware walk that surfaces directory-scoped AGENTS.md and forwards results to subagents (no redundant rescans on spawn)
- **Bun runtime**: Native TypeScript execution, faster startup, all packages migrated
- **Centralized file logging**: Debug logs with daily rotation to `~/.omp/logs/`
-- **Bash interceptor**: Optionally block shell commands that have dedicated tools
-- **Per-command PTY control**: Bash tool supports `pty: true` for commands requiring a real terminal (sudo, ssh)
+- **Bash interceptor**: Optionally block shell commands that have dedicated tools — checks the original command before `cd …&&` normalization
+- **Per-command PTY control**: `bash` tool supports `pty: true` for commands requiring a real terminal (sudo, ssh)
- **@file auto-read**: Type `@path/to/file` in prompts to inject file contents inline
- **AST tools**: `ast_grep` and `ast_edit` for syntax-aware code search and codemods via ast-grep
+- **Plan mode**: ExitPlanMode offers three approvals — execute (purge), keep full transcript, or compact context (re-anchors plan on a fresh cache breakpoint)
+- **`/btw` ephemeral turns**: One-shot model query that doesn't pollute the session transcript
- **Sampling controls**: `topP`, `topK`, `minP`, `presencePenalty`, `repetitionPenalty` settings for fine-grained model tuning
---
@@ -422,7 +568,7 @@ Examples:
curl -fsSL https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.sh | sh -s -- --source
# Install release tag via binary
-curl -fsSL https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.sh | sh -s -- --binary --ref v3.20.1
+curl -fsSL https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.sh | sh -s -- --binary --ref v15.0.0
# Install branch/commit via source
curl -fsSL https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.sh | sh -s -- --source --ref main
@@ -430,7 +576,7 @@ curl -fsSL https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/insta
```powershell
# Install release tag via binary
-& ([scriptblock]::Create((irm https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.ps1))) -Binary -Ref v3.20.1
+& ([scriptblock]::Create((irm https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.ps1))) -Binary -Ref v15.0.0
# Install branch/commit via source
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/can1357/oh-my-pi/main/scripts/install.ps1))) -Source -Ref main
```
@@ -485,12 +631,14 @@ return config
| Mistral | `MISTRAL_API_KEY` |
| Groq | `GROQ_API_KEY` |
| Cerebras | `CEREBRAS_API_KEY` |
+| Fireworks (`fireworks`) | `FIREWORKS_API_KEY` |
| Hugging Face (`huggingface`) | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` |
| Synthetic | `SYNTHETIC_API_KEY` |
| NVIDIA (`nvidia`) | `NVIDIA_API_KEY` |
| NanoGPT (`nanogpt`) | `NANO_GPT_API_KEY` |
| Together (`together`) | `TOGETHER_API_KEY` |
| Ollama (`ollama`) | `OLLAMA_API_KEY` _(optional)_ |
+| Ollama Cloud (`ollama-cloud`) | `OLLAMA_CLOUD_API_KEY` |
| LiteLLM (`litellm`) | `LITELLM_API_KEY` |
| LM Studio (`lm-studio`) | `LM_STUDIO_API_KEY` _(optional)_ |
| llama.cpp (`llama.cpp`) | `LLAMA_CPP_API_KEY` _(optional)_ |
@@ -498,12 +646,23 @@ return config
| Moonshot (`moonshot`) | `MOONSHOT_API_KEY` |
| Venice (`venice`) | `VENICE_API_KEY` |
| Kilo Gateway (`kilo`) | `KILO_API_KEY` |
-| GitLab Duo (`gitlab-duo`) | _OAuth only_ |
+| GitLab Duo (`gitlab-duo`) | `GITLAB_TOKEN` _(or OAuth)_ |
+| Cursor (`cursor`) | _OAuth only_ |
+| Antigravity (`google-antigravity`) | _OAuth only_ |
| Jina (`jina`, web search) | `JINA_API_KEY` |
+| Kagi (`kagi`, web search) | `KAGI_API_KEY` |
+| Tavily (`tavily`, web search) | `TAVILY_API_KEY` |
+| Parallel (`parallel`, web search) | `PARALLEL_API_KEY` |
| Perplexity | `PERPLEXITY_API_KEY` or `PERPLEXITY_COOKIES` |
| xAI | `XAI_API_KEY` |
| OpenRouter | `OPENROUTER_API_KEY` |
+| OpenCode Go (`opencode-go`) | `OPENCODE_API_KEY` |
+| OpenCode Zen (`opencode-zen`) | `OPENCODE_API_KEY` |
| Z.AI | `ZAI_API_KEY` |
+| ZenMux (`zenmux`) | `ZENMUX_API_KEY` |
+| MiniMax Coding Plan (`minimax-code`) | `MINIMAX_CODE_API_KEY` |
+| MiniMax Coding Plan CN (`minimax-code-cn`) | `MINIMAX_CODE_CN_API_KEY` |
+| Alibaba Coding Plan (`alibaba-coding-plan`) | `ALIBABA_CODING_PLAN_API_KEY` |
| Qwen Portal (`qwen-portal`) | `QWEN_OAUTH_TOKEN` or `QWEN_PORTAL_API_KEY` |
| vLLM (`vllm`) | `VLLM_API_KEY` |
| Cloudflare AI Gateway (`cloudflare-ai-gateway`) | `CLOUDFLARE_AI_GATEWAY_API_KEY` |
@@ -514,47 +673,57 @@ See [Environment Variables](docs/environment-variables.md) for the full list.
**Option 2: `/login` (interactive auth / API key setup)**
-Use `/login` with supported providers:
+Use `/login` with supported providers (alphabetical):
+- Alibaba Coding Plan (`alibaba-coding-plan`)
- Anthropic (Claude Pro/Max)
-- ChatGPT Plus/Pro (Codex)
-- GitHub Copilot
-- Google Cloud Code Assist (Gemini CLI)
-- Antigravity (Gemini 3, Claude, GPT-OSS)
-- Cursor
-- Kimi Code
-- Perplexity
-- NVIDIA (`nvidia`)
-- NanoGPT (`nanogpt`)
-- Hugging Face Inference (`huggingface`)
-- OpenCode Zen
-- Kilo Gateway (`kilo`)
+- Antigravity (`google-antigravity`, Gemini 3 / Claude / GPT-OSS)
+- Cerebras (`cerebras`)
+- ChatGPT Plus/Pro (Codex, `openai-codex`)
+- Cloudflare AI Gateway (`cloudflare-ai-gateway`)
+- Cursor (`cursor`)
+- Fireworks (`fireworks`)
+- GitHub Copilot (`github-copilot`)
- GitLab Duo (`gitlab-duo`)
-- Qianfan (`qianfan`)
-- Ollama (local / self-hosted, `ollama`)
+- Google Cloud Code Assist (Gemini CLI, `google-gemini-cli`)
+- Hugging Face Inference (`huggingface`)
+- Kagi (`kagi`)
+- Kilo Gateway (`kilo`)
+- Kimi Code (`kimi-code`)
+- LiteLLM (`litellm`)
- LM Studio (local / self-hosted, `lm-studio`)
- llama.cpp (local / self-hosted, `llama.cpp`)
-- vLLM (local OpenAI-compatible, `vllm`)
-- Z.AI (GLM Coding Plan)
-- Synthetic
-- Together (`together`)
-- LiteLLM (`litellm`)
-- Xiaomi MiMo (`xiaomi`)
+- MiniMax Coding Plan (International, `minimax-code`)
+- MiniMax Coding Plan (China, `minimax-code-cn`)
- Moonshot (Kimi API, `moonshot`)
-- Venice (`venice`)
-- MiniMax Coding Plan (International / China)
+- NanoGPT (`nanogpt`)
+- NVIDIA (`nvidia`)
+- Ollama (local / self-hosted, `ollama`)
+- Ollama Cloud (`ollama-cloud`)
+- OpenCode Go (`opencode-go`)
+- OpenCode Zen (`opencode-zen`)
+- Parallel (`parallel`, web search)
+- Perplexity
+- Qianfan (`qianfan`)
- Qwen Portal (`qwen-portal`)
-- Cloudflare AI Gateway (`cloudflare-ai-gateway`)
+- Synthetic
+- Tavily (`tavily`, web search)
+- Together (`together`)
+- Venice (`venice`)
- Vercel AI Gateway (`vercel-ai-gateway`)
+- vLLM (local OpenAI-compatible, `vllm`)
+- Xiaomi MiMo (`xiaomi`)
+- Z.AI (GLM Coding Plan)
+- ZenMux (`zenmux`)
-For `ollama`, API key is optional. Leave it unset for local no-auth instances, or set `OLLAMA_API_KEY` for authenticated hosts.
-For `llama.cpp`, API key is optional. Leave it unset for local no-auth instances, or set `LLAMA_CPP_API_KEY` for authenticated hosts.
-For `lm-studio`, API key is optional. Leave it unset for local no-auth instances, or set `LM_STUDIO_API_KEY` for authenticated hosts.
-For `vllm`, paste your key in `/login` (or use `VLLM_API_KEY`). For local no-auth servers, any placeholder value works (for example `vllm-local`).
-For `nanogpt`, `/login nanogpt` opens `https://nano-gpt.com/api` and prompts for your `sk-...` key (or set `NANO_GPT_API_KEY`). Login validates the key via NanoGPT's models endpoint (not a fixed model entitlement).
-For `cloudflare-ai-gateway`, set provider base URL to
-`https://gateway.ai.cloudflare.com/v1///anthropic`
-(for example in `~/.omp/agent/models.yml`).
+**Provider-specific login notes:**
+
+- **`ollama`** — API key optional. Leave unset for local no-auth instances; set `OLLAMA_API_KEY` for authenticated hosts.
+- **`llama.cpp`** — API key optional. Leave unset for local no-auth instances; set `LLAMA_CPP_API_KEY` for authenticated hosts.
+- **`lm-studio`** — API key optional. Leave unset for local no-auth instances; set `LM_STUDIO_API_KEY` for authenticated hosts.
+- **`vllm`** — paste your key in `/login` (or use `VLLM_API_KEY`). For local no-auth servers, any placeholder value works (for example `vllm-local`).
+- **`nanogpt`** — `/login nanogpt` opens `https://nano-gpt.com/api` and prompts for your `sk-...` key (or set `NANO_GPT_API_KEY`). Validates the key via NanoGPT's models endpoint, not a fixed model entitlement.
+- **`cloudflare-ai-gateway`** — set the provider base URL to `https://gateway.ai.cloudflare.com/v1///anthropic` (for example in `~/.omp/agent/models.yml`).
```bash
omp
@@ -610,6 +779,19 @@ Run `/extensions` and:
- Inspect each item source (`via ` + file path)
- Disable full providers or specific items you don't want (`Space`)
+#### 5) Manage subagents via `/agents`
+
+Open the Agent Control Center to inspect, configure, and toggle subagents (the `task` tool's dispatch targets).
+
+Run `/agents` and:
+
+- Browse discovered agents (built-in, project, user, and marketplace-installed)
+- Inspect each agent's source file, model, tools, and system prompt
+- Enable/disable agents per project, or scope-toggle to user/project
+- Open the underlying agent definition for editing
+
+---
+
---
## Usage
@@ -617,37 +799,54 @@ Run `/extensions` and:
### Slash Commands
These are **in-chat slash commands** (not CLI subcommands).
-| Command | Description |
-| ------- | ----------- |
-| `/settings` | Open settings menu |
-| `/plan` | Toggle plan mode |
-| `/model` (`/models`) | Open model selector |
-| `/export [path]` | Export session to HTML |
-| `/dump` | Copy session transcript to clipboard |
-| `/share` | Upload session as a secret gist |
-| `/session` | Show session info and usage |
-| `/usage` | Show provider usage and limits |
-| `/hotkeys` | Show keyboard shortcuts |
-| `/extensions` (`/status`) | Open Extension Control Center |
-| `/changelog` | Show changelog entries |
-| `/tree` | Navigate session tree |
-| `/branch` | Open branch selector (tree or message selector, based on settings) |
-| `/fork` | Fork from a previous message |
-| `/resume` | Open session picker |
-| `/new` | Start a new session |
-| `/compact [focus]` | Compact context manually |
-| `/handoff [focus]` | Hand off context to a new session |
-| `/browser [headless\|visible]` | Toggle browser mode |
-| `/mcp ...` | Manage MCP servers |
-| `/memory ...` | Inspect/clear/rebuild memory state |
-| `/move ` | Move current session to a different cwd |
-| `/background` (`/bg`) | Detach UI and continue in background |
-| `/debug` | Open debug tools |
-| `/copy` | Copy last agent message |
-| `/login` / `/logout` | OAuth login/logout |
-| `/exit` (`/quit`) | Exit interactive mode |
-Bundled custom slash commands include `/review` (interactive code review launcher).
+| Command | Description |
+| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `/settings` | Open settings menu |
+| `/plan [prompt]` | Toggle plan mode |
+| `/model` (`/models`) | Open model selector |
+| `/fast [on\|off\|status]` | Toggle OpenAI service-tier fast mode |
+| `/loop [count\|duration]` | Toggle loop mode (re-submits next prompt after each yield) |
+| `/export [path]` | Export session to HTML |
+| `/dump` | Copy session transcript to clipboard |
+| `/share` | Upload session as a secret GitHub gist |
+| `/copy [last\|code\|all\|cmd]` | Copy last agent message / code block(s) / last bash or python command |
+| `/todo ` | View/edit todo list (`edit`, `copy`, `export`, `import`, `append`, `start`, `done`, `drop`, `rm`) |
+| `/session [info\|delete]` | Show session info or delete the current session |
+| `/usage` | Show provider usage and limits |
+| `/jobs` | Show async background jobs status |
+| `/changelog [full]` | Show changelog entries |
+| `/hotkeys` | Show keyboard shortcuts |
+| `/tools` | Show tools currently visible to the agent |
+| `/context` | Show estimated context usage breakdown |
+| `/extensions` (`/status`) | Open Extension Control Center dashboard |
+| `/agents` | Open Agent Control Center dashboard |
+| `/tree` | Navigate session tree (switch branches) |
+| `/branch` | Branch from a previous message (tree or message selector) |
+| `/fork` | Fork from a previous message into a new session |
+| `/resume` | Open session picker |
+| `/new` | Start a new session |
+| `/drop` | Delete current session and start a new one |
+| `/compact [focus]` | Manually compact session context |
+| `/handoff [focus]` | Hand off context to a new session |
+| `/btw ` | Ephemeral side question using the current context |
+| `/retry` | Retry the last failed agent turn |
+| `/rename ` | Rename the current session |
+| `/move ` | Move session to a different working directory |
+| `/background` (`/bg`) | Detach UI and continue running in background |
+| `/browser [headless\|visible]` | Toggle browser headless/visible mode |
+| `/mcp ` | Manage MCP servers (`add`, `list`, `remove`, `test`, `reauth`, `unauth`, `enable`, `disable`, `smithery-search`, `smithery-login`, `smithery-logout`, `reconnect`, `reload`, `resources`, `prompts`, `notifications`) |
+| `/ssh ` | Manage SSH hosts (`add`, `list`, `remove`) |
+| `/memory ` | Inspect/clear/rebuild memory (`view`, `clear`/`reset`, `enqueue`/`rebuild`, `mm list\|show\|refresh\|history\|seed\|delete\|reload`) |
+| `/marketplace ` | Manage marketplace sources and plugins (`add`, `remove`, `update`, `list`, `discover`, `install`, `uninstall`, `installed`, `upgrade`) |
+| `/plugins [list\|enable\|disable]` | View and manage installed plugins (npm + marketplace) |
+| `/reload-plugins` | Reload skills, commands, hooks, tools, agents, and MCP |
+| `/force [prompt]` | Force the next turn to use a specific tool |
+| `/debug` | Open debug tools selector |
+| `/login` / `/logout` | OAuth login/logout |
+| `/exit` (`/quit`) | Exit interactive mode |
+
+Installed skills are dispatchable as `/skill:`. Bundled custom commands include `/review` (interactive code review launcher).
### Editor Features
@@ -657,6 +856,8 @@ Bundled custom slash commands include `/review` (interactive code review launche
**Drag & drop:** Drag files from your file manager into the terminal.
+**Paste images (Ctrl+V):** Paste images from the clipboard alongside drag-and-drop attachment.
+
**Multi-line paste:** Pasted content is collapsed in preview but sent in full.
**Message queuing:** Submit messages while the agent is working; queue behavior is configurable in `/settings`.
@@ -684,23 +885,23 @@ Bundled custom slash commands include `/review` (interactive code review launche
**Other:**
-| Key | Action |
-| --------------------- | --------------------------------------------------------- |
-| Tab | Path completion / accept autocomplete |
-| Escape | Cancel autocomplete / abort streaming |
-| Ctrl+C | Clear editor (first) / exit (second) |
-| Ctrl+D | Exit (when editor is empty) |
-| Ctrl+Z | Suspend to background (use `fg` in shell to resume) |
-| Shift+Tab | Cycle thinking level |
-| Ctrl+P / Shift+Ctrl+P | Cycle role models (slow/default/smol), temporary on shift |
-| Alt+P | Select model temporarily |
-| Ctrl+L | Open model selector |
-| Alt+Shift+P | Toggle plan mode |
-| Ctrl+R | Search prompt history |
-| Ctrl+O | Toggle tool output expansion |
-| Ctrl+T | Toggle todo list expansion |
-| Ctrl+G | Edit message in external editor (`$VISUAL` or `$EDITOR`) |
-| Alt+H | Toggle speech-to-text recording |
+| Key | Action |
+| --------------------- | ----------------------------------------------------------- |
+| Tab | Path completion / accept autocomplete |
+| Escape | Cancel autocomplete / abort streaming |
+| Ctrl+C | Clear editor (first) / exit (second) |
+| Ctrl+D | Exit (when editor is empty) |
+| Ctrl+Z | Suspend to background (use `fg` in shell to resume) |
+| Shift+Tab | Cycle thinking level |
+| Ctrl+P / Shift+Ctrl+P | Cycle role models (slow/default/smol), temporary on shift |
+| Alt+P | Select model temporarily |
+| Ctrl+L | Open model selector |
+| Alt+Shift+P | Toggle plan mode |
+| Ctrl+R | Search prompt history |
+| Ctrl+O | Toggle tool output expansion |
+| Ctrl+T | Toggle thinking mode (hide reasoning summaries server-side) |
+| Ctrl+G | Edit message in external editor (`$VISUAL` or `$EDITOR`) |
+| Alt+H | Toggle speech-to-text recording |
### Bash Mode
@@ -755,7 +956,7 @@ omp -r
omp --resume # Resume by session ID prefix
omp --resume # Resume by explicit .jsonl path
omp --session # Alias of --resume
-omp --no-session # Ephemeral mode (don't save)
+omp --no-session # Ephemeral mode (don't save)
```
Session IDs are Snowflake-style hex IDs (not UUIDs).
@@ -771,6 +972,8 @@ Long sessions can exhaust context windows. Compaction summarizes older messages
- **Overflow recovery**: model returns context overflow; compact and retry.
- **Threshold maintenance**: context exceeds configured headroom after a successful turn.
+**Plan mode:** when approving a plan, `Approve and compact context` distills the plan-mode discussion into a summary and starts execution in the same session — a middle ground between `Approve and execute` (fresh context) and `Approve and keep context` (full history preserved).
+
**Configuration** (`~/.omp/agent/config.yml`):
```yaml
@@ -793,20 +996,33 @@ See [docs/compaction.md](docs/compaction.md) for internals and hook integration.
**Create new session (`/branch` / `/fork`):** Branch to a new session file from a selected previous message.
-### Autonomous Memory
+### Memory
-When enabled, the agent extracts durable knowledge from past sessions and injects it at startup. The pipeline runs in the background and never blocks the active session.
+omp ships two memory backends, selected via `memory.backend` (`off | local | hindsight`).
-Memory is isolated per project (working directory) and stored under `~/.omp/agent/memories/`. At session start, a compact summary is injected into the system prompt. The agent can read deeper context via `memory://root/MEMORY.md` and `memory://root/skills//SKILL.md`.
+**Legacy local backend (`memory.backend: local`)**
+
+The agent extracts durable knowledge from past sessions and injects a compact summary at startup. The pipeline runs in the background and never blocks the active session. Memory is isolated per project (working directory) and stored under `~/.omp/agent/memories/`. The agent can pull deeper context via `memory://root/MEMORY.md` and `memory://root/skills//SKILL.md`.
Manage via the `/memory` slash command:
- `/memory view` — show current injection payload
-- `/memory clear` — delete all memory data and artifacts
-- `/memory enqueue` — force consolidation at next startup
+- `/memory clear` (or `/memory reset`) — delete all memory data and artifacts
+- `/memory enqueue` (or `/memory rebuild`) — force consolidation at next startup
> See [Memory Documentation](docs/memory.md).
+**Hindsight backend (`memory.backend: hindsight`)**
+
+Opt-in remote memory backed by [Hindsight](https://hindsight.vectorize.io) (Cloud or self-hosted). Instead of injecting a static summary, Hindsight surfaces three tools to the agent — `retain` (store durable facts), `recall` (search prior memories), and `reflect` (synthesise an answer across many memories) — and runs an auto-recall on the first turn so prior context lands before the model speaks.
+
+- **Per-session state**: each session aliases a bank; subagents reuse the parent's bank so retains/recalls persist to the same place.
+- **Bank scoping**: `hindsight.scoping` selects `global` (one shared bank), `per-project` (isolated per cwd), or `per-project-tagged` (shared bank with `project:` tags so global + project memories merge on recall).
+- **Mental models**: long-running curated summaries (user preferences, project conventions) are seeded once per bank and refreshed automatically after consolidations; an `` block is spliced into the system prompt.
+- **Maintenance**: `/memory mm list|show|refresh|history|seed|delete|reload` from the TUI; `/memory view|clear|enqueue` still apply.
+
+Configure via `hindsight.apiUrl`, `hindsight.apiToken`, `hindsight.bankId`, and `hindsight.scoping` in `config.yml`.
+
---
## Configuration
@@ -833,7 +1049,8 @@ Replace the default system prompt by creating `SYSTEM.md`:
1. **Project-local:** `.omp/SYSTEM.md` (takes precedence)
2. **Global:** `~/.omp/agent/SYSTEM.md` (fallback)
- `--system-prompt` overrides both files. Use `--append-system-prompt` to append additional instructions.
+
+`--system-prompt` overrides both files. Use `--append-system-prompt` to append additional instructions.
### Custom Models and Providers
@@ -881,6 +1098,8 @@ equivalence:
Canonical ids are official upstream model ids such as `claude-sonnet-4-6` or `gpt-5.3-codex`. Use `equivalence.overrides` to map custom provider variants into those canonical groups while keeping explicit `provider/model` selection available.
+**Path-scoped model config:** `modelRoles` and other model selectors can be overridden per working directory by nesting a `paths:` map under the setting — useful for pinning a heavier model on one repo without changing the global default. See [docs/models.md](docs/models.md).
+
### Settings File
Global settings are stored in:
@@ -942,6 +1161,10 @@ compaction:
enabled: true
reserveTokens: 16384
keepRecentTokens: 20000
+ autoContinue: true
+
+memory:
+ backend: local # off | local | hindsight
skills:
enabled: true
@@ -949,12 +1172,34 @@ skills:
terminal:
showImages: true
+display:
+ tabWidth: 4 # Tab rendering width (.editorconfig integration)
+
topP: -1 # Nucleus sampling (0-1, -1 = provider default)
topK: -1 # Top-K tokens (-1 = provider default)
minP: -1 # Minimum probability (0-1, -1 = provider default)
-display:
- tabWidth: 4 # Tab rendering width (.editorconfig integration)
+tools:
+ discoveryMode: all # off | mcp-only | all
+
+eval:
+ py: true
+ js: true
+
+recipe:
+ enabled: true
+
+irc:
+ enabled: true
+
+github:
+ cache:
+ enabled: true
+ softTtlSec: 300
+ hardTtlSec: 86400
+
+plan:
+ enabled: true
async:
enabled: false
@@ -963,8 +1208,12 @@ async:
task:
eager: false
isolation:
- mode: none # none | worktree | fuse-overlay | fuse-projfs
+ # auto lets the native PAL pick the best CoW backend; explicit values
+ # pin to one of: apfs | btrfs | zfs | reflink | overlayfs | projfs |
+ # block-clone | rcopy | none
+ mode: none
merge: patch # patch | branch
+ commits: generic # generic | ai
```
`modelRoles` may use either canonical ids or explicit `provider/model` selectors. `modelProviderOrder` decides which provider backs a canonical model when multiple equivalent variants are available.
@@ -974,6 +1223,10 @@ Legacy migration notes:
- `settings.json` → `config.yml`
- `queueMode` → `steeringMode`
- flat `theme: "..."` → `theme.dark` / `theme.light`
+- `memories.enabled: true|false` → `memory.backend: local|off`
+- `task.isolation.enabled` + legacy modes (`worktree`, `fuse-overlay`, `fuse-projfs`) → `task.isolation.mode` enum (`auto`, `apfs`, `btrfs`, `zfs`, `reflink`, `overlayfs`, `projfs`, `block-clone`, `rcopy`, `none`)
+
+---
---
@@ -1003,6 +1256,7 @@ Define reusable prompt commands as Markdown files:
- Global: `~/.omp/agent/commands/*.md`
- Project: `.omp/commands/*.md`
+- Also discovered: `~/.claude/commands/`, `.claude/commands/`, `~/.codex/commands/`, `.codex/commands/`
```markdown
---
@@ -1023,7 +1277,7 @@ Argument placeholders:
- `$1`, `$2`, ... positional arguments
- `$@` and `$ARGUMENTS` for all arguments joined
-TypeScript custom commands are also supported:
+TypeScript custom commands are also supported — drop an `index.ts` into a per-command folder and default-export a factory:
- `~/.omp/agent/commands//index.ts`
- `.omp/commands//index.ts`
@@ -1064,19 +1318,25 @@ Hook locations:
- Global: `~/.omp/agent/hooks/pre/*.ts`, `~/.omp/agent/hooks/post/*.ts`
- Project: `.omp/hooks/pre/*.ts`, `.omp/hooks/post/*.ts`
-- CLI: `--hook `
+- CLI: `--hook ` (treated as an alias for `--extension`)
```typescript
-import type { HookAPI } from "@oh-my-pi/pi-coding-agent/hooks";
+import type { HookAPI } from "@oh-my-pi/pi-coding-agent/extensibility/hooks";
export default function (omp: HookAPI) {
- omp.on("tool_call", async (event, ctx) => {
- if (event.toolName === "bash" && /sudo/.test(event.input.command as string)) {
- const ok = await ctx.ui.confirm("Allow sudo?", event.input.command as string);
- if (!ok) return { block: true, reason: "Blocked by user" };
- }
- return undefined;
- });
+ omp.on("tool_call", async (event, ctx) => {
+ if (
+ event.toolName === "bash" &&
+ /sudo/.test(event.input.command as string)
+ ) {
+ const ok = await ctx.ui.confirm(
+ "Allow sudo?",
+ event.input.command as string,
+ );
+ if (!ok) return { block: true, reason: "Blocked by user" };
+ }
+ return undefined;
+ });
}
```
@@ -1086,7 +1346,7 @@ Inject messages from hooks with:
omp.sendMessage(message, { triggerTurn: true });
```
-> See [Hooks Documentation](docs/hooks.md) and [examples/hooks/](packages/coding-agent/examples/hooks/).
+> See [Hooks Documentation](docs/hooks.md) and [examples/hooks/](packages/coding-agent/examples/hooks/). For richer integrations (tools + commands + events from one module) prefer `ExtensionAPI`.
### Custom Tools
@@ -1101,22 +1361,41 @@ Auto-discovered locations:
import { Type } from "@sinclair/typebox";
import type { CustomToolFactory } from "@oh-my-pi/pi-coding-agent";
const factory: CustomToolFactory = () => ({
- name: "greet",
- label: "Greeting",
- description: "Generate a greeting",
- parameters: Type.Object({
- name: Type.String({ description: "Name to greet" }),
- }),
- async execute(_toolCallId, params) {
- const { name } = params as { name: string };
- return { content: [{ type: "text", text: `Hello, ${name}!` }] };
- },
+ name: "greet",
+ label: "Greeting",
+ description: "Generate a greeting",
+ parameters: Type.Object({
+ name: Type.String({ description: "Name to greet" }),
+ }),
+ async execute(_toolCallId, params) {
+ const { name } = params as { name: string };
+ return { content: [{ type: "text", text: `Hello, ${name}!` }] };
+ },
});
export default factory;
```
> See [Custom Tools Documentation](docs/custom-tools.md) and [examples/custom-tools/](packages/coding-agent/examples/custom-tools/).
+### Marketplace
+
+omp ships a Claude-compatible plugin marketplace: discover, install, and manage plugins (skills, commands, hooks, MCP/LSP servers) from Git-hosted catalogs or local directories.
+
+A **marketplace** is a Git repo (or directory) with a `.claude-plugin/marketplace.json` catalog. A **plugin** is identified as `name@marketplace` (e.g. `code-review@claude-plugins-official`) and can be installed at **user** scope (default, `~/.omp/plugins/`) or **project** scope (`.omp/plugins/`, shadows user installs).
+
+```text
+/marketplace add anthropics/claude-plugins-official
+/marketplace discover # browse catalogs
+/marketplace install code-review@claude-plugins-official
+/marketplace list | remove | update | uninstall | upgrade | installed
+/plugins list # all installed plugins (npm + marketplace)
+/plugins enable|disable
+```
+
+Or just type `/marketplace` with no arguments to open the interactive browser. The same operations are available via `omp plugin ...` from the CLI.
+
+> See [Marketplace Documentation](docs/marketplace.md).
+
---
## CLI Reference
@@ -1141,19 +1420,21 @@ omp [args] [flags]
| `--api-key ` | API key (overrides environment/provider lookup) |
| `--system-prompt ` | Replace system prompt |
| `--append-system-prompt ` | Append to system prompt |
-| `--mode ` | Output mode: `text`, `json`, `rpc` |
+| `--mode ` | Output mode: `text`, `json`, `rpc`, `acp`, `rpc-ui` |
| `--print`, `-p` | Non-interactive: process prompt and exit |
| `--continue`, `-c` | Continue most recent session |
| `--resume`, `-r [id\|path]` | Resume by ID prefix/path (or open picker if omitted) |
| `--session ` | Alias of `--resume` |
| `--session-dir ` | Directory for session storage and lookup |
| `--no-session` | Don't save session |
+| `--fork ` | Fork from a specific message ID |
| `--tools ` | Restrict to comma-separated built-in tool names |
| `--no-tools` | Disable all built-in tools |
| `--no-lsp` | Disable LSP integration |
| `--no-pty` | Disable PTY-based interactive bash execution |
| `--extension `, `-e` | Load extension file (repeatable) |
| `--hook ` | Load hook/extension file (repeatable) |
+| `--plugin-dir ` | Load plugin from directory (repeatable) |
| `--no-extensions` | Disable extension discovery (`-e` paths still load) |
| `--no-skills` | Disable skills discovery and loading |
| `--skills ` | Comma-separated glob patterns to filter skills |
@@ -1168,17 +1449,22 @@ omp [args] [flags]
`omp` also ships dedicated subcommands:
-- `commit`
-- `config`
-- `grep`
-- `jupyter`
-- `plugin`
-- `search` (alias: `q`)
-- `setup`
-- `shell`
-- `ssh`
-- `stats`
-- `update`
+| Command | Description |
+| -------------- | ---------------------------------------------------------------- |
+| `acp` | Run as an Agent Client Protocol server (editor integration) |
+| `agents` | Manage agent definitions (e.g. `omp agents unpack`) |
+| `commit` | Generate and apply git commits with the agentic commit pipeline |
+| `config` | Inspect or edit settings (`config.yml`) |
+| `grep` | Standalone content search using the in-tree ripgrep wrapper |
+| `grievances` | Review queued tool-issue / autoqa grievances |
+| `plugin` | Manage npm-installed plugins |
+| `read` | CLI inspector for files, archives, tool outputs, and `*://` URIs |
+| `search` (`q`) | Run the multi-provider web-search tool from the shell |
+| `setup` | First-run setup (Python kernel, OAuth, model defaults) |
+| `shell` | Spawn an interactive shell session through omp's bash runtime |
+| `ssh` | Manage SSH host definitions used by the `ssh` tool |
+| `stats` | Inspect session/usage statistics |
+| `update` | Update the installed omp binary |
### File Arguments
@@ -1197,31 +1483,46 @@ Text files are wrapped in `` blocks. Images are attached.
```bash
# Interactive mode
omp
-# Non-interactive
+
+# Non-interactive prompt
omp -p "List all .ts files in src/"
+
+# Continue / resume
omp -c "What did we discuss?"
-# Resume by ID prefix
omp -r abc123
+# Restrict toolset for a read-only review
+omp --tools read,search,find -p "Review the architecture"
+
+# Editor integration (ACP server, stdio transport)
+omp acp
+
+# Agentic commit on staged changes
+omp commit
+
+# Inspect a tool output by artifact URI
+omp read 'artifact://abc123'
+
# Model cycling with patterns
omp --models "sonnet:high,haiku:low"
-# Restrict toolset for read-only review
-omp --tools read,grep,find -p "Review the architecture"
-# Export session
+# Export a session to HTML
omp --export session.jsonl output.html
```
### Environment Variables
-| Variable | Description |
-| ------------------------------------------------- | ------------------------------------------------------- |
-| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, etc. | Provider credentials |
-| `PI_CODING_AGENT_DIR` | Override agent data directory (default: `~/.omp/agent`) |
-| `PI_PACKAGE_DIR` | Override package directory resolution |
-| `PI_SMOL_MODEL`, `PI_SLOW_MODEL`, `PI_PLAN_MODEL` | Role-model overrides |
-| `PI_NO_PTY` | Disable PTY-based bash execution |
-| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
+| Variable | Description |
+| ------------------------------------------------- | -------------------------------------------------------- |
+| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, etc. | Provider credentials |
+| `PI_CODING_AGENT_DIR` | Override agent data directory (default: `~/.omp/agent`) |
+| `PI_PACKAGE_DIR` | Override package directory resolution |
+| `PI_SMOL_MODEL`, `PI_SLOW_MODEL`, `PI_PLAN_MODEL` | Role-model overrides |
+| `PI_NO_PTY` | Disable PTY-based bash execution |
+| `PI_PY`, `PI_JS` | Gate the python / JavaScript backends of the `eval` tool |
+| `PI_HL_SEP` | Override the hashline payload separator (single char) |
+| `OMP_GITHUB_CACHE_DB` | Override the GitHub view cache database path |
+| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
See [Environment Variables](docs/environment-variables.md) for the complete reference.
@@ -1233,39 +1534,65 @@ Use `--tools ` to restrict available built-in tools.
### Built-in Tool Names (`--tools`)
-| Tool | Description |
-| ---------------- | -------------------------------------------------------------- |
-| `ask` | Ask the user structured follow-up questions (interactive mode) |
-| `bash` | Execute shell commands |
-| `python` | Execute Python code in IPython kernel |
-| `calc` | Deterministic calculator/evaluator |
-| `ssh` | Execute commands on configured SSH hosts |
-| `edit` | In-place file editing with anchors |
-| `find` | Find files by glob pattern |
-| `grep` | Search file content |
-| `ast_grep` | Structural code search using AST matching (ast-grep) |
-| `ast_edit` | Structural AST-aware code rewrites (ast-grep) |
-| `lsp` | Language server actions (11 operations) |
-| `notebook` | Edit Jupyter notebooks |
-| `read` | Read files/directories (default text cap: 3000 lines) |
-| `browser` | Browser automation tool (model-facing name: `puppeteer`) |
-| `task` | Launch subagents for parallel execution |
-| `poll` | Block on async background jobs |
-| `todo_write` | Phased task tracking with progress management |
-| `fetch` | Fetch and extract URL content |
-| `web_search` | Multi-provider web search |
-| `write` | Create/overwrite files |
-| `generate_image` | Generate or edit images using Gemini image models |
+| Tool | Description |
+| ------------------ | --------------------------------------------------------------------------------------- |
+| `ask` | Ask the user structured follow-up questions (interactive mode) |
+| `bash` | Execute shell commands |
+| `eval` | Run code in a persistent kernel (Python and JavaScript backends) |
+| `calc` | Deterministic calculator/evaluator |
+| `ssh` | Execute commands on configured SSH hosts |
+| `github` | Op-based wrapper around the GitHub CLI (`repo_view`, `pr_*`, `search_*`, `run_watch`) |
+| `recipe` | Run a recipe / target from the project's task runner (bun, just, make, …) |
+| `irc` | Send short messages between live agents (main ↔ subagents) |
+| `edit` | In-place file editing with anchors |
+| `write` | Create/overwrite files |
+| `find` | Find files by glob pattern |
+| `search` | Search file contents (regex) |
+| `ast_grep` | Structural code search using AST matching (ast-grep) |
+| `ast_edit` | Structural AST-aware code rewrites (ast-grep) |
+| `lsp` | Language server actions (multi-operation) |
+| `debug` | Debugger access via DAP (launch/attach, breakpoints, stepping, threads/stack/variables) |
+| `read` | Read files, directories, archives, SQLite, PDFs, notebooks, URLs |
+| `inspect_image` | Extract image content with a vision model |
+| `render_mermaid` | Render Mermaid diagrams to ASCII or PNG |
+| `browser` | Browser automation tool (model-facing name: `puppeteer`) |
+| `task` | Launch subagents for parallel execution |
+| `job` | Manage async background jobs (poll, cancel, list) |
+| `todo_write` | Phased task tracking with progress management |
+| `web_search` | Multi-provider web search |
+| `search_tool_bm25` | Tool-discovery search over hidden built-in / MCP / extension tools |
+| `generate_image` | Generate or edit images using Gemini image models |
+| `checkpoint` | Save a workspace checkpoint |
+| `rewind` | Rewind the workspace to a previous checkpoint |
+| `retain` | Persist a memory note (hindsight backend) |
+| `recall` | Recall memory notes (hindsight backend) |
+| `reflect` | Trigger memory consolidation (hindsight backend) |
Notes:
-- Some tools are setting-gated (`calc`, `browser`, etc.)
-- `ask` requires interactive UI
-- `ssh` requires configured SSH hosts
+- `ask` requires interactive UI.
+- `ssh` requires configured SSH hosts.
+- Some tools are setting-gated and are excluded from the active toolset unless enabled:
+ - `calc` ← `calc.enabled`
+ - `browser` ← `browser.enabled`
+ - `github` ← `github.enabled`
+ - `recipe` ← `recipe.enabled`
+ - `irc` ← `irc.enabled` (and only attached to the main agent when `async.enabled` is true)
+ - `inspect_image` ← `inspect_image.enabled`
+ - `render_mermaid` ← `renderMermaid.enabled`
+ - `web_search` ← `web_search.enabled`
+ - `find` / `search` ← `find.enabled` / `search.enabled`
+ - `ast_grep` / `ast_edit` ← `astGrep.enabled` / `astEdit.enabled`
+ - `lsp` ← `lsp.enabled` (and `--no-lsp` is not set)
+ - `checkpoint` / `rewind` ← `checkpoint.enabled`
+ - `debug` ← `debug.enabled`
+ - `search_tool_bm25` ← `tools.discoveryMode !== "off"` (or legacy `mcp.discoveryMode`)
+ - `retain` / `recall` / `reflect` ← `memory.backend === "hindsight"`
+ - `eval` python/JS backends individually gated by `eval.py` / `eval.js` (or the `PI_PY` / `PI_JS` env vars)
Example:
-`omp --tools read,grep,find -p "Review this codebase"`
+`omp --tools read,search,find -p "Review this codebase"`
For adding new tools, see [Custom Tools](#custom-tools).
@@ -1278,19 +1605,27 @@ For adding new tools, see [Custom Tools](#custom-tools).
For embedding omp in Node.js/TypeScript applications, use the SDK:
```typescript
-import { ModelRegistry, SessionManager, createAgentSession, discoverAuthStorage } from "@oh-my-pi/pi-coding-agent";
+import {
+ ModelRegistry,
+ SessionManager,
+ createAgentSession,
+ discoverAuthStorage,
+} from "@oh-my-pi/pi-coding-agent";
const authStorage = await discoverAuthStorage();
const modelRegistry = new ModelRegistry(authStorage);
await modelRegistry.refresh();
const { session } = await createAgentSession({
- sessionManager: SessionManager.inMemory(),
- authStorage,
- modelRegistry,
+ sessionManager: SessionManager.inMemory(),
+ authStorage,
+ modelRegistry,
});
session.subscribe((event) => {
- if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
- process.stdout.write(event.assistantMessageEvent.delta);
- }
+ if (
+ event.type === "message_update" &&
+ event.assistantMessageEvent.type === "text_delta"
+ ) {
+ process.stdout.write(event.assistantMessageEvent.delta);
+ }
});
await session.prompt("What files are in the current directory?");
```
@@ -1313,6 +1648,8 @@ For embedding from other languages or process isolation:
```bash
omp --mode rpc --no-session
+# or, for embedders that want to drive the TUI (tool cards, dialogs, selectors) over the protocol:
+omp --mode rpc-ui --no-session
```
Send JSON commands on stdin:
@@ -1320,12 +1657,49 @@ Send JSON commands on stdin:
```json
{"id":"req-1","type":"prompt","message":"List all .ts files"}
{"id":"req-2","type":"abort"}
+{"id":"req-3","type":"get_login_providers"}
+{"id":"req-4","type":"login","providerId":"anthropic"}
+{"id":"req-5","type":"handoff"}
```
-Responses are emitted as `type: "response"`; session events stream on stdout as they occur.
+Responses are emitted as `type: "response"`; session events and extension UI requests stream on stdout as they occur.
+
+Available command families (non-exhaustive): `prompt` / `steer` / `follow_up` / `abort` / `abort_and_prompt`, `new_session` / `switch_session` / `branch` / `handoff`, `get_state` / `get_messages` / `get_session_stats`, `set_model` / `cycle_model` / `get_available_models`, `set_thinking_level`, `compact` / `set_auto_compaction`, `bash` / `abort_bash`, `set_host_tools` (register host-side tools the agent can call back into), `get_login_providers` / `login`, `export_html`.
+
+`--mode rpc-ui` adds full UI plumbing on top of the same protocol: tool execution cards, selectors, dialogs, and other interactive surfaces are streamed as `extension_ui_request` frames that the embedder must answer with `extension_ui_response`. `--mode rpc` keeps it headless (no UI requests).
> See [RPC Documentation](docs/rpc.md) for the full protocol.
+### ACP Mode
+
+For embedding in editors that speak the [Agent Client Protocol](https://github.com/zed-industries/agent-client-protocol) (e.g. Zed):
+
+```bash
+omp acp
+# equivalent to: omp --mode acp
+```
+
+ACP mode starts a JSON-RPC server over stdio. It does **not** require a configured model at startup — the client can drive `initialize` and `authenticate` (including `/login`) before any model is selected. A `terminal` auth method is advertised when the client opts in via `clientCapabilities.auth.terminal` and falls back to an embedded interactive login flow.
+
+When the client advertises capabilities at `initialize`, the agent routes tool I/O through them via the `ClientBridge` abstraction (`packages/coding-agent/src/session/client-bridge.ts`):
+
+- `bash` → `terminal/create` + `terminal/output` (per-call client-side terminals)
+- `read` → `fs/read_text_file` (so unsaved editor buffers and in-memory edits are visible)
+- `write` → `fs/write_text_file` (writes go through the editor and let it track agent changes)
+- `bash`, `edit`, `write`, and `ast_edit` are gated behind `session/request_permission` when the client supports it; `allow_always` / `reject_always` decisions are remembered per tool for the session lifetime
+
+Slash commands available to ACP clients reach feature parity with the TUI for non-interactive flows, including `/model`, `/plan`, `/loop`, `/login`, `/logout`, `/agents`, `/extensions`, `/plugins`, `/marketplace`, `/mcp`, `/ssh`, `/session`, `/branch`, `/fork`, `/new`, `/resume`, `/drop`, `/handoff`, `/move`, `/memory`, `/todo`, `/jobs`, `/changelog`, `/dump`, `/copy`, `/hotkeys`, `/btw`, `/tree`, `/export`, `/share`, plus all `/skill:` commands. The full set is registered in `packages/coding-agent/src/slash-commands/acp-builtins.ts`.
+
+Beyond stock ACP methods, the agent exposes a small set of `_omp/*` extension methods for omp-aware clients (renamed from `omp/*` in 15.0.0 to match the ACP spec's `_`-prefix requirement for non-spec methods):
+
+- `_omp/sessions/listAll` — paginated cross-cwd session index
+- `_omp/projects/list` — discovered project cwds with session counts
+- `_omp/chats/byCwd` — sessions filtered by working directory
+- `_omp/usage` — token/cost rollup for active sessions
+- `_omp/extensions` / `_omp/extensions/toggle` — list and toggle discovered extensions
+
+Mode-aware notifications are also wired up: `session/set_mode` and `session/set_session_config_option("mode", …)` both emit `current_mode_update`; `/model` emits `config_option_update` after a model switch so client config selectors stay in sync; `tool_call_update.locations` is kept fresh from in-flight tool args so editors can "follow along" multi-file edits.
+
### HTML Export
```bash
@@ -1374,11 +1748,14 @@ For architecture and contribution guidelines, see [packages/coding-agent/DEVELOP
### Rust Crates
-| Crate | Description |
-| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
-| **[pi-natives](crates/pi-natives)** | Core Rust native addon used by `@oh-my-pi/pi-natives` |
-| **[brush-core-vendored](crates/brush-core-vendored)** | Vendored fork of [brush-shell](https://github.com/reubeno/brush) for embedded bash execution |
-| **[brush-builtins-vendored](crates/brush-builtins-vendored)** | Vendored bash builtins (cd, echo, test, printf, read, export, etc.) |
+| Crate | Description |
+| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
+| **[pi-natives](crates/pi-natives)** | Core Rust native addon (N-API `cdylib`) used by `@oh-my-pi/pi-natives`; aggregates the crates below |
+| **[pi-shell](crates/pi-shell)** | Embedded shell / PTY / process management split out of `pi-natives` (wraps `brush-*`) |
+| **[pi-ast](crates/pi-ast)** | tree-sitter-based code summarizer and AST utilities (50+ language grammars) |
+| **[pi-iso](crates/pi-iso)** | Task isolation backend resolver: APFS clones, btrfs/zfs reflinks, overlayfs, projfs, rcopy |
+| **[brush-core-vendored](crates/brush-core-vendored)** | Vendored fork of [brush-shell](https://github.com/reubeno/brush) for embedded bash execution |
+| **[brush-builtins-vendored](crates/brush-builtins-vendored)** | Vendored bash builtins (cd, echo, test, printf, read, export, etc.) |
---