Competitor Analysis: pi (pi.dev) — Minimal Terminal Coding Agent #123

Open
opened 2026-02-27 08:06:41 +00:00 by Hermes · 1 comment
Contributor

Overview

pi (@mariozechner/pi-coding-agent) by Mario Zechner (badlogic) is a minimal terminal coding harness for LLM-assisted coding.

Core Architecture

pi is a terminal-first interactive coding agent with 4 default tools: read, write, edit, bash. It supports 15+ LLM providers (Anthropic, OpenAI, Google, Azure, Bedrock, Mistral, Groq, xAI, OpenRouter, Ollama, etc.) with mid-session model switching.

4 modes: interactive (TUI), print/JSON (one-shot), RPC (process integration), SDK (embedding). Notably, OpenClaw is listed as a real-world SDK integration in their README.

Extension System (TypeScript)

This is pi's most differentiated feature. Extensions are TypeScript modules loaded via jiti (no compilation step), exporting a default function that receives an ExtensionAPI object:

export default function (pi: ExtensionAPI) {
  pi.registerTool({ name: "deploy", ... });      // Custom tools
  pi.registerCommand("stats", { ... });           // Slash commands
  pi.registerShortcut("ctrl+x", { ... });         // Keybindings
  pi.registerFlag("my-flag", { ... });             // Feature flags
  pi.on("tool_call", async (event, ctx) => { ... }); // Event hooks
}

Extension Capabilities

  • Custom toolspi.registerTool() with TypeBox schema for parameters. Can replace built-in tools entirely.
  • Event system — Rich lifecycle hooks: session_start, before_agent_start, agent_start, turn_start, context, tool_call, tool_result, agent_end, session_compact, etc. Events can block (e.g., block dangerous rm -rf), modify (transform tool results), or inject (add context before agent start).
  • Custom commands/mycommand registered via pi.registerCommand()
  • Custom keybindingspi.registerShortcut()
  • UI componentsctx.ui.custom() for full TUI components (select, confirm, input, notify, status line, widgets, overlays)
  • Session persistencepi.appendEntry() for state that survives restarts
  • Custom compaction — Override how context is summarized via session_before_compact event
  • Custom rendering — Control how tool calls/results render in the TUI

Extension Discovery

Location Scope
~/.pi/agent/extensions/*.ts Global
.pi/extensions/*.ts Project-local
Pi packages (npm/git) Shared

Pi Packages

Bundled extensions, skills, prompts, and themes distributed via npm or git:

pi install npm:@foo/pi-tools
pi install git:github.com/user/repo@v1

Skills System

Follows the Agent Skills standard — same standard OpenClaw uses. Skills are Markdown-based SKILL.md files invoked via /skill:name or auto-loaded. Placed in ~/.pi/agent/skills/, .pi/skills/, or shared via pi packages.

Other Notable Features

  • Tree-structured sessions — JSONL with id/parentId branching, /tree for navigation, /fork for branching
  • Context files — Loads AGENTS.md (or CLAUDE.md) from cwd up to home
  • Compaction — Automatic context summarization on overflow
  • Prompt templates — Reusable Markdown prompts with {{variables}}
  • Themes — Hot-reloadable TUI themes
  • Message queue — Steering messages during agent execution (Enter = interrupt, Alt+Enter = follow-up)

Comparison with OpenClaw/Cobot

Aspect pi OpenClaw/Cobot
Focus Coding assistance (terminal) Autonomous sovereign agents
Identity None (user's tool) Nostr keypair, self-sovereign
Payments None Lightning Network
Runtime Interactive terminal Daemon (headless + channels)
Extensions TypeScript ExtensionAPI Skills (Markdown) + tools
Distribution npm/git packages Skills, channels, tools
Multi-agent No built-in (extension possible) Native sub-agents, FileDrop
Channels Terminal only Telegram, Discord, Signal, etc.

Key Takeaways

  1. Extension API is well-designed — The event-driven lifecycle with block/modify/inject semantics is powerful and composable. Worth studying for Cobot's own extensibility story.
  2. Shared skills standard — Both use Agent Skills (agentskills.io), creating potential ecosystem overlap.
  3. SDK integration acknowledged — OpenClaw is explicitly mentioned as a real-world pi SDK integration, suggesting complementary rather than purely competitive positioning.
  4. Different niches — pi is a developer's coding tool; Cobot is an autonomous agent framework. Overlap exists in the "AI agent that does things" space but the sovereignty/identity/payments layer is unique to Cobot.
  5. No agent autonomy — pi has no daemon mode, no identity, no inter-agent communication, no payment rails. It's a human-in-the-loop coding harness, not an autonomous agent.
## Overview **pi** (`@mariozechner/pi-coding-agent`) by Mario Zechner (badlogic) is a minimal terminal coding harness for LLM-assisted coding. - **Website:** https://pi.dev - **Repo:** https://github.com/badlogic/pi-mono - **Package:** `npm install -g @mariozechner/pi-coding-agent` - **License:** Open source ## Core Architecture pi is a **terminal-first interactive coding agent** with 4 default tools: `read`, `write`, `edit`, `bash`. It supports 15+ LLM providers (Anthropic, OpenAI, Google, Azure, Bedrock, Mistral, Groq, xAI, OpenRouter, Ollama, etc.) with mid-session model switching. 4 modes: interactive (TUI), print/JSON (one-shot), RPC (process integration), SDK (embedding). Notably, **OpenClaw is listed as a real-world SDK integration** in their README. ## Extension System (TypeScript) This is pi's most differentiated feature. Extensions are TypeScript modules loaded via [jiti](https://github.com/unjs/jiti) (no compilation step), exporting a default function that receives an `ExtensionAPI` object: ```typescript export default function (pi: ExtensionAPI) { pi.registerTool({ name: "deploy", ... }); // Custom tools pi.registerCommand("stats", { ... }); // Slash commands pi.registerShortcut("ctrl+x", { ... }); // Keybindings pi.registerFlag("my-flag", { ... }); // Feature flags pi.on("tool_call", async (event, ctx) => { ... }); // Event hooks } ``` ### Extension Capabilities - **Custom tools** — `pi.registerTool()` with TypeBox schema for parameters. Can replace built-in tools entirely. - **Event system** — Rich lifecycle hooks: `session_start`, `before_agent_start`, `agent_start`, `turn_start`, `context`, `tool_call`, `tool_result`, `agent_end`, `session_compact`, etc. Events can **block** (e.g., block dangerous `rm -rf`), **modify** (transform tool results), or **inject** (add context before agent start). - **Custom commands** — `/mycommand` registered via `pi.registerCommand()` - **Custom keybindings** — `pi.registerShortcut()` - **UI components** — `ctx.ui.custom()` for full TUI components (select, confirm, input, notify, status line, widgets, overlays) - **Session persistence** — `pi.appendEntry()` for state that survives restarts - **Custom compaction** — Override how context is summarized via `session_before_compact` event - **Custom rendering** — Control how tool calls/results render in the TUI ### Extension Discovery | Location | Scope | |---|---| | `~/.pi/agent/extensions/*.ts` | Global | | `.pi/extensions/*.ts` | Project-local | | Pi packages (npm/git) | Shared | ### Pi Packages Bundled extensions, skills, prompts, and themes distributed via npm or git: ```bash pi install npm:@foo/pi-tools pi install git:github.com/user/repo@v1 ``` ## Skills System Follows the [Agent Skills standard](https://agentskills.io) — same standard OpenClaw uses. Skills are Markdown-based `SKILL.md` files invoked via `/skill:name` or auto-loaded. Placed in `~/.pi/agent/skills/`, `.pi/skills/`, or shared via pi packages. ## Other Notable Features - **Tree-structured sessions** — JSONL with `id`/`parentId` branching, `/tree` for navigation, `/fork` for branching - **Context files** — Loads `AGENTS.md` (or `CLAUDE.md`) from cwd up to home - **Compaction** — Automatic context summarization on overflow - **Prompt templates** — Reusable Markdown prompts with `{{variables}}` - **Themes** — Hot-reloadable TUI themes - **Message queue** — Steering messages during agent execution (Enter = interrupt, Alt+Enter = follow-up) ## Comparison with OpenClaw/Cobot | Aspect | pi | OpenClaw/Cobot | |---|---|---| | **Focus** | Coding assistance (terminal) | Autonomous sovereign agents | | **Identity** | None (user's tool) | Nostr keypair, self-sovereign | | **Payments** | None | Lightning Network | | **Runtime** | Interactive terminal | Daemon (headless + channels) | | **Extensions** | TypeScript `ExtensionAPI` | Skills (Markdown) + tools | | **Distribution** | npm/git packages | Skills, channels, tools | | **Multi-agent** | No built-in (extension possible) | Native sub-agents, FileDrop | | **Channels** | Terminal only | Telegram, Discord, Signal, etc. | ## Key Takeaways 1. **Extension API is well-designed** — The event-driven lifecycle with block/modify/inject semantics is powerful and composable. Worth studying for Cobot's own extensibility story. 2. **Shared skills standard** — Both use Agent Skills (`agentskills.io`), creating potential ecosystem overlap. 3. **SDK integration acknowledged** — OpenClaw is explicitly mentioned as a real-world pi SDK integration, suggesting complementary rather than purely competitive positioning. 4. **Different niches** — pi is a developer's coding tool; Cobot is an autonomous agent framework. Overlap exists in the "AI agent that does things" space but the sovereignty/identity/payments layer is unique to Cobot. 5. **No agent autonomy** — pi has no daemon mode, no identity, no inter-agent communication, no payment rails. It's a human-in-the-loop coding harness, not an autonomous agent.
Author
Contributor

Deep Dive: What Can We Learn from pi's Extension System

1. The Event-Driven Lifecycle Model

pi's core insight: everything is an interceptable event. The agent lifecycle is decomposed into ~20 fine-grained events, each with block/modify/continue semantics:

session_start → input → before_agent_start → agent_start
  → turn_start → context → tool_call → tool_execution_* → tool_result → turn_end
  → agent_end → session_shutdown

Key design patterns:

  • tool_call can block (return { block: true, reason }) — enables permission gates
  • tool_result can modify results — enables output filtering/enrichment
  • context can rewrite messages before LLM sees them — enables dynamic context injection
  • before_agent_start can inject messages and modify the system prompt per-turn
  • input can transform user input before skill/template expansion
  • Handlers chain like middleware — multiple extensions compose without conflicts

Lesson for Cobot: OpenClaw currently has skills (prompt injection) and tools (function calling) but lacks a formal event bus with interception. A lifecycle hook system would enable:

  • Safety gates without modifying core (block dangerous tool calls)
  • Context engineering plugins (inject relevant memory before each turn)
  • Audit/logging extensions (observe all tool calls without modifying them)
  • Custom compaction strategies

2. Extension Registration API

The ExtensionAPI surface is small but powerful:

pi.registerTool({ name, description, parameters, execute, renderCall?, renderResult? })
pi.registerCommand("name", { description, handler })
pi.registerShortcut("ctrl+x", { ... })
pi.registerFlag("my-flag", { ... })
pi.on("event", handler)
pi.sendMessage(message, { deliverAs, triggerTurn })
pi.sendUserMessage(content, { deliverAs })
pi.appendEntry(customType, data)  // session persistence

Notable: Tools can replace built-in tools entirely, not just add new ones. Extensions can override read, write, edit, bash — enabling SSH delegation, sandboxing, etc.

Lesson for Cobot: Our tools are currently defined in the system prompt or hard-coded. A registerTool() API would let skills provide callable functions, not just prompt instructions.

3. State Persistence via Session Entries

pi.appendEntry(customType, data) lets extensions persist state in the session JSONL. On session restore, extensions reconstruct state by scanning ctx.sessionManager.getBranch() for their custom entries.

This means extension state survives restarts AND respects branching — if you fork a session, the extension state forks with it.

Lesson for Cobot: Our agents use flat files (MEMORY.md, daily notes) for state. A structured session-scoped persistence layer would enable stateful tools that survive restarts without polluting the filesystem.

4. Message Delivery Modes

Three delivery modes for injected messages:

  • "steer" — interrupts after current tool, skips remaining
  • "followUp" — waits for agent to finish all tools
  • "nextTurn" — queued for next user prompt

Lesson for Cobot: Our sessions_send is fire-and-forget. Delivery modes would give inter-agent communication more precision — e.g., "inject this context but don't interrupt the current tool chain."

5. Package Distribution

pi packages bundle extensions + skills + prompts + themes in a single package.json:

{
  "name": "my-package",
  "keywords": ["pi-package"],
  "pi": {
    "extensions": ["./extensions"],
    "skills": ["./skills"],
    "prompts": ["./prompts"]
  }
}

Distributed via npm or git. Installed with pi install npm:@foo/bar. Package filtering lets users cherry-pick which resources to load.

Lesson for Cobot: ClewHub skills are currently standalone. A package format that bundles skills + tools + config would make distribution more composable. The filtering mechanism ("skills": [] to disable, glob patterns, !exclusions) is worth adopting.

6. Custom Tool Rendering

Extensions can define renderCall() and renderResult() to control how tool invocations appear in the TUI. This separates tool behavior from tool presentation.

Lesson for Cobot: Less relevant for our channel-based (Telegram/Discord) agents, but relevant for any future web UI or CLI surface.

7. Context Manipulation

The context event fires before every LLM call with a deep copy of all messages. Extensions can filter, reorder, inject, or transform messages without affecting the session history.

This is powerful: an extension can dynamically prune old messages, inject RAG results, or add system context — all transparently.

Lesson for Cobot: This is essentially programmable context engineering. Our system prompt + AGENTS.md approach is static. A context manipulation hook would let skills dynamically adjust what the LLM sees each turn.

8. Cross-Harness Skill Compatibility

pi explicitly supports loading skills from Claude Code (~/.claude/skills/) and OpenAI Codex (~/.codex/skills/) directories. They all share the Agent Skills standard.

Lesson for Cobot: OpenClaw already follows this standard. We should document cross-compatibility and make it easy to use pi/Claude Code skills in Cobot.

9. Example Extension Ecosystem (60+ examples)

Their examples reveal what users actually want:

Category Examples Relevance to Cobot
Safety permission-gate, protected-paths, dirty-repo-guard High — we need safety gates
Git git-checkpoint (stash per turn), auto-commit-on-exit Medium — useful for dev agents
Sub-agents subagent/ (isolated context windows) High — validates our approach
SSH ssh.ts (delegate all tools to remote) High — remote agent execution
Custom providers anthropic, gitlab-duo, qwen-cli Medium — we handle this differently
Plan mode plan-mode/ (read-only exploration) Medium — useful for complex tasks
Compaction custom-compaction, trigger-compact High — context management

Summary: What to Steal

  1. Event bus with interception — The single most valuable idea. Block/modify/continue semantics on lifecycle events.
  2. registerTool() API — Let skills register callable tools, not just prompt text.
  3. Message delivery modes — steer/followUp/nextTurn for inter-agent and extension messages.
  4. Context manipulation hooks — Programmable context engineering before each LLM call.
  5. Package bundling — Skills + tools + config in one distributable unit with filtering.
  6. Session-scoped state — Structured persistence that respects branching/forking.

What They Don't Have (Our Advantage)

  • No agent identity (Nostr keys)
  • No payment rails (Lightning)
  • No inter-agent communication (FileDrop, sessions)
  • No daemon mode (always human-in-the-loop)
  • No multi-channel support (terminal only)
  • No autonomous operation

pi is a great coding harness. Cobot is an autonomous agent framework. We can learn from their extension architecture without competing on their turf.

## Deep Dive: What Can We Learn from pi's Extension System ### 1. The Event-Driven Lifecycle Model pi's core insight: **everything is an interceptable event**. The agent lifecycle is decomposed into ~20 fine-grained events, each with block/modify/continue semantics: ``` session_start → input → before_agent_start → agent_start → turn_start → context → tool_call → tool_execution_* → tool_result → turn_end → agent_end → session_shutdown ``` **Key design patterns:** - `tool_call` can **block** (return `{ block: true, reason }`) — enables permission gates - `tool_result` can **modify** results — enables output filtering/enrichment - `context` can **rewrite messages** before LLM sees them — enables dynamic context injection - `before_agent_start` can **inject messages** and **modify the system prompt** per-turn - `input` can **transform** user input before skill/template expansion - Handlers **chain like middleware** — multiple extensions compose without conflicts **Lesson for Cobot:** OpenClaw currently has skills (prompt injection) and tools (function calling) but lacks a formal event bus with interception. A lifecycle hook system would enable: - Safety gates without modifying core (block dangerous tool calls) - Context engineering plugins (inject relevant memory before each turn) - Audit/logging extensions (observe all tool calls without modifying them) - Custom compaction strategies ### 2. Extension Registration API The `ExtensionAPI` surface is small but powerful: ```typescript pi.registerTool({ name, description, parameters, execute, renderCall?, renderResult? }) pi.registerCommand("name", { description, handler }) pi.registerShortcut("ctrl+x", { ... }) pi.registerFlag("my-flag", { ... }) pi.on("event", handler) pi.sendMessage(message, { deliverAs, triggerTurn }) pi.sendUserMessage(content, { deliverAs }) pi.appendEntry(customType, data) // session persistence ``` **Notable:** Tools can **replace built-in tools** entirely, not just add new ones. Extensions can override `read`, `write`, `edit`, `bash` — enabling SSH delegation, sandboxing, etc. **Lesson for Cobot:** Our tools are currently defined in the system prompt or hard-coded. A `registerTool()` API would let skills provide callable functions, not just prompt instructions. ### 3. State Persistence via Session Entries `pi.appendEntry(customType, data)` lets extensions persist state in the session JSONL. On session restore, extensions reconstruct state by scanning `ctx.sessionManager.getBranch()` for their custom entries. This means extension state **survives restarts AND respects branching** — if you fork a session, the extension state forks with it. **Lesson for Cobot:** Our agents use flat files (MEMORY.md, daily notes) for state. A structured session-scoped persistence layer would enable stateful tools that survive restarts without polluting the filesystem. ### 4. Message Delivery Modes Three delivery modes for injected messages: - `"steer"` — interrupts after current tool, skips remaining - `"followUp"` — waits for agent to finish all tools - `"nextTurn"` — queued for next user prompt **Lesson for Cobot:** Our `sessions_send` is fire-and-forget. Delivery modes would give inter-agent communication more precision — e.g., "inject this context but don't interrupt the current tool chain." ### 5. Package Distribution pi packages bundle extensions + skills + prompts + themes in a single `package.json`: ```json { "name": "my-package", "keywords": ["pi-package"], "pi": { "extensions": ["./extensions"], "skills": ["./skills"], "prompts": ["./prompts"] } } ``` Distributed via npm or git. Installed with `pi install npm:@foo/bar`. Package filtering lets users cherry-pick which resources to load. **Lesson for Cobot:** ClewHub skills are currently standalone. A package format that bundles skills + tools + config would make distribution more composable. The filtering mechanism (`"skills": []` to disable, glob patterns, `!exclusions`) is worth adopting. ### 6. Custom Tool Rendering Extensions can define `renderCall()` and `renderResult()` to control how tool invocations appear in the TUI. This separates tool *behavior* from tool *presentation*. **Lesson for Cobot:** Less relevant for our channel-based (Telegram/Discord) agents, but relevant for any future web UI or CLI surface. ### 7. Context Manipulation The `context` event fires before every LLM call with a **deep copy** of all messages. Extensions can filter, reorder, inject, or transform messages without affecting the session history. This is powerful: an extension can dynamically prune old messages, inject RAG results, or add system context — all transparently. **Lesson for Cobot:** This is essentially programmable context engineering. Our system prompt + AGENTS.md approach is static. A context manipulation hook would let skills dynamically adjust what the LLM sees each turn. ### 8. Cross-Harness Skill Compatibility pi explicitly supports loading skills from Claude Code (`~/.claude/skills/`) and OpenAI Codex (`~/.codex/skills/`) directories. They all share the [Agent Skills standard](https://agentskills.io). **Lesson for Cobot:** OpenClaw already follows this standard. We should document cross-compatibility and make it easy to use pi/Claude Code skills in Cobot. ### 9. Example Extension Ecosystem (60+ examples) Their examples reveal what users actually want: | Category | Examples | Relevance to Cobot | |---|---|---| | **Safety** | permission-gate, protected-paths, dirty-repo-guard | High — we need safety gates | | **Git** | git-checkpoint (stash per turn), auto-commit-on-exit | Medium — useful for dev agents | | **Sub-agents** | subagent/ (isolated context windows) | High — validates our approach | | **SSH** | ssh.ts (delegate all tools to remote) | High — remote agent execution | | **Custom providers** | anthropic, gitlab-duo, qwen-cli | Medium — we handle this differently | | **Plan mode** | plan-mode/ (read-only exploration) | Medium — useful for complex tasks | | **Compaction** | custom-compaction, trigger-compact | High — context management | --- ## Summary: What to Steal 1. **Event bus with interception** — The single most valuable idea. Block/modify/continue semantics on lifecycle events. 2. **`registerTool()` API** — Let skills register callable tools, not just prompt text. 3. **Message delivery modes** — steer/followUp/nextTurn for inter-agent and extension messages. 4. **Context manipulation hooks** — Programmable context engineering before each LLM call. 5. **Package bundling** — Skills + tools + config in one distributable unit with filtering. 6. **Session-scoped state** — Structured persistence that respects branching/forking. ## What They Don't Have (Our Advantage) - No agent identity (Nostr keys) - No payment rails (Lightning) - No inter-agent communication (FileDrop, sessions) - No daemon mode (always human-in-the-loop) - No multi-channel support (terminal only) - No autonomous operation pi is a great coding harness. Cobot is an autonomous agent framework. We can learn from their extension architecture without competing on their turf.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ultanio/cobot#123
No description provided.