我平时用 opencode 挺多的,用得也算顺手。前一阵子崔总跟我说,建议也试试 pi 吧。我一开始还纳闷,pi 是个啥东西,没听说过。装上一看才明白,它跟 opencode 是同一类东西,都是跑在终端里的 AI 编程助手,但这两个家伙的脾气完全不一样。
这篇文章就说说 pi 是啥、怎么用,以及它和 opencode 到底差在哪。我尽量按自己用下来的实际感受写,不吹也不黑,讲错了的地方欢迎指出来。
pi 是个啥
pi 的全名是 @earendil-works/pi-coding-agent,作者是 Mario Zechner,也就是当年写 libGDX 的那个 badlogic。官网是 pi.dev,MIT 协议,用 TypeScript 写的,跑在 Node 上,要求 Node 22.19 以上。我装的时候是 0.85.1。
它给自己的定位是 minimal terminal coding harness,直译就是"极简的终端编程外壳"。注意它说的是 harness,外壳,不是 framework,也不是 platform。意思很清楚:它只管最核心的那点事,剩下的都留着让你自己加。
默认情况下,pi 只给模型四个工具,read、write、edit、bash,另外还有 grep、find、ls 这些查东西用的。就这些。你让它干活,它就靠这么几个工具去干。
最有个性的地方,是它故意不做很多东西。官方文档里说得很直白:
No MCP. No sub-agents. No permission popups. No plan mode. No built-in to-dos. No background bash.
翻译过来就是:没有 MCP、没有子智能体、没有权限弹窗、没有计划模式、没有内置待办、没有后台 bash。
这几样东西,在 opencode 里基本都有。pi 的态度是,你要你就自己搭,或者装别人写好的包,别指望我塞给你。
我刚看到这段的时候,第一反应是,这不等于啥都没有吗。后来用了一阵子才转过弯来,它不是没有,是把这些都做成了"可选",而不是"必须"。内核小,改起来就方便,这跟 opencode 那种"开箱即用"是两个路子。
怎么装、怎么跑起来
安装有两种方式,一种是 npm,一种是官方脚本。npm 这种:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
那个 --ignore-scripts 是官方特意让加的,因为 pi 正常安装不需要跑依赖的安装脚本,加上这个更安稳。
如果你更喜欢脚本,也可以:
curl -fsSL https://pi.dev/install.sh | sh
装完要配一个模型。最省事的是设个环境变量:
export ANTHROPIC_API_KEY=sk-ant-...
pi
或者不设环境变量,直接敲 pi 进去,再用 /login 选提供商:
/login
然后就能用了。在终端里敲 pi,进去就是交互界面,直接跟它说话就行,跟 opencode 一样,没什么学习成本。
日常怎么用
进到界面里,编辑框有几个用法挺顺手。输入 @ 可以模糊搜项目里的文件,Tab 补全路径,Shift+Enter 换行。想用外部编辑器按 Ctrl+G。要贴图直接 Ctrl+V,或者把图片拖进终端。还有个我觉得挺方便的,输入 !command 能把命令跑掉、把结果发给模型,!!command 则是跑掉但不发给模型。
输入 / 会弹出命令。常用的有这些:
| 命令 | 干嘛的 |
|---|---|
/login /logout |
管提供商的登录 |
/model |
换模型,选的时候按 Ctrl+S 存成默认 |
/thinking |
换思考档位,同样能 Ctrl+S 存默认 |
/settings |
主题、消息投递、传输方式这些设置 |
/resume |
从之前的会话里挑一个继续 |
/new |
开新会话 |
/tree |
跳到会话的任意一点,从那儿接着往下 |
/fork /clone |
从某条消息分叉、或者复制当前分支 |
/compact |
手动压缩上下文 |
/export /import |
导出、导入会话 |
/share |
传成私有 gist,给一个能看的网页链接 |
/hotkeys |
看所有快捷键 |
快捷键里,Ctrl+L 换模型,Shift+Tab 切思考档位,连按两下 Escape 打开 /tree,Ctrl+O 折叠工具输出,Ctrl+T 折叠思考块,连按两下 Ctrl+C 退出。
还有个小细节,pi 支持消息排队。它正在干活的时候,你按 Enter 发的是"引导消息",等它这一轮工具调用跑完就插进去;按 Alt+Enter 发的是"后续消息",得等它彻底干完才发。这个在多轮任务里挺有用,不用干等着。
会话能长成一棵树
这块是 pi 我觉得最好玩的地方。
它的会话存成 JSONL 文件,而且里面的结构是树,每条记录有 id 和 parentId。好处是,你可以在同一个文件里原地分支,不用另开文件。
比如你聊着聊着发现前面某步走歪了,按 /tree 就能把整个会话树调出来,跳到那个点,从那儿重新走下去,两条分支的历史都留着。/fork 是从某条消息分出一个新会话文件,/clone 是把当前分支整个复制一份。
命令行里也能干这些事:
pi -c # 继续最近一次会话
pi -r # 浏览挑一个历史会话
pi --no-session # 临时模式,不保存
pi --name "my task" # 起个名字
pi --fork <path|id> # 从某个会话分叉出来
上下文快满了怎么办?pi 有压缩,叫 compaction。手动是 /compact,自动默认也开着,快满了会自己总结前面的内容。要说明的是这个压缩是有损的,前面的细节会被总结掉,但完整历史还在 JSONL 里,想翻旧账用 /tree 回去看就行。
模型和提供商
pi 支持的提供商不少。订阅类的可以接 Claude Pro/Max、ChatGPT Plus/Pro 的 Codex、还有 GitHub Copilot。API key 类的就更多了,Anthropic、OpenAI、Google、DeepSeek、Mistral、Groq、xAI、OpenRouter、Kimi、MiniMax 一大堆。
换模型就 /model,选中了按 Ctrl+S 能存成默认。命令行里可以用 --list-models 列出来,用 --models 指定一批给 Ctrl+P 循环切换,像我这样经常换模型的人挺方便。
它还内置了 llama.cpp 的路由服务,/login llama.cpp 配上,再用 /llama 下模型、加载模型,本地跑也行。
有意思的是,pi 的提供商列表里居然还有 OpenCode Zen 和 OpenCode Go。也就是说,你可以用 pi 这个客户端,去连 opencode 家的模型服务。
如果你要接的是那种 OpenAI、Anthropic、Google 格式的自定义服务,可以在 ~/.pi/agent/models.json 里加。要是碰到非标准 API 或者要 OAuth,那就得写扩展了。
四件套和包
pi 的定制,主要靠四样东西,官方叫 prompt templates、skills、extensions、themes。
prompt templates 就是把常用提示词存成 Markdown,放到 ~/.pi/agent/prompts/,用的时候输入 /名字 就展开了。
skills 是技能,跟 opencode 用的是同一套 Agent Skills 标准,放在 ~/.pi/agent/skills/ 或者 ~/.agents/skills/。用的话输入 /skill:名字,或者让模型自己按需加载。这点挺省事的——我把同一套技能,同时装给了 opencode 和 pi,两边都能用,不用维护两份。(顺带说一句,pi 也能直接加载 ~/.claude/skills、~/.codex/skills 这些别的工具的技能目录,在 settings 里配上就行。)
extensions 是扩展,用 TypeScript 写。这个是 pi 的重头戏。它能加自定义工具、加命令、加键盘快捷键、拦事件,还能改 UI,甚至连内置工具都能整个换掉。官方示例里连 Doom 都给塞进去了,等模型干活的时候打游戏。前面说的那些"pi 故意不做"的功能——子智能体、计划模式、权限闸门、MCP 支持——理论上都能用扩展自己搭出来。
themes 是主题,改完直接热加载,不用重启。prompt template、skill、extension、theme 这四样,加上包管理,合起来就是 pi packages。可以打包成 npm 包或者 git 仓库分享给别人:
pi install npm:@foo/pi-tools
pi install git:github.com/user/repo
pi list
pi update --all
pi config # 在 TUI 里开关各个包资源
除了交互模式,还能当积木用
pi 不只是个给人用的 TUI,它还有几种程序化的用法。
比如打印模式,跑完就退,适合写脚本:
pi -p "总结一下这个代码库"
cat README.md | pi -p "把这段文字总结一下"
再比如 JSON 模式,所有事件按 JSON 行输出,方便别的程序解析;还有 RPC 模式,走 stdin/stdout,给非 Node 的进程集成用。最后它本身就是个 SDK,可以在自己的 TypeScript 程序里直接把它嵌进去:
import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";
要让它遵守项目里的规矩,就在项目根目录放个 AGENTS.md(或者 CLAUDE.md),pi 启动会自动读。想整个换掉系统提示词,用 .pi/SYSTEM.md。
pi 和 opencode 有啥不一样
说到这儿,可能有人会问,那它跟 opencode 到底选哪个。我先把两边的主要区别摆出来,都是我自己用下来加上看文档整理的。
| 方面 | pi | opencode |
|---|---|---|
| 定位 | 极简内核,自己拼 | 功能齐全,开箱即用 |
| 出身 | Mario Zechner(badlogic) | SST 团队 |
| 子智能体 | 没有,自己搭 | 有,主/子 agent |
| MCP | 没有,写扩展加 | 有 |
| 计划模式 | 没有 | 有 |
| 权限弹窗 | 没有 | 有权限配置 |
| 扩展方式 | TypeScript 扩展 | 插件 + 配置 + 命令 Markdown |
| 会话 | JSONL 树,原地分支 | 会话 + 分享 + 回退 |
| 形态 | 终端 TUI + 库 | TUI + 服务端 + 网页 + 桌面端 |
| 集成 | SDK / RPC / JSON | ACP / MCP / GitHub / serve / attach |
| 技能 | Agent Skills 标准 | Agent Skills 标准 |
差别最大的,我认为是思路。opencode 是"我都给你配好,你直接用",它有子智能体、有 MCP、有权限控制、能起服务端、有网页和桌面端、还跟 GitHub 打通,能 opencode github、opencode pr 直接拉 PR。功能面铺得很宽。你可以把它当成一个完整的开发平台来用。
pi 反过来,它相信"你不想要我强塞的东西"。核心就四个工具,剩下的全靠扩展和包。你不动手,它就是个很小的终端助手;你愿意折腾,它能被改成任何样子,而且不用去 fork 它的源码。
会话这块是 pi 的强项。它的树状会话和原地分支,用起来比一般工具的"线性历史"灵活,尤其是那种试错很多的任务。
隐私和安全上,得说两句实在话。pi 明确没有权限弹窗,官方建议是要么在容器里跑,要么自己用扩展写确认流程。扩展和技能又是能执行任意代码的,第三方包一定要先看看源码再装。opencode 这边至少有权限配置这一层,你可以把危险的 bash 命令设成要确认或者直接拒绝。这两点在取舍上得想清楚。
做了个对照实验,看看谁快
前面说 pi 手感快,这只是感觉,不算数。所以我认真做了一组对照实验,想看看差距到底从哪来。
条件尽量卡平:同一个模型(DeepSeek 的 deepseek-chat,两边都直连官方接口),同一个任务——目录里放一个算平均值的 buggy.py,让它读文件、找 bug、修好、跑一遍,把结果告诉我;每次都在全新的空目录里跑。为了排除干扰,我把 pi 的技能、扩展、上下文文件全关掉,opencode 那边用一个只留 provider 的最小配置,两边各跑 4 次取平均。
这里说的"快",用的是墙钟时间,也就是从敲下回车到它彻底干完,现实中真实等了多久。这个数里包含启动、把提示词发给模型、模型生成,还有它读文件、改文件、跑命令的全过程,跟咱们的体感一致。
结果是这样:
| 指标 | pi | opencode |
|---|---|---|
| 总耗时 | 4.40 秒 | 7.32 秒 |
| 第一轮模型响应 | 0.60 秒 | 4.33 秒 |
| 输入 token | 809 | 6310 |
| 缓存读 token | 6016 | 23936 |
| 输出 token | 289 | 231 |
| 总 token | 7114 | 30477 |
| 工具调用 / 模型回合 | 3 / 4 | 3 / 4 |
| 正确率 | 4/4 | 4/4 |
两边干的活一模一样,都修对了,工具调用和回合数也一样。但你看输出 token,289 对 231,基本是一个量级——说明模型"想"和"说"的量差不多。差的全在输入这一侧:opencode 每一轮背的上下文,差不多是 pi 的 4 倍。
这 4 倍是哪来的?我单独测了一句废话"只回复 ok",不触发任何工具:pi 是 1515 个 token,opencode 是 7333 个。一上来 opencode 就多背了将近 6000 token。原因也不神秘,它的内置工具多(read、edit、write、bash、glob、grep、list、patch、task、todowrite、webfetch 一大堆),每个工具的定义都要发给模型,再加上它内置了好几套 agent 的系统提示词。pi 默认就四个工具,提示词也短。
输出差不多、输入差很多,意味着时间差主要花在"把上下文喂给模型"这一步,也就是预填充和网络传输,而不是模型在思考。
技能装得越多,差距会怎么变
这才是有意思的地方。pi 和 opencode 都遵循同一套 Agent Skills 标准,技能的名字和描述都是常驻在系统提示词里的(正文要按需才读)。那技能一多,两边的差距会不会被拉大?
我用统一规格的技能做了个扫描,还是测一句"ok"的输入 token:
| 技能数 | pi | opencode |
|---|---|---|
| 0 | 1515 | 7333 |
| 10 | 3659 | 9443 |
| 43 | 10490 | 16406 |
| 100 | 22289 | 28433 |
| 200 | 42989 | 49533 |
把它拟合成一条直线,能看出:
- pi:成本 ≈ 1561 + 207 × 技能数
- opencode:成本 ≈ 7333 + 211 × 技能数
关键结论是:每装一个技能,两边增加的开销几乎一样(207 对 211),差距全在起跑线上那个固定的 5800。 技能本身不是差距来源,基线才是。所以技能越多,opencode 的相对劣势反而越小,但绝对差距基本卡在 5800 上下不动。
拿我自己那套 43 个技能来说:pi 一个请求 15051 token,opencode 20256。跑一个 4 轮的编码任务,总 token 是这样:
| 技能数 | pi 总 token | opencode 总 token |
|---|---|---|
| 0 | 7171 | 30541 |
| 43(真实) | 61284 | 82175 |
| 200 | 168290 | 194595 |
这里得划个重点:技能数会把每个任务的 token 成倍放大,因为每一轮都要把完整上下文重发一遍。 43 个技能就把一个 4 轮任务从 7 千 token 顶到了 6 万(pi)。公式大概就是:任务总 token ≈ 回合数 × (基线 + 210 × 技能数)。所以真要省钱,最有效的不是换工具,而是把技能精简掉——这一条对 pi 和 opencode 都成立。
换个模型会变吗
我又用 deepseek-reasoner(带思考的那个)测了一遍。结论是:换模型不改变两边的固定差距。opencode 不管用 chat 还是 reasoner,每个任务都稳定地比 pi 多背两万多 token,正好是 4 轮乘以那个 5800 的基线差。差距是壳带来的常数,不是模型带来的。
启动速度也顺带量了:pi 冷启动约 0.44 秒,opencode 约 0.75 秒。不过真正让 opencode 显慢的,是第一轮那个大上下文,不是这零点几秒。
所以"pi 快一些"这事,拆开看其实很朴素:它省的是那个固定的上下文基线,不是它有什么更快的引擎。 输出和回合数两边一样,说明模型那一侧是同一个东西;差的只是每一轮要背多少包袱。
当然,这个实验也有局限,我得说清楚:样本不大(各 4 次),而且我把两边都调成了最小配置。你真实用起来,opencode 还会加载 agent、规则这些,盘子只会更大;pi 的技能是描述常驻、正文按需,涨得慢一些。数值会变,但"pi 省在固定基线、技能对两边等价"这个结论不会变。
我的一些看法
要我说,这俩不是非要二选一。
如果你想要一个东西,装上就能干活,功能越全越好,团队里还要统一管控权限,那 opencode 更合适。它有子智能体、有 MCP、有权限这一套,拿来就能用。
如果你跟我一样,喜欢把工具拆开看、按自己习惯组装,还经常写点小脚本小扩展,那 pi 会让你觉得很舒服。它内核小,改起来不费劲,出了什么问题也容易看明白。而且它是认真在做"可扩展",不是嘴上说说。
我用下来的感觉是,平时常规的写代码、改代码、跑命令,两个都能干,差别不大。真到了要分支探索、要接一堆自定义流程的时候,pi 的树状会话和扩展能力就显出好处了。反过来,要做那种需要子智能体分工、需要连 MCP 服务、需要团队权限管控的活,opencode 更省心。
还有个我挺喜欢的地方,是这两个工具并不互斥。技能是同一套标准,模型服务也能互相用(pi 能连 opencode 的 Zen/Go),会话也各管各的。完全可以两个都装着,看当天想干什么就用哪个。
最后
说句实在的,pi 这种"故意少做"的工具,一开始会让人有点不习惯,觉得啥都得自己来。但用久了会发现,正是因为它肯把决定权留给你,才没那么多"它以为你需要"的东西。
当然,天下没有免费的午餐。东西越少,你要自己补的就越多;权限没有弹窗,出了事也得自己担着。所以装第三方扩展之前,多看一眼代码,这个习惯一定要有。
想试试的话,官网是 pi.dev,源码在 GitHub 上(earendil-works/pi),npm 包名是 @earendil-works/pi-coding-agent。我这边是 0.85.1,opencode 是 1.18.31,上面说的都是这个版本的实际用法,后面版本要是有变化,以官方文档为准。