Pi Coding Agent 完整指南

# Pi Coding Agent 完整指南

> **一句话定位**:pi 是 [Earendil Inc.](https://earendil.com) 出的极简终端 coding agent。哲学是"框架管核心、工作流靠你扩展",刻意不内置 sub-agent / plan mode / MCP / 权限弹窗 / TODO,全靠 Skills + Extensions + Packages 三层组合自己拼。
>
> 同类对比:比 Claude Code / Codex / OpenCode 都更"裸",但 **SDK 钩子最完整**——其他几个主要是 CLI,pi 是 CLI + SDK 双形态,能直接 `import` 进自己的 Node 进程。

---

## Level 1 · 5 分钟跑起来

### 安装

```bash
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
# 或
curl -fsSL https://pi.dev/install.sh | sh
```

`--ignore-scripts` 是官方推荐项,pi 自身不需要 install 阶段的 lifecycle script。

### 认证(二选一)

**订阅登录**(Claude Pro/Max、ChatGPT Plus/Pro Codex、GitHub Copilot):

```bash
pi
/login
```

**API Key**:

```bash
export ANTHROPIC_API_KEY=sk-ant-...
pi
```

支持的 API key provider 几乎全:Anthropic / OpenAI / Azure / DeepSeek / Gemini / Vertex / Bedrock / Groq / Cerebras / xAI / OpenRouter / Vercel AI Gateway / HuggingFace / Fireworks / Together / Kimi / MiniMax / 小米 MiMo 等等。

### 首跑

```bash
cd /your/project
pi
> Summarize this repo and how to run its checks
```

默认四把工具:`read` / `write` / `edit` / `bash`。还能开 `grep` / `find` / `ls`(read-only,通过 tool options)。

---

## Level 2 · 日常使用

### TUI 四块布局

```
┌────────────────────────────────────────┐
│ Startup header (快捷键、加载的 skills) │
├────────────────────────────────────────┤
│ Messages (用户/助手/工具调用/通知)     │
│                                        │
├────────────────────────────────────────┤
│ Editor (输入区,边框颜色=思考级别)     │
├────────────────────────────────────────┤
│ Footer (cwd、session、token、cost、$$) │
└────────────────────────────────────────┘
```

### 编辑器小技能

| 操作 | 用法 |
|------|------|
| 引用文件 | `@` 触发模糊搜 |
| 路径补全 | Tab |
| 多行 | Shift+Enter(Win Terminal 用 Ctrl+Enter)|
| 贴图 | Ctrl+V(Win 用 Alt+V),或拖入 |
| Shell 命令 | `!cmd` 跑且把输出喂给模型;`!!cmd` 跑但**不**喂 |
| 外部编辑器 | Ctrl+G 开 `$EDITOR` |

### 斜杠命令

| 命令 | 干什么 |
|------|--------|
| `/login` `/logout` | 凭据 |
| `/model` `/scoped-models` | 切模型;scoped 是 Ctrl+P 循环列表 |
| `/settings` | 思考级别、主题、消息投递、传输 |
| `/new` `/resume` `/name` `/session` | 会话生命周期 |
| `/tree` `/fork` `/clone` | 会话**树**操作 |
| `/compact [自定义提示]` | 手动压缩历史 |
| `/copy` `/export [file]` `/share` | 导出 |
| `/reload` | 重载键位/扩展/skills/prompts/上下文文件 |
| `/hotkeys` `/changelog` `/quit` | 杂项 |

### 消息队列

agent 流式输出时你也能继续输入:

- **Enter** = steering 消息,**当前 turn 跑完就送达**
- **Alt+Enter** = follow-up 消息,**所有任务全干完才送达**
- **Escape** = 中止 + 把队列消息撤回到编辑器
- **Alt+Up** = 把队列消息拿回编辑器改

### 会话与树(pi 的杀手特性)

会话存到 `~/.pi/agent/sessions/--<cwd path>--/<ts>_<uuid>.jsonl`,每条 entry 有 `id` + `parentId`,**整个会话本质是一棵树存在单文件里**。

```bash
pi -c                  # 接最近一次
pi -r                  # 浏览选一个
pi --no-session        # 不保存(一次性)
pi --session <id>      # 用特定 session(partial UUID 也行)
pi --fork <id>         # 复制一份新开
```

`/tree` 在 TUI 里直接走树,可以**回到任何历史节点继续聊**——不开新文件、原地分叉。这点比 Claude Code 的"不可逆 compaction"和 Codex 的"线性 history"都强。

`/fork` 从某条 user message 开新文件、`/clone` 把当前活跃分支复制到新文件。

### 上下文文件

- `~/.pi/agent/AGENTS.md` 全局
- `AGENTS.md` 或 `CLAUDE.md`(兼容)从 cwd 一路向上找
- 当前目录

替换默认 system prompt:放 `.pi/SYSTEM.md`(项目)或 `~/.pi/agent/SYSTEM.md`(全局)。追加(不替换):用 `APPEND_SYSTEM.md`。

### Compaction(自动 + 手动)

长会话超 context 时 pi 自己压。算法(源码 `src/core/compaction/compaction.ts`):

1. 从最新消息往回走,凑够 `keepRecentTokens`(默认 20k)的"保留段"
2. 把"保留段"之前的消息打包给 LLM 写结构化摘要
3. 写一条 `CompactionEntry`,下次 reload 用 摘要 + 保留段
4. 原始 jsonl **完整保留**,`/tree` 还能回去看

Compaction 是有损的,但树没动。这是为什么 pi 敢用——出错能回滚。

---

## Level 3 · 定制四件套

### 1. Prompt Templates

`~/.pi/agent/prompts/review.md`:

```markdown
Review this code for bugs, security, performance.
Focus on: {{focus}}
```

输入 `/review` 自动展开。也能放 `.pi/prompts/` 项目级。

### 2. Skills(按需加载)

遵循 [agentskills.io](https://agentskills.io) 标准:

```
~/.pi/agent/skills/my-skill/SKILL.md
~/.pi/agent/skills/my-skill/scripts/...
~/.pi/agent/skills/my-skill/references/...
```

触发:`/skill:my-skill`,或 agent 看上下文自己加载。

加载位置(按优先级):
- `~/.pi/agent/skills/`、`~/.agents/skills/`(全局)
- `.pi/skills/`、`.agents/skills/`(项目,从 cwd 向上找到 git 根)
- packages 里的 `skills/`
- settings 里的 `skills` 数组(可指向 `~/.claude/skills`、`~/.codex/skills` **共用**)

### 3. Extensions(最强)

```typescript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

export default function (pi: ExtensionAPI) {
  pi.registerTool({ name: "deploy", ... });
  pi.registerCommand("stats", { ... });
  pi.on("tool_call", async (event, ctx) => {
    if (event.toolName === "bash" && /rm -rf/.test(event.input.command)) {
      const ok = await ctx.ui.confirm("Really run this?");
      if (!ok) return { block: true };
    }
  });
}
```

放 `~/.pi/agent/extensions/`(auto-discover)或 `.pi/extensions/`。

**官方明确鼓励用 extension 补 pi 没做的事**:sub-agent、plan mode、permission gate、git checkpoint、SSH/sandbox 执行、MCP 集成、自定义 compaction、status line、自定义编辑器……

### 4. Themes

`dark` / `light` 内置,自己写就放 `themes/`。**热重载**——改文件 pi 立刻应用。

### Pi Packages(把上面四样打包共享)

```bash
pi install npm:@foo/pi-tools
pi install npm:@foo/pi-tools@1.2.3
pi install git:github.com/user/repo@v1
pi install https://github.com/user/repo
pi list
pi update              # 更新 pi 自己 + 包
pi update --self
pi config              # 启/禁单个资源
pi -e npm:@foo/bar     # 临时试用,不写 settings
```

`-l` flag 装到项目级(`.pi/git/`、`.pi/npm/`)。git 包默认 `npm install --omit=dev`,所以运行时依赖必须在 `dependencies`。

⚠️ **安全**:包跑全权限。装第三方包前看源码。

---

## Level 4 · 编程嵌入(pi 的差异化优势)

pi 跑四种模式:

| 模式 | 入口 | 适用 |
|------|------|------|
| Interactive | `pi` | 终端日常 |
| Print / JSON | `pi -p "..."` 或 `pi --mode json` | 一次性 / shell pipeline |
| RPC | `pi --mode rpc` | 非 Node 调用方走 stdin/stdout JSONL |
| **SDK** | `import` | Node.js 进程内嵌入 |

### SDK 最小可跑

```typescript
import {
  AuthStorage, createAgentSession,
  ModelRegistry, SessionManager,
} from "@earendil-works/pi-coding-agent";

const authStorage = AuthStorage.create();
const modelRegistry = ModelRegistry.create(authStorage);

const { session } = await createAgentSession({
  sessionManager: SessionManager.inMemory(),
  authStorage, modelRegistry,
});

session.subscribe(e => {
  if (e.type === "message_update" && e.assistantMessageEvent.type === "text_delta")
    process.stdout.write(e.assistantMessageEvent.delta);
});

await session.prompt("What files are here?");
```

### 几个核心类的分工

| 类 | 干什么 |
|---|---|
| `AgentSession` | 单次会话:消息流、模型、压缩、事件订阅 |
| `AgentSessionRuntime` | runtime 容器,能**替换** session(`/new` `/fork` `/resume` `/import` 都在这)|
| `SessionManager` | jsonl 持久化 + 树遍历 |
| `AuthStorage` + `ModelRegistry` | 凭据 + 模型发现,支持 `setRuntimeApiKey()` 不落盘 |
| `DefaultResourceLoader` | 加载 extensions/skills/prompts/themes/AGENTS.md |
| `InteractiveMode` | 完整 TUI(pi 命令本体)|

### 斜杠命令在 SDK 里的真相

**三类,行为完全不同**:

1. **TUI 内置命令** —— ❌ 不能当 prompt 字符串传,必须调对应 SDK 方法

   | TUI 斜杠 | SDK 等价 |
   |---|---|
   | `/new` | `runtime.newSession()` |
   | `/resume <id>` | `runtime.switchSession(target)` |
   | `/fork <id>` | `runtime.fork(entryId)` |
   | `/clone` | `runtime.fork(entryId, { position: "at" })` |
   | `/model <id>` | `session.setModel(...)` |
   | `/compact [prompt]` | `session.compact(customInstructions?)` |
   | `/tree` | `session.navigateTree(targetId, opts)` |

   **铁律**:会话替换操作必须走 `AgentSessionRuntime`,不在 `AgentSession` 上。

2. **纯 UI 命令** —— `/login` `/copy` `/share` `/export` 等,服务端没意义,丢弃。

3. **用户/扩展命令** —— ✅ `/skill:xxx`、`/<template>`、扩展的 `/<cmd>` 直接 `session.prompt("/...")` 即可。

### 必踩的 6 个坑

1. **会话替换后事件订阅失效**——必须 unsubscribe + re-subscribe。
2. **流式中 `prompt()` 不带 streamingBehavior 会抛**——必须显式 `{ streamingBehavior: "steer" | "followUp" }`。
3. **扩展命令不能 queue**——必须非流式时执行。
4. **每个聊天独立 cwd**——别让所有聊天共享一个 cwd。
5. **runtime Map 并发要 mutex**——同一 chatId 收两条快速消息会并发调 `prompt()`。
6. **API key 解析顺序**:`setRuntimeApiKey` → `auth.json` → env → models.json fallback。临时换 key 用 `setRuntimeApiKey`(不持久化)。

### 多租户嵌入(飞书 bot / 多用户平台)

| 隔离层 | 调谁 |
|---|---|
| 资源根(auth/skills/extensions/sessions)| `agentDir` 参数,或 `PI_CODING_AGENT_DIR` env |
| 项目层(`.pi/`、AGENTS.md ancestor walk)| `cwd` 参数 |
| 凭据 | `AuthStorage.create(customAuthPath)` + `setRuntimeApiKey()` |
| 自定义模型表 | `ModelRegistry.create(authStorage, customModelsPath)` |
| 进程隔离 / OS uid 隔离 / 资源限额 | bwrap、systemd-run、容器(自己叠)|

**部署模式**:

| 模式 | 隔离强度 | 适用 |
|---|---|---|
| **CLI spawn** | 进程级 | 飞书 bot 起步推荐 |
| **SDK 同进程多 session** | 应用层路径隔离 | 互信用户 |
| **SDK + 子进程 worker** | 进程级 + SDK 灵活性 | 既要隔离也要 SDK 钩子 |
| **SDK + bwrap/容器** | 内核级 | 互不信任 |

源码定位:
- `packages/coding-agent/src/config.ts:472` — `getAgentDir()`,所有路径的根
- `packages/coding-agent/src/config.ts:452` — `ENV_AGENT_DIR` / `ENV_SESSION_DIR` 定义

---

## Level 5 · 自实现 `/goal` 循环

**Codex** 和 **Claude Code** 都内置了 `/goal`:持久目标 + 自动循环 + 评估器判完成。**pi 官方核心不做这层**。

补的方式两条:

1. 装社区扩展:`pi install npm:pi-goals`(对标 Codex)或 `pi install npm:@capyup/pi-goal`(对标 Claude Code,意图先行)
2. SDK 自实现:

```typescript
async function runGoal(rt, condition, maxTurns = 20) {
  await rt.session.prompt(condition);
  for (let i = 0; i < maxTurns; i++) {
    while (rt.session.isStreaming) await new Promise(r => setTimeout(r, 200));
    // 评估器必须是另一个模型实例
    const verdict = await pi.sendMessage(
      `Has "${condition}" been satisfied? "YES: ..." or "NO: ..."`,
      { model: "claude-haiku" }
    );
    if (/^YES/i.test(verdict.text)) return { satisfied: true, turns: i + 1 };
    await rt.session.followUp("Continue working toward the goal.");
  }
  return { satisfied: false, turns: maxTurns };
}
```

**关键**:评估器**必须是另一个模型实例**,不要让干活的 session 自己评判——干活的模型容易自我说服"我做完了"。

---

## Level 6 · 设计哲学

pi 主动**不做**这些(来自官方 README):

- **No MCP** — 用 CLI 工具 + README(即 Skills),或写 extension 加 MCP 支持
- **No sub-agents** — 用 tmux 多开 pi 实例,或 extension 自己造
- **No permission popups** — 跑容器里,或 extension 内联确认流
- **No plan mode** — 写到文件,或 extension 实现
- **No built-in TODO** — "they confuse models"
- **No background bash** — 用 tmux

整体逻辑:**核心保持极简,不绑定工作流;扩展点足够强,让用户用代码塑形 pi**。

---

## Level 7 · 与同类对比速查

| 维度 | pi | Claude Code | Codex CLI | OpenCode |
|---|---|---|---|---|
| 形态 | CLI + **SDK** | CLI | CLI | CLI |
| 默认 provider | 多家 | Claude only | OpenAI only | 多家 |
| 内置 sub-agent | ❌ | ✅ | ❌ | ❌ |
| 内置 plan mode | ❌ | ✅ | ✅ | ❌ |
| 内置 `/goal` | ❌(社区扩展)| ✅ | ✅ | ❌ |
| 内置 MCP | ❌ | ✅ | ✅ | ❌ |
| 会话树 + 原地分叉 | **✅(核心特色)** | ❌ | ❌ | ❌ |
| Skills 标准 | agentskills.io | 自家 | 自家 | 无 |
| 扩展机制 | TS extensions(最强)| 有限 | 有限 | 有限 |
| 嵌入式 SDK | **✅** | ❌ | ❌ | ❌ |

**什么时候选 pi**:
- 要嵌入到自己的产品(飞书 bot、Web 后端、自动化 pipeline)
- 想用同一个 agent 在多 provider 间切换
- 重视会话树/分叉/历史回溯
- 愿意为定制写 TS extension

**什么时候不选 pi**:
- 只想开箱即用 sub-agent / plan mode / MCP(选 Claude Code)
- 强依赖 ChatGPT subscription(选 Codex)
- 完全不需要扩展,只要稳定 CLI(任意都行)

---

## 学习路径

```
Day 1: Level 1+2  —— 装上跑通,玩熟 TUI 和 /tree
Day 2: Level 3    —— 写一个 prompt template + 一个 skill
Day 3: Level 4    —— 写一个 extension 拦截 bash 危险命令
Week 2: Level 5+6 —— 嵌入到一个自己的项目、读一遍 src/config.ts
```

**官方文档入口**:
- 主页 https://pi.dev/docs/latest
- GitHub https://github.com/earendil-works/pi/tree/main/packages/coding-agent
- npm https://www.npmjs.com/package/@earendil-works/pi-coding-agent
- Discord https://discord.com/invite/3cU7Bz4UPx

**Hermes 配套 skill**:`skill_view(name='pi-coding-agent-sdk')` 调出整理过的 SDK 集成手册(含飞书 bot 模板、多租户架构图、斜杠命令完整对照表)。