最近准备认真看一下 Pi Coding Agent。它把自己定义成一个 minimal terminal coding harness:核心只提供一套能工作的终端 Coding Agent,sub-agent、plan mode 等能力没有全部内置,而是留给 Extension、Skill、Prompt Template、Theme 和 Pi Package。
这和我一开始的预期不太一样。我原本以为它又是一个安装、登录、进入 TUI 就算体验完成的 Coding Agent。读完 README 才发现,Pi 更值得观察的是它如何划分核心与扩展,以及这种取舍能不能让日常使用更可控。
这一篇先不谈架构,只记录安装、目录选择和第一批扩展。CLI、六个 Pi Package 和 RTK 已经装好,模型认证和第一次最小会话也已完成;各个扩展的实际效果,留到后面继续验证。
1. 安装环境
这次使用的是 Linux x86_64:
Node.js: v24.15.0
npm: 11.12.1
Bun: 1.3.14
Pi: 未安装Pi 0.81.1 要求 Node.js >=22.19.0,现有版本不需要升级。Node.js 由 NVM 管理,这个细节会直接影响 Pi 的安装位置,以及切换 Node.js 版本后还能不能找到 pi。
2. 两种安装方式
Pi README 给出的 npm 安装命令是:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent也可以使用官方脚本:
curl -fsSL https://pi.dev/install.sh | sh我没有直接执行 curl | sh,而是先把脚本保存下来:
curl -fsSL https://pi.dev/install.sh -o /tmp/pi-install.sh
less /tmp/pi-install.sh
sh /tmp/pi-install.sh截至本文记录时,install.sh 并不是另一套发行方式,最终仍然通过 npm 安装同一个包。它主要多做几件事:
- 检查 Node.js 和 npm;
- 在缺少合适 Node.js 时协助安装;
- 判断 npm 全局目录是否可写;
- 必要时回退到
~/.local; - 检查并配置
PATH; - 提供重新安装和卸载入口。
两种方式都使用 --ignore-scripts,禁止依赖在安装阶段运行 preinstall、install 和 postinstall。这不能消除所有供应链风险,但能收窄安装时自动执行的代码范围。Pi 的普通 npm 安装也不依赖这些 lifecycle scripts。
对于还没有 Node.js 的新机器,安装脚本比较省事;这台机器已经通过 NVM 管理 Node.js,直接使用 npm 更容易预测。
3. Pi 会安装到哪里
在安装前,我先确认了 npm 的全局 prefix:
npm prefix -g输出是:
~/.nvm/versions/node/v24.15.0全局包目录则是:
npm root -g~/.nvm/versions/node/v24.15.0/lib/node_modulesnpm 的“全局”不是指整台机器只能有一个全局目录,而是指这个包不属于某个项目。全局包可能由系统、用户自定义 prefix 或某个 NVM Node.js 版本管理:
| 类型 | 示例目录 | 范围 |
|---|---|---|
| 项目本地包 | 项目/node_modules/ | 当前项目 |
| 用户级全局包 | ~/.local/lib/node_modules/ | 当前用户、指定 prefix |
| NVM 全局包 | ~/.nvm/versions/node/v24.15.0/lib/node_modules/ | 当前用户、当前 Node.js 版本 |
Pi 安装脚本会检查 <prefix>/lib/node_modules 和 <prefix>/bin 是否可写。如果 npm 默认 prefix 是普通用户不可写的 /usr/local,并且那里没有旧的 pi,脚本会回退到:
npm install -g \
--prefix "$HOME/.local" \
--ignore-scripts \
@earendil-works/pi-coding-agent这样包和命令会分别落在:
~/.local/lib/node_modules/@earendil-works/pi-coding-agent/
~/.local/bin/pi如果旧 prefix 已经存在 pi,脚本会停止,不再安装第二份。否则系统中可能同时出现 /usr/local/bin/pi 和 ~/.local/bin/pi,实际运行哪一个只能由 PATH 顺序决定。
要不要主动使用 ~/.local
把 Pi 安装到 ~/.local,可以避免命令位置绑定某个 NVM 版本。但 Pi 的 npm 包并不会因此变成独立二进制,它的入口仍然通过:
#!/usr/bin/env node寻找当前 PATH 中的 Node.js。切换到低于 22.19.0 的版本后,pi 命令虽然还在,程序仍然无法正常运行。
自定义 prefix 也要一直带在后续的 npm 命令中:
npm list -g --prefix "$HOME/.local" --depth=0
npm uninstall -g \
--prefix "$HOME/.local" \
@earendil-works/pi-coding-agent所以我没有主动迁移。当前 NVM prefix 属于当前用户,相关目录都可写,也不需要 sudo。
4. 完成 CLI 安装
实际执行:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent然后检查:
command -v pi
pi --version结果:
~/.nvm/versions/node/v24.15.0/bin/pi
0.81.1这只能说明 CLI 已经安装,还不代表 Pi 配置完成。它仍然需要模型提供商和认证信息,才能开始第一次会话。
5. Pi Package 不是全局 npm 包
安装 Pi 本体以后,我又看了六个社区包:Todo、结构化提问、Hooks、CLIProxyAPI Provider、Subagents 和 RTK Optimizer。
Pi Package 不应该直接用 npm install -g 管理,而是交给 Pi:
pi install npm:pi-ask-user默认安装位置是:
~/.pi/agent/npm/来源会记录在:
~/.pi/agent/settings.json之后可以统一查看、更新和移除:
pi list
pi update --extensions
pi remove npm:pi-ask-user项目级安装使用 -l:
pi install -l npm:pi-ask-user它会修改当前项目的 .pi/settings.json,并把依赖放进 .pi/npm/。项目被信任后,Pi 会自动补齐缺少的包。这个能力适合团队共享,但这次只是个人配置,没有必要让 blogv3 仓库承担这些依赖。
临时试用则可以使用 -e:
pi -e npm:pi-ask-user包只对当前 Pi 进程生效,适合检查 UI 和启动错误。
Pi Package 也不只是普通数据包。Extension 可以执行任意代码,Skill 可以影响 Agent 使用工具和执行命令,pi install 还会运行 npm install 安装依赖。第三方包至少要先看仓库、发布包内容和它注册的资源。
6. 六个包分别做什么
我先下载 npm tarball,检查 package.json 中的 pi manifest、README 和源码入口,没有立即装进真实配置。
| Package | 版本 | 作用与限制 |
|---|---|---|
@pi-archimedes/todo | 1.8.2 | 注册 manage_todo_list 和 /todos;子 Agent 分栏依赖 Archimedes 自己的组件 |
pi-ask-user | 0.13.0 | 注册支持单选、多选和自由输入的 ask_user,并附带指导 Agent 何时提问的 Skill |
@hsingjui/pi-hooks | 0.0.2 | 把 Pi 事件映射成类似 Claude Code 的 command hooks;规则通过 bash -c 执行,权限很高 |
@router-for-me/pi-cliproxyapi-provider | 1.4.7 | 从 CLIProxyAPI 发现模型并注册 Provider,需要服务地址和 Key |
@router-for-me/pi-subagents-lite | 1.5.0 | 提供并发、后台执行和独立模型配置;默认可继承全部工具、Extension 和 Skill |
pi-rtk-optimizer | 0.9.0 | 改写工具命令并压缩输出;依赖外部 rtk,有损 Read 压缩默认关闭 |
@pi-archimedes/todo 能显示子 Agent 的 Todo,不代表它能自动识别所有第三方 Subagent 插件。这个能力依赖 Archimedes 自己的 bus 和事件。把它和 pi-subagents-lite 分别装上,不能据此判断两者已经联动。
7. peer dependency 只是第一层判断
三个包声明的 peer dependency 没有覆盖 Pi 0.81.1:
pi-cliproxyapi-provider: >=0.80.9 <0.81.0
pi-subagents-lite: ^0.80.1
pi-rtk-optimizer: 最高列到 ^0.80.0按照 SemVer,^0.80.x 不会覆盖 0.81.1。不过,“没有声明支持”不等于“一定无法运行”。
我把兼容性测试放进临时配置目录:
PI_CODING_AGENT_DIR=/tmp/pi-compat-test \
pi install npm:@router-for-me/pi-subagents-lite
PI_CODING_AGENT_DIR=/tmp/pi-compat-test \
PI_OFFLINE=1 \
pi --no-context-files --no-session --list-models三个包都能完成安装,被 pi list 识别,离线启动时也没有 Extension API 错误。CLIProxyAPI Provider 还输出了未配置提示,说明入口代码确实执行了。
Pi 0.81.1 的 changelog 提到,该版本恢复了 pre-0.81 agent-core Extension 所需的默认 stream fallback。这也说明 Pi 仍保留了一部分旧 API 兼容路径。
目前能得出的结论只有三层:
- peer dependency 尚未声明支持 Pi
0.81.1; - 包可以安装,Extension 可以完成基础加载;
- 登录和推理、真实子 Agent 调用、RTK 输出压缩还没有验证。
版本范围、安装成功、基础加载和完整兼容,是四件不同的事。
8. 安装扩展和 RTK
确认发布包和基础加载没有明显问题后,我把六个包安装到用户级配置:
pi install npm:@pi-archimedes/todo
pi install npm:pi-ask-user
pi install npm:@hsingjui/pi-hooks
pi install npm:@router-for-me/pi-cliproxyapi-provider
pi install npm:@router-for-me/pi-subagents-lite
pi install npm:pi-rtk-optimizer我没有固定版本,Pi 会记录包名,之后由 pi update --extensions 更新。安装时的 npm audit 没有报告已知漏洞,但这不等于 Extension 已经经过安全审计。
pi-rtk-optimizer 只是 Pi 与 RTK 之间的适配器,不包含 rtk 命令。本机最初找不到 rtk,插件虽然能加载,命令改写仍会回退到原始命令。
我同样先下载并阅读 RTK 的安装脚本:
curl -fsSL \
https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh \
-o /tmp/rtk-install.sh
less /tmp/rtk-install.sh
sh /tmp/rtk-install.sh脚本会从 GitHub Release 下载对应二进制,验证 SHA-256,默认安装到 ~/.local/bin/rtk。本次装到的版本是:
rtk 0.43.0最小验证:
rtk rewrite 'git status'输出:
rtk git statusRTK 提示尚未执行 rtk init -g,我没有照做。这个命令主要为其他 Coding Agent 安装全局 Hook;pi-rtk-optimizer 已经监听 Pi 的 tool_call 事件并调用 rtk rewrite,没有必要再修改其他工具的配置。
9. 完成第一次模型调用
配置模型以后,我重新启动 Pi。启动页识别到了 ask-user Skill 和已经安装的六个 Extension,当前模型显示为 gpt-5.6-sol。
先只发一个最简单的消息:
hi模型正常返回:
Hi! How can I help?到这里可以确认模型发现、认证和最基本的请求链路已经工作,已安装的 Extension 也能完成启动加载。