本記事はAI(Claude)が執筆し、人間が事実確認・編集を行っています。
Claude Code、Cursor、Codex CLI。コーディングエージェントには毎月のように機能が足される。MCP、サブエージェント、プランモード、バックグラウンド実行。できることは増えた。だが裏側で何が動いているか、把握しきれなくなってきた。
pi はその流れに逆行する。GitHub スター数は 21,000 超。作者の Mario Zechner は Java ゲームフレームワーク libGDX で知られるエンジニアで、既存のコーディングエージェントに不満を持ち、自分用にゼロから書いた。設計原則は "if I don't need it, it won't be built"。既存ツールはユーザーの裏でコンテキストを注入し、何が起きているか見えなくしている。それが動機だった。
pi は何を削ぎ落とし、何を残し、何をユーザーに委ねたのか。
pi の設計で目立つのは、他のコーディングエージェントが当然持っている機能を意図的に外していることだ。
| 入れなかった機能 | pi での代替 |
|---|---|
| MCP(Model Context Protocol) | CLI ツールの README をスキルとして読ませる |
| サブエージェント | tmux で pi を複数立てる |
| 権限確認ポップアップ | コンテナで実行する。または Extension で書く |
| プランモード | ファイルに計画を書く。または Extension で書く |
| バックグラウンド bash | tmux で別ペインに出す |
足りないのではない。入れないと決めた。
Zechner はブログで MCP に疑問を投げている。問題はプロトコルの存在ではなく、トークンコストだ。Playwright MCP は 21 ツール・13,700 トークンで、コンテキストウィンドウの 7〜9% を食う。Chrome DevTools MCP は 26 ツール・18,000 トークン。MCP サーバーを接続すれば、毎セッション全ツール定義がコンテキストに流し込まれる。CLI ツールには README がある。必要なときだけそれを読んで実行すればいい。常時コンテキストを消費する理由がない。
サブエージェントへの態度も同じだ。Claude Code はサブエージェントを内部で起動し、結果だけ要約して返す。中で何が起きたかは外から見えない。pi は tmux でインスタンスを横に並べる。やりとりはすべて人間が直接読める。
既存のハーネスに対する批判はもう1つある。システムプロンプトやツール定義が頻繁に変わり、ユーザーはどんなコンテキストが注入されているか制御できない。pi はシステムプロンプトを 1,000 トークン未満に抑え、内容を完全に公開している。
一貫しているのは、ハーネスがワークフローを決めるべきではないという考え方だ。足りなければ使う人が自分で作る。
pi は 7 つのパッケージで構成されたモノレポだ。依存は上から下への一方向で、下位パッケージだけ取り出して使える。
┌─────────────────────────────────────────────────┐
│ アプリ層 │
│ pi-coding-agent / pi-mom / pi-web-ui / pi-pods │
├─────────────────────────────────────────────────┤
│ エージェント層 │
│ pi-agent-core │
├─────────────────────────────────────────────────┤
│ UI 層 │ 基盤層 │
│ pi-tui │ pi-ai │
└─────────────────────────────────────────────────┘
最下層の pi-ai は 15 以上のプロバイダに対応した統一 LLM API だ。Anthropic、OpenAI、Google、Azure、Bedrock、Mistral、Groq、Cerebras、xAI、OpenRouter。Ollama や vLLM のように OpenAI 互換 API を話すローカルプロバイダも接続できる。ツール呼び出し対応のモデルだけをサポートし、ツール定義は TypeBox スキーマで書く。AJV が自動でバリデーションをかける。
pi-agent-core はその上にエージェントループを載せる。ツール実行、メッセージキュー、コンテキスト管理を受け持つ。
pi-coding-agent がユーザーの触る CLI だ。ツールは read、write、edit、bash の 4 つだけ。コードを読み、書き、直し、コマンドを叩く。
残り 4 つは用途別のパッケージだ。pi-tui は差分レンダリングのターミナル UI。pi-web-ui はブラウザ向けチャット UI。pi-mom は Slack ボット。pi-pods は vLLM を GPU にデプロイする CLI。
使いたい層だけ切り出せる。pi-ai 単体でマルチプロバイダ LLM クライアントを作れるし、pi-agent-core で独自エージェントを組むこともできる。
引き算で設計された pi だが、Claude Code が持っていない機能もある。
pi の Context はプロバイダに依存しない形式でシリアライズされる。Anthropic で作業を始めて、途中で OpenAI に切り替えても文脈は残る。/model か Ctrl+L で即座に切り替わる。
思考の扱いも統一した。Claude の extended thinking、OpenAI の reasoning effort、Gemini の thinking budget を minimal から xhigh まで 5 段階に揃えている。
セッション履歴は JSONL で保存される。各エントリが id と parentId を持ち、ツリー構造を作る。/tree コマンドで過去の任意の時点に戻れて、そこから別の分岐を伸ばせる。
Git のブランチに似ているが、履歴は 1 ファイルに収まる。あの時点のアプローチに戻りたい。そう思ったとき、セッションを最初からやり直さなくていい。
Extensions、Skills、Prompt Templates、Themes をまとめて npm や git で配布できる。
pi install npm:@foo/pi-tools pi install git:github.com/user/repo pi config # 有効・無効を切替
コミュニティが拡張を作って共有する仕組みが、ツール本体に組み込まれている。
pi が機能を絞っても使えるのは、3 つの拡張手段を持っているからだ。
Extensions の自由度が一番高い。TypeScript で書き、カスタムツール、コマンド、ショートカット、イベントハンドラを足せる。ツール呼び出しの前後にフックを挟めるので、たとえば危険なコマンドをブロックする Extension はこう書ける。
import { ExtensionAPI } from "@mariozechner/pi-coding-agent"; export default function (pi: ExtensionAPI) { pi.on("tool_call", async (event, ctx) => { if (event.toolName === "bash" && event.input.command.includes("rm -rf")) { const ok = await ctx.ui.confirm( "Dangerous!", "Allow rm -rf?" ); if (!ok) return { block: true, reason: "Blocked" }; } }); }
Claude Code の権限確認ポップアップを省いたのではない。ユーザーが自分の基準で作れるようにした。
Skills は Agent Skills 標準に準拠した SKILL.md ファイルで、Claude Code のスキルと同じ仕様に従う。
Prompt Templates は /templatename で展開できる再利用可能な Markdown ファイルだ。Mustache 変数({{variable}})も使える。
インストールは 3 行で済む。
npm install -g @mariozechner/pi-coding-agent export ANTHROPIC_API_KEY=sk-ant-... pi
Anthropic 以外のプロバイダも /login で追加できる。OpenAI、GitHub Copilot、Google Gemini。Claude Max や ChatGPT Plus のサブスクリプション認証にも対応している。
操作体系は Claude Code と重なる部分がある。
| 操作 | pi |
|---|---|
| ファイル参照 | @ であいまい検索、Tab でパス補完 |
| bash 実行 | !command で結果を LLM に送る。!!command は送らない |
| モデル切替 | /model か Ctrl+L |
| 画像入力 | Ctrl+V でクリップボードから貼る |
| 思考レベル | Shift+Tab |
| セッション続行 | pi -c で直近、pi -r で選択 |
| 履歴ナビゲーション | /tree で分岐点を一覧して選ぶ |
pi から読み取れることが 3 つある。
機能を足すほど、ユーザーから見えない処理が増える。サブエージェント、バックグラウンド実行、自動コンパクション。どれも便利だが、ブラックボックスを増やす。pi はすべてのやりとりを人間が直接観察できることを最優先にした。
常時接続されるツール定義はコンテキストを圧迫する。MCP サーバーを 3 つ接続すれば、それだけで数万トークンがコンテキストから消える。pi は必要なときにだけ読むアプローチでこの問題を避けた。
削ったものの代わりを自分で作れる仕組みがあれば、本体は薄くていい。pi は Extensions、Skills、Prompt Templates の 3 層で拡張性を確保した上で、本体を絞った。削るだけでは使い物にならない。削った穴を埋める手段を用意したから成立している。
エージェントを自分で作る側に回ったとき、pi の設計判断は参照点になる。全部入りで始めるのではなく、4 つのツールと 1,000 トークンのシステムプロンプトから始めて、必要なものだけ足す。何を足すかではなく、何を削るかから始める設計だ。
この記事は note でも公開しています。