🔴 深入

Pi Coding Agent 到底怎么用:一套只给四个工具的编码代理

读完你能亲手把它装起来、接上一个模型、让它在你的项目里改代码,并且知道它的护栏在哪儿、什么时候该换别的工具。

更新于 2026-09-13

本文校对于 @earendil-works/pi-coding-agent @ 0.85.1 · 官方源:pi.dev · github.com/earendil-works/pi

4
模型默认拿到的工具
0.85.1
本文锚定的版本
≥22.19
需要的 Node.js 版本
4
运行形态(交互 / 单发 / RPC / SDK)
🎯 一句话价值主张

Pi 是一个装在终端里的 AI 编码代理——你对着它说话,它自己读文件、改代码、跑命令,直到任务做完。它故意只给模型四把工具,剩下的能力由你按需加。

先记住这三句

📌 三句话速记

① 它出厂只给模型四个工具:read(读文件)、write(写文件)、edit(精准改文件)、bash(执行命令);子代理、Plan 模式、权限弹窗一律不内置。

② 缺的能力不是没有,而是"装"进来:写一份说明文档(Skill)、写一个 TypeScript 模块(扩展)、或从 npm / git 装一个别人打包好的 Pi Package。

③ 它对你完全透明:上下文里放了什么你看得见,每一步工具动作都实时打印;代价是默认没有权限护栏,护栏要你自己搭。

你现在是什么处境,直接跳到哪一节

你现在的状态先去哪一节为什么
完全没装,想知道它值不值得装§01 → §02先弄清"它是什么、什么时候别选它",避免装完发现不合手
已经决定装,机器上可能有 Node§04前置条件、三种安装方式、三步自检都在这一节
装好了,卡在"没有可用模型"§05Key、订阅登录、本地模型、连接问题速查
配好了,想第一次真的让它干活§06 → §07一个最小会话,再走一遍从零搭小工具的完整演练
想把它接进脚本、CI 或自己的程序§08单发模式、JSON 事件流、RPC、SDK 都在这里
用了一阵,想让它稳定、省钱、不出事§14 → §15安全边界的默认值,以及别人踩过的坑
想知道某条命令怎么敲§99命令 / 环境变量 / 键位三张速查表

从零到能干活,只要这几步

1
装 Node.js(≥ 22.19)

Pi 是用 TypeScript 写的、通过 npm 分发。已装过 Node 的话,先跑 node --version 确认版本够新。

2
装 Pi

一条命令:npm install -g --ignore-scripts @earendil-works/pi-coding-agent。装完 pi --version 应该能打印出版本号。

3
给它一个能用的模型

要么设一个 API Key 环境变量,要么用 /login 走订阅账号授权。第一次记得执行 pi update --models 刷新模型目录。

4
进项目目录,说一句话

cd 到你的项目里再敲 pi——它只看得到当前目录。然后像给同事发消息一样描述你要什么。

5
把约定写进 AGENTS.md

命令、目录规范、提交格式这类"每次都一样"的要求写进项目根目录的 AGENTS.md,之后每个会话自动生效。

读完你应该能

01Pi 到底是什么?

它是什么:一句话 + 三个名字

Pi(读音 /paɪ/,命令就是 pi)是一个运行在终端里的极简 AI 编码代理。官方给自己的定位叫 minimal agent harness——字面意思是"极简的代理驱动框架"。

这里有两个词要拆开。第一个是"代理"(agent):它不是聊天机器人,它会动手。第二个是"驱动框架"(harness):它是套在模型外面的那层壳——负责把工具递给模型、把工具的输出塞回给模型、把整个过程记下来。模型负责"想",Pi 负责"让它能动手并且看得见"。

它由 Mario Zechner(网名 badlogic,LibGDX 游戏引擎的作者)和 Earendil 公司开发,MIT 协议开源。官网 pi.dev,源码在 github.com/earendil-works/pi,命令行的 npm 包名是 @earendil-works/pi-coding-agent。

它怎么干活:工具调用循环

你发消息进入上下文
→
模型决策回答,或调工具
→
Pi 执行read / write / edit / bash
→
结果回填输出塞回上下文
→
循环直到它不再调工具

这个循环在行业里叫 工具调用循环(tool-use loop)。它不是 Pi 独有的,几乎所有编码代理都这么跑。差别在于:循环里能用的工具有几个、上下文里被塞进了什么、以及这些事你能不能看见。

💡 为什么这条流水线值得你花两分钟

因为"它为什么自己读起了文件""它为什么跑了一半停下来问我"这类困惑,答案全在这条线上。它读文件,是模型选择调用 read;它停下来,是模型这一轮不再调工具、给出最终回答。

它和 Claude Code 差在哪:不是功能多少,是默认值

最省事的记法是:Claude Code 开箱就把一堆功能装好了;Pi 开箱只有四个工具,缺什么你自己加。

官方 README 的原话是 "Pi ships with powerful defaults but skips features like sub agents and plan mode"——它带着很强的默认值出厂,但主动跳过了子代理和 Plan 模式这类功能。跳过的理由是:与其替你决定工作流,不如让你把它改造成你的形状。

维度Claude Code 这类全家桶Pi对你意味着什么
模型默认拿到的工具一整套内置能力 + 外部工具协议只有 4 个:读、写、改、跑命令Pi 的单轮上下文更短,通常更省 token
缺的功能怎么办官方排期加,你等着你自己加,或者装别人做好的包想要什么形状由你定,但要动手
权限护栏默认弹窗确认默认不弹,以你的身份直接跑Pi 更快,但出事的下限更低
行为可预测性版本升级可能改系统提示和工具集内核小,升级不容易破坏你的工作流长期用下来更"稳",但你要自己维护定制部分
本地 / 自托管模型支持有限Ollama、llama.cpp、任意 OpenAI 兼容端点都能接代码可以不出本机
⚠️ 反过来也成立

极简不等于更好上手。想复现"权限确认、子代理、Plan 模式",你得自己写或装扩展。如果你追求"装上就能用、不想折腾",Claude Code / OpenCode 更省心——这不是 Pi 的缺点,是它的取舍。

名字别搞混:这里的 Pi 指哪一个

Pi 这个字太小,网上至少还有另一个同名项目:一个 Python 写的 pi-agent,用 pip install pi-coding-agent 也能装出一个叫 pi 的命令。两者命令名相同,但互不相干。

本文讲的是官网 pi.dev 对应的这个。判断方法很简单:装完跑 pi --version,能对上 0.85.x 这个系列的才是。

三个最容易混的概念

新手最先误会的往往不是功能,而是"它是哪一层"。这三个区分清楚,后面全篇都好读:

容易混成实际关系为什么这个区分重要
Pi 是一个模型不是。它是套在模型外面的壳。模型由 Anthropic / OpenAI / DeepSeek / 本地 Ollama 提供模型好坏和 Pi 好坏是两件事。换了模型,Pi 的命令、快捷键、会话全不变
Pi 是一个 IDE 插件不是。它活在终端里,对文件系统说话,不依赖任何编辑器你可以把它跑在服务器上、容器里,或者用 tmux 挂后台
Pi 是一个 MCP 客户端默认不是。它刻意不内置 MCP,主张用"带说明文档的 CLI 脚本"替代如果你手上的能力已经有现成 CLI 工具,直接包一层就能用,不必先写 MCP server

02它解决什么问题,什么时候该用它

它解决什么问题

Pi 的作者长期用 Claude Code,后来形容它"变成了一艘 80% 功能他根本用不上的宇宙飞船",而且每次发布都改系统提示和工具集,把他习惯的工作流打断。于是他按自己的需求重写了一个:内核可预测、不偷偷往上下文里塞东西、一切可以检查、会话格式干净、能接本地模型。

✅ 你能掌控上下文
系统提示极短,不搞背着你注入。往上下文里放什么、怎么管理,全在你手上——这直接决定输出质量和花费。
✅ 工作流不被产品定义
官方的说法是"原语,不是功能"(primitives, not features)。不想要 Plan 模式?就不装。想要什么,自己拼。
✅ 支持本地 / 自托管模型
接 Ollama、llama.cpp 或任意 OpenAI 兼容端点,代码可以不出本机,适合隐私敏感的项目。
✅ 通常更省 token
系统提示短、工具少、工具说明精打细算,配合提示缓存,单轮消耗一般比全家桶型代理低。

什么场景该用它

你的处境结论原因 / 替代方案
代码不能出本机(合规、私有仓库)该用接 Ollama 或 llama.cpp 就能全程本地推理,这是它的强项
想严格控制上下文和花费该用系统提示短、不多塞东西,且底部状态栏实时显示缓存命中与成本
团队要沉淀一套统一工作流并一键分发该用把扩展、Skill、提示模板、主题打成一个包,pi install 一条命令装好
要把它嵌进自己的脚本或程序该用单发模式、JSON 事件流、RPC、SDK 四种形态覆盖从 shell 到 Node 应用
只想要"装上就能用、功能齐全"别用Pi 对这类需求是更高的门槛:缺的功能要你自己补,Claude Code / OpenCode 更顺
指望它默认帮你拦住危险操作别用,或先改默认值它没有内置权限弹窗,必须自己用 --tools、容器或权限门扩展兜底
团队完全没人愿意碰配置换个工具更划算Pi 的价值在可改造,用不上这一点就只剩"缺功能"
📖 判断法:你愿不愿意花半小时调工作流

愿意 → Pi 大概率越用越顺手;不愿意 → 那些"缺失的功能"会一直烦你。用同一个项目各跑一次最小任务,二十分钟就能有手感,比看任何评测都准。

03它"刻意不做"什么?

理解 Pi 最快的方式,是看它主动删掉了哪些"标配"。下面每一行都是官方明说"不做"的,最后一列是它建议的替代路径。

别的代理通常内置Pi 的态度你想要时怎么办
MCP(给模型挂外部工具的通用协议)不做用"带 README 的 CLI 脚本 + Bash",也就是 Skill;或写扩展把 MCP server 桥接进来
子代理(sub-agents)不做用 tmux 另开 Pi 实例协作,或写扩展,或装现成包
权限弹窗不做跑在容器里做硬隔离,或用扩展自己做确认流程
Plan 模式不做把计划写进文件,或写扩展
内置待办清单不做用 TODO.md 文件,或写扩展
后台 Bash(后台跑长命令)不做用 tmux——完全可见、可交互
⚠️ 这套减法带来两个后果,都要提前知道

一是内核稳定:工具集小、系统提示短,模型行为可预期,升级不容易打乱你的工作流。二是安全边界默认很松:没有内置权限系统时,Pi 启动后基本等于"以你的身份在跑命令"。想要更硬的边界,就得自己装进容器 / 沙箱,或用扩展加确认门。

四种运行形态,新手只需要先会用第一种

内核只有一个,但 Pi 对外提供四种"怎么用"的形态,覆盖从人机对话到嵌入你自己的程序:

① 交互式(默认)

直接敲 pi,像和同事聊天一样让它干活。日常改 bug、写功能、读仓库都用这个。

② 单发 / JSON

pi -p "问题" 问一次拿答案就退出;--mode json 输出事件流,给别的程序用。

③ RPC

pi --mode rpc,走 stdin/stdout 上的 JSON 协议,非 Node 程序也能集成。

④ SDK

在 Node 应用里 npm 引入,把 Pi 的会话循环嵌进你自己的程序。

04怎么装?三步装完还能自检

0. 前置条件:Node.js ≥ 22.19

Pi 是用 TypeScript 写的,通过 npm 分发,运行环境要求 Node.js 22.19 或更高(这是 npm 上声明的 engines 字段,本文按 0.85.1 核对)。如果你还没装 Node,macOS(Apple Silicon)推荐用 Homebrew:

# 先确认有没有装 Homebrew(macOS 的包管理器)
brew --version

# 没有的话先装 Homebrew(官网脚本,粘贴到终端回车)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 用 Homebrew 安装 Node.js
brew install node

# 验证版本(应 >= 22.19.0)
node --version
⚠️ 有 nvm / mise 的人特别注意

机器上有多套 Node 时,你以为在用的那套和当前 shell 实际用的是哪套可能不一样。装 Pi 之前先跑 node --version,确认输出确实是 ≥ 22.19 的那个。

1. 装 Pi(三选一)

官方提供三种入口。本文推荐 npm 方式——可预测、好升级。注意官方的 --ignore-scripts 不是可选项而是明确要求:Pi 正常安装不需要执行依赖的生命周期脚本,加上更安全。

# 方式 A(推荐):npm 全局安装
npm install -g --ignore-scripts @earendil-works/pi-coding-agent

# 方式 B:官方一键安装脚本(curl 到管道给 sh,介意可不用)
curl -fsSL https://pi.dev/install.sh | sh

# 方式 C:Windows PowerShell 用户
# powershell -c "irm https://pi.dev/install.ps1 | iex"

官网还给了 pnpm add -g --ignore-scripts @earendil-works/pi-coding-agent 和 bun add -g --ignore-scripts @earendil-works/pi-coding-agent 两种等价写法——如果你平时用 pnpm 或 bun,就用你熟的那条。

2. 验证安装

pi --version    # 应显示当前版本号,如 0.85.1
pi --help       # 查看全部参数用法

3. 更新

Pi 每次启动会联网查一次最新版本(可以关,见 §99)。手动升级命令和"第三方包升级"是分开的,别搞混:

pi update            # 只升级 Pi 本身
pi update --models   # 只刷新各提供商的模型目录(推荐装完就执行一次)
pi update --all      # Pi + 所有已安装的第三方包
pi update --self --force   # 强制重装当前版本(用于修复损坏)
💡 装完立刻做一件事

跑一次 pi update --models。它只刷新各家提供商的模型目录,不升级程序——能把"想用的型号显示不出来"这类问题提前消掉。

4. 启动前的三步自检

新手最常见的挫败不是 Pi 不好用,而是环境没到位。花 30 秒过一遍这三件事,能避开大半问题:

1
Node 版本够新吗

跑 node --version,结果必须 ≥ 22.19。装了 nvm / mise 的话,注意当前 shell 用的是哪套。

2
pi 命令在 PATH 里吗

执行 pi --version。若提示 command not found,跑 npm config get prefix 找到全局安装目录,把它的 bin 加进 ~/.zshrc 的 PATH,然后重开终端。

3
至少有一个可用的模型

要么已设好 API Key 环境变量,要么打算用 /login 走订阅账号。先做一次 pi update --models 更保险。

装在哪、想卸干净怎么卸

📖 它把东西放在两个地方

程序本体在 npm 全局目录;所有数据和配置都在 ~/.pi/agent/——会话、设置、扩展、Skill、信任记录、已装包全在里面。

彻底卸载两步:先 npm rm -g @earendil-works/pi-coding-agent,再手动删掉 ~/.pi/agent。删目录会清掉所有会话与配置,动手前确认一遍。

安装问题的三种典型症状

症状多半是什么怎么处理
pi: command not foundnpm 全局 bin 目录不在 PATHnpm config get prefix 找到目录,把它的 /bin 加进 shell 配置
启动报 Node 版本不符当前 shell 用的 Node 太旧切到 ≥ 22.19 的版本,或重装 Node
装完立刻报缺依赖 / 模块找不到用了不带 --ignore-scripts 的装法,或装包中途断网按上面的命令重装一次;仍不行用 pi update --self --force

05怎么接上模型?Key、登录、换模型、本地跑

两种认证方式,先选一种

✅ 方式一:环境变量 API Key(推荐新手)
# 在终端里临时设置(当前窗口有效)
export ANTHROPIC_API_KEY=sk-ant-...

# 然后启动
pi

想永久生效,就把这行 export 写进 ~/.zshrc。谁家的 Key 就认谁家的变量名:OPENAI_API_KEY、GEMINI_API_KEY、DEEPSEEK_API_KEY……

✅ 方式二:/login 用订阅账号授权
pi
/login

有 Anthropic Claude Pro/Max、ChatGPT Plus/Pro、GitHub Copilot 订阅的话,选对应提供商网页授权即可,不用手动填 Key。

它支持哪些提供商

官网首页的表述是"15+ 提供商、数百个模型",而 README 里逐个列出的内置提供商目录已经有三十多个。按 0.85.1 的官方列表,大致可以分成三类:

类别包含哪些适合谁
订阅账号(OAuth)Anthropic Claude Pro/Max · OpenAI ChatGPT Plus/Pro(Codex)· GitHub Copilot已经有这些订阅的人,不用另外买 API 额度
主流云 API KeyAnthropic · OpenAI · Azure OpenAI · Google Gemini · Google Vertex · Amazon Bedrock · DeepSeek · Mistral · Groq · Cerebras · xAI · NVIDIA NIM · Hugging Face · Fireworks · Together AI · Baseten · OpenRouter · Cloudflare(AI Gateway / Workers AI)· Vercel AI Gateway · Ant Ling手里有任意一家的 Key 就能开工
国内 / 编程套餐Kimi For Coding · MiniMax · Xiaomi MiMo(含 Token Plan 三区)· ZAI Coding Plan(全球 / 中国)· OpenCode Zen / Go国内网络环境下更顺,部分按套餐计费
本地 / 自托管Ollama · llama.cpp 路由服务器 · 任意说 OpenAI / Anthropic / Google 方言的自定义端点代码不出本机,或走公司内网网关
💡 为什么值得提 OpenRouter 这类中转

很多国内用户没有 Anthropic / OpenAI 账号,又想用 Claude / GPT 系模型。OpenRouter 是一个聚合 API:一个 Key 能调几十家模型。Pi 把它当普通提供商接入,等于省掉为每家单独申请 Key 的麻烦。同样的逻辑也适用于 Kimi For Coding 这类"编程套餐"。

自定义提供商通过 ~/.pi/agent/models.json 添加——只要对方说 OpenAI / Anthropic / Google 三种方言之一就行。要接完全自定义的 API 或 OAuth,那得写扩展。

在会话里换模型 / 设默认

Pi 很方便的一点是:会话中途随时能换模型,不用重开。

操作说明什么时候用
/model 或 Ctrl+L打开模型选择器,列出可用模型想临时换成更强的模型做难活
选择器里按 Ctrl+S把高亮的模型存为启动默认找到顺手的型号后,以后就直接用它
Ctrl+P / Shift+Ctrl+P在你收藏的模型之间前后循环在"贵而强"和"便宜够用"之间秒切
/thinking 或 Shift+Tab切换思考强度:off / minimal / low / medium / high / xhigh / max简单任务调低省钱,复杂算法题调高
/scoped-models管理哪些模型参与 Ctrl+P 循环收藏列表太长了,清理一下
/login llama.cpp 然后 /llama本地跑 llama.cpp 路由服务器,下载 / 加载模型想完全本地推理

不想先进交互界面也可以,直接带参数启动指定模型:

# 也可以不先进交互界面,直接带参数启动指定模型
pi --provider anthropic --model claude-... "帮我重构这个函数"

# 用 "提供商/模型" 前缀可以省略 --provider
pi --model openai/gpt-... "给这段代码写测试"

# 想加高思考强度(型号后接 :high)
pi --model anthropic/claude-...:high "解一道复杂算法题"

# 查看某提供商有哪些可选模型
pi --list-models anthropic
⚠️ 模型名会变,别把型号写死

上面命令里的 claude-...、gpt-... 是示意。各家型号名随厂商更新,不同提供商可用型号也不同。最稳的做法:进会话后按 Ctrl+L 从列表里挑,或先用 pi --list-models 提供商名 看目录。目录会自动刷新,也能用 pi update --models 立即拉新。

本地 / 私密运行(可选)

想把代码留在本机、或者单纯省 API 费,可以接本地模型:

同时配了多个 Key,怎么指定用谁

你可以把 Anthropic、OpenAI、DeepSeek 的 Key 全设上。Pi 的规则是:

登录 / 连接问题速查

现象多半原因 → 怎么办先看哪里
启动报"没有可用模型 / provider not found"Key 没生效,或模型目录过期检查环境变量名拼写;跑 pi update --models 再试
/login 选完提供商一直转圈网络问题,或订阅授权没走完看报错文案;网页授权类确认浏览器里已完成,再回终端
能聊,但模型"不会用工具"选到了纯对话模型(目录里没标工具能力)换一个目录中标记支持工具调用的模型
429 / 5xx 报错被限流,或服务端抖动Pi 默认会自动退避重试;等一会儿或换模型 / 换提供商
换模型后回答风格突变不同模型的脾气本来就不同,属正常弱模型做粗活、强模型做难活,按任务切
💡 一句话

连接问题八成出在三处:环境变量名、模型目录没刷新、选了不支持工具的模型。挨个排查基本都能解决。

06最小例子:第一次让它干活

假设你已经装好并配好 Key。第一件事:先进入你打算让它干活的项目目录。Pi 只看得到当前目录(它把这个目录叫工作区),会话也默认按目录分开存。

cd ~/Desktop/my-demo-project   # 换成你的项目目录
pi                            # 启动交互式界面

然后像给同事发消息一样,直接敲任务。第一句先让它摸底:

这个目录里有什么?帮我看看结构。

它调用 bash 里的 ls、read 等工具探索目录,然后总结每个文件是干嘛的。注意你会看到每一步的原始输出,而不是只有结论。

第二句才是真正的活:

在 demo.py 里加一个函数 hello(name),返回 "Hello, " + name,然后跑一下验证。

跑到一半想插话,有两种插法

比如你觉得它想复杂了:

先别加参数校验,保持简单。

按 Enter 发送,这是转向消息:它执行完当前工具后立刻送达,并打断剩下的动作。按 Alt+Enter 则是追问:排在队尾,等它把这一轮全部干完才送。选错的话,要么打断了它,要么白等半天。

让 Pi 一次看懂更多:@ 引用文件

在输入框里打 @ 会弹出项目文件的模糊搜索,选中就把该文件内容放进本次消息——等价于"把这份文件也看进去":

@src/utils.ts 帮我看下这个文件里的格式化函数有没有 bug

命令行里也一样,可以在参数位置直接写 @文件。想让它一次性看两份文件再对比,就用两个 @:

pi @src/foo.ts @src/bar.ts "Review these two files"

想贴图片:交互界面里 Ctrl+V 粘贴,或直接把图片文件拖进终端;单发模式下用 pi -p @screenshot.png "What's in this image?"。

📌 这个例子里的三句话

① 让它干活前先 cd 进目标目录;② 它每一步工具动作都会实时显示在界面上,不放心就盯着看;③ 想中途纠正,直接按 Enter 插话,不用等它做完。

把这次会话起个名字

一行命令问完就走、还想以后能翻到它,用单发模式加个名字:

pi --name "release audit" -p "Audit this repository"

会话默认存在按目录分类的文件夹里,所以名字起得清楚,找起来省事。会话的完整玩法(树、分叉、压缩、导出)在 §10。

07完整演练:从零搭一个待办清单小工具

下面这场对话你可以照着在自己的空目录里跑一遍,体会"从想法到能跑"的全过程。每一句后括号里是 Pi 大概会做的事——你只需要发左边那句话,然后看它表演。

1
先圈定地盘,再说目标
mkdir ~/Desktop/todo-demo && cd ~/Desktop/todo-demo && pi
做一个命令行待办清单工具 todo.py:支持 add "事项" 添加、list 列出、done 序号 标记完成。数据存在同目录 todos.json。

Pi 会先看目录(空的),然后写 todo.py、建好数据结构,并主动把文件内容贴给你看。

2
让它跑起来并自测
跑一下试试:添加两条,列出来,再完成第一条,确认输出和 todos.json 都正常。

它会用 bash 执行 python3 todo.py add ... 这类命令,把输出和报错一并处理,直到自测通过。这一步你能直观看到工具循环:写文件 → 跑命令 → 看结果 → 修 → 再跑。

3
迭代加需求
再加一个子命令 clear,一键清空已完成的事项。

此时它已"记得"刚才的代码,直接 read 现文件 → edit 加函数 → 跑一遍验证。改坏了大不了 Escape 中止,或用 !git diff 自己看一眼。

4
收尾:把玩法写进 README
写个 README.md,把每个子命令的用法列清楚。

从这场演练里能学到的三件事

🎯 核心要点

① 把"目标 → 验证 → 迭代 → 文档"拆成几句喂给它,比一句超长要求效果好得多;② 每一步都实打实跑了命令验证——Pi 是执行者,你才是验收者;③ 中途任何不满都可以按 Enter 插话纠正,不必等它全做完。

为什么"先圈地盘"和"先验证"是硬要求

做法不这么做会怎样原因
先 cd 进项目再启动它可能"找不到文件",或改到别的项目里Pi 的视野就是启动时的当前目录
要求它跑一遍验证代码看起来对,跑起来报错,你还得自己去查模型的自我判断不可靠,命令输出才是证据
把大目标拆成几句话它一次性猜太多,方向偏了你才发现每次只加一层约束,偏了当场就能纠正
改完写进 README三天后你自己也忘了有哪些子命令文档是给下一个读这段代码的人看的,包括未来的你

08四种运行形态与常用 CLI:什么时候用哪个

形态总览

形态怎么进适合场景不适合
交互式(默认)直接 pi人机对话、边看边改,日常主力塞进脚本或 CI
Print 单发pi -p "问题"一句话问答,或脚本里跑一次就退出;会读管道输入需要连续多轮修改的任务
JSON 事件流pi --mode json要结构化结果给别的程序消费人自己看(读起来很累)
RPCpi --mode rpc非 Node 程序通过 stdin/stdout 集成只想问一句话
SDK 嵌入npm 引入包把 Pi 的会话循环嵌进你自己的 Node 应用不写代码的人

最常用的单发用法(print 模式)

不想进交互界面,问一次拿结果就走——非常适合作 shell 脚本或快捷命令:

# 一句话问答
pi -p "总结这个 README 的要点"

# 用 -- 让以横杠开头的内容不被当成参数
pi -p -- "- 用三点概括这个仓库"

# 把文件内容通过管道喂给它(print 模式会自动读 stdin)
cat README.md | pi -p "Summarize this text"

# 把文件作为消息的一部分(@ 前缀)
pi @prompt.md "按这个要求写代码"
pi @src/foo.ts @src/bar.ts "Review these two files"

# 附带截图问"图里有什么"(-p 单发 + 图片 @)
pi -p @screenshot.png "What's in this image?"

# 命名一次性会话(好找历史)
pi --name "release audit" -p "Audit this repository"

常用命令行参数

下面这张表按用途分组,名字和取值都按 0.85.1 的 pi --help 核对过。

参数作用什么时候用
--provider <名> / --model <名>指定提供商 / 模型一个 Key 想指定型号;provider/model 前缀可合并成一个参数
--thinking <级别>思考强度:off / minimal / low / medium / high / xhigh / max简单任务省 token,难题换更强的思考
--api-key <key>直接传 Key,覆盖环境变量脚本里临时换账号;注意别写进会公开的地方
--models <模式>逗号分隔的模型模式,圈定 Ctrl+P 循环范围经常在几个固定模型间切换
--list-models [搜索]列出可用模型型号名记不住时先查目录
-c / --continue接着最近一次会话继续干昨天没做完,今天继续
-r / --resume浏览并挑一个历史会话继续想回到几天前那个会话
--session <路径或 ID>指定用某个会话文件 / 部分 UUID拿到了具体 ID,想精确续跑
--fork <路径或 ID>把某个会话分叉成新会话(旧的不动)想从某个旧会话另起一条实验线
--session-dir <目录>自定义会话存储目录想把不同项目的会话分开归档
--no-session临时模式:不保存任何会话跑一次性验证,不想留垃圾
--name <名> / -n启动时给会话起个名会话多了以后好找
--tools read,ls,find,grep / -t只允许列出的工具最简单的"只读安全模式"
--exclude-tools <名> / -xt禁用某个工具,其余保留只想关掉一个碍事的工具
--no-builtin-tools / -nbt关掉全部内置工具,保留扩展工具你有一整套自定义工具替代内置的
--no-tools / -nt关掉所有工具(纯问答)只想问知识,不想它碰文件
-e ./my-ext.ts / --no-extensions临时加载某个扩展 / 禁用扩展发现调试自己写的扩展
--skill <路径> / --no-skills临时加载技能 / 禁用技能发现试一个新 Skill,不想动全局配置
--no-context-files / -nc不加载 AGENTS.md / CLAUDE.md怀疑项目指令文件在捣乱,想对照一次
--system-prompt / --append-system-prompt本次运行替换 / 追加系统提示(不改文件)临时改行为做实验
-a / --approve、-na / --no-approve本次运行临时信任 / 忽略项目本地设置非交互模式下跳过信任提问
--tui-mode fullscreen实验性的全屏界面想要更大的消息区
--offline / PI_OFFLINE=1关掉全部启动联网操作在意隐私,或网络不通
-v / -h版本 / 帮助随时查
💡 别背参数表

日常九成时间你只用到五样:pi、/model、Ctrl+L、@文件、以及单发的 pi -p。参数表留着当字典查就行。

默认内置工具与"只读"用法

默认给模型的是四个:read(读文件)、write(写文件)、edit(精准改文件)、bash(执行命令;Windows 上另有 powershell)。另外还有 grep、find、ls 三个只读工具,默认不启用,需要用 --tools 打开。

❌ 让模型随意跑命令(默认)
pi -p "这个仓库结构怎么样?顺便跑一下测试"

它可能执行 bash 跑测试——这是在你机器上真实发生的副作用。

✅ 只读审查模式(推荐给"只看不改")
pi --tools read,grep,find,ls -p "Review the code for bugs"

只准读、搜、列目录,不碰文件、不跑命令,审查类任务很安心。

SDK 与 RPC:给想写程序的人的两扇门

前三种形态都是"Pi 是主角、你在旁边用"。想把 Pi 的能力嵌进自己的程序(内部助手、批处理工具),用后两种:

SDK:在 Node 里直接调用
import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";

const modelRuntime = await ModelRuntime.create();
const { session } = await createAgentSession({
  sessionManager: SessionManager.inMemory(),
  modelRuntime,
});

await session.prompt("当前目录下有哪些文件?");

注意 SessionManager.inMemory()——会话只活在内存里,跑完就没了,适合当工具函数用。

RPC:非 Node 也能接

启动方式:

pi --mode rpc

协议文档在官方仓库的 packages/coding-agent/docs/rpc.md。

⚠️ 写 RPC 客户端时的一个真坑

RPC 走严格的 LF 分隔 JSONL:客户端只能按 \\n 切记录。官方特别提醒别用 Node 的 readline 这类通用按行读的库——它们会把 JSON 载荷里的 Unicode 分隔符也当换行拆开,你的解析就乱了。

子进程怎么知道"自己在 Pi 里"

Pi 启动 CLI / RPC 时会给子进程注入两个标记:AI_AGENT=pi 和 PI_CODING_AGENT=true——通用工具据此识别"我正在被 AI 代理调用"。跑 shell 工具时还会带上当前会话元数据(PI_SESSION_ID、PI_MODEL、PI_PROVIDER、PI_REASONING_LEVEL 等),你写的脚本可以按需读取。

09界面从上到下是什么,快捷键记哪几个

界面从上到下

区域内容你该看什么
启动头部快捷键提示(/hotkeys)、已加载的 AGENTS.md、提示模板、Skills、扩展的数量数量对不对——你以为加载了的东西,真的加载了吗
消息区你的消息、模型回复、工具调用与结果、通知、错误、扩展画的界面工具动作的原始输出;它写文件前你都能看到
输入框(编辑器)你打字的地方;边框颜色表示当前思考强度,流式输出时有活动指示边框颜色是否变深——别用着最强思考干粗活
底部状态栏当前目录、会话名、token 用量与成本、上下文占用、当前模型token 突然暴涨说明历史太长,该压缩了

一段典型会话在界面里大概长这样(简化示意):

┌────────────────────────────────────────────────────────────┐
│ ⌘ 快捷键: /hotkeys · AGENTS: 1 · 模板: 2 · skills: 3       │ ← 启动头部
├────────────────────────────────────────────────────────────┤
│ 你: 帮我看看 src/utils.ts 的格式化函数有没有 bug            │
│ Pi: 我先读一下这个文件…  [调用 read]                       │
│    ┌─ 工具输出 ────────────────────────────────────┐       │
│    │ (文件内容)                                     │       │
│    └────────────────────────────────────────────────┘       │ ← 消息区
│ Pi: 找到一个问题:第 12 行缺判空,我准备改一下…            │
├────────────────────────────────────────────────────────────┤
│ > _                      边框颜色=思考强度 · 流式指示灯     │ ← 输入框
├────────────────────────────────────────────────────────────┤
│ ~/demo · todo-demo · ↑1.2k ↓3.4k R2.0k W0 CH91% · $0.012   │ ← 底部状态栏
└────────────────────────────────────────────────────────────┘

输入框里的六个小技巧

操作作用什么时候特别有用
@模糊搜索项目文件,选中即把文件内容加进消息想让它只看某个文件,而不是整个仓库
Tab补全路径路径很深,懒得打
Shift+Enter多行输入(Windows Terminal 用 Ctrl+Enter)要贴一段多行的需求说明
Ctrl+G打开外部编辑器写长内容(用 $VISUAL / $EDITOR)要写一整段规范,不想在小输入框里挤
Ctrl+V / 拖图粘贴图片或文本,或直接把图片拖进终端让它看一张报错截图
!命令 / !!命令执行一条 shell 命令;! 把输出发给模型,!! 不发给模型自己想先看一眼 git diff,又不想让模型读到

斜杠命令:打 / 就会列出来

扩展可以注册自定义命令,Skill 以 /skill:名字 调用,提示模板用 /模板名 展开。内置的常用命令:

命令作用用它的时机
/login · /logout管理提供商登录 / 退出第一次配模型,或换个账号
/model · /thinking切模型 / 切思考强度(选择器里 Ctrl+S 存默认)任务变难或变简单了
/scoped-models设置哪些模型参与 Ctrl+P 快速循环收藏夹太乱
/settings改主题、消息投递方式等偏好想调界面或行为默认值
/resume · /new · /name续上次会话 / 开新会话 / 给会话起名切换任务
/session看当前会话详情:文件、ID、消息数、token、成本想知道会话 ID,好之后精确续跑
/tree回到会话树里任意节点继续,或切换分支想从某个岔路口换方案
/fork · /clone从某条历史消息另起新会话 / 复制当前分支为新会话想拎出一条实验线
/compact手动压缩上下文(把旧消息总结掉)底部 token 涨得太快
/export · /import · /share导出 HTML / JSONL · 导入续跑 · 传到 GitHub gist 拿分享链接存档、交接、给别人看
/copy复制上一条模型回复到剪贴板要把答案贴到别处
/reload热重载:键位、扩展、Skills、提示模板、主题、上下文文件改完文件没生效时
/trust保存对当前项目的"信任"决定不想每次启动都被问(需重启生效)
/llama下载、加载、卸载 llama.cpp 路由模型用本地模型
/hotkeys · /changelog看全部快捷键 / 版本历史查你记不住的那个键
/quit退出—

高频快捷键

按键作用备注
Ctrl+C清空输入框连按两次退出
Escape取消 / 中止当前运行连按两次打开 /tree
Enter / Alt+Enter(运行中)发送转向消息 / 排队追问区别见下文
Alt+Up把已排队等待的消息撤回输入框排错了想改
Ctrl+L打开模型选择器选好后 Ctrl+S 存默认
Ctrl+P / Shift+Ctrl+P在收藏模型间循环(前 / 后)配合 /scoped-models
Shift+Tab循环切换思考强度比进选择器快
Ctrl+O折叠 / 展开工具输出输出太长时
Ctrl+T折叠 / 展开"思考块"只想看结论时
Ctrl+X复制上一条模型回复 / 复制选中的文本—

消息队列:边跑边插话

Enter(转向)

插到队伍最前,等它执行完当前工具就送达,并打断剩余工具动作。适合"方向不对,赶紧纠正"。

Alt+Enter(追问)

排在最后,等它把当前一轮全部干完才送。适合"做完这个,再帮我做下一个"。

Escape 中止当前运行并把排队消息退回输入框,方便你改。行为可在 /settings 里调:steeringMode / followUpMode 默认 "one-at-a-time"(发一条等一条),可改成 "all"(攒着一起发)。

⚠️ Windows Terminal 的 Alt+Enter 冲突

Windows Terminal 默认把 Alt+Enter 当全屏快捷键。要在终端设置里改键,Pi 才有机会收到"追问"这个操作。

学会读底部状态栏(省钱的第一步)

字段含义新手怎么看
工作目录当前 Pi 的工作区确认没跑错目录
会话名当前会话标识用 /name 起个名,日后好找
↑ 输入 / ↓ 输出本轮累计的输入 / 输出 token某轮突然很大 = 历史太长,该压缩或开新会话
R / W提示缓存读取 / 写入量W 大说明缓存被重建(比如你改过系统提示)
CH最近一次缓存命中率高 = 省钱;长期偏低可考虑把约定写进 AGENTS.md 而不是每次复述
成本 / 上下文占比花费,以及上下文窗口用了多少上下文逼近上限时主动 /compact
当前模型现在用的是哪个型号确认没在用贵模型干粗活

/settings 里可以调什么

常用偏好都在 /settings 面板里改,改动写进 settings.json(全局 ~/.pi/agent/settings.json,项目级 .pi/settings.json 可覆盖):

进阶用户可以直接编辑 JSON 加更多键(完整选项表见官方 docs/settings.md)。项目级设置里写路径、资源时,只有"你信任了该项目"之后它才会被加载——这一点在 §14 细讲。

10会话怎么管:树、分叉、压缩、导出

会话存在哪、长什么样

每次会话自动保存成一条 JSONL 文件(每行一条记录),存在 ~/.pi/agent/sessions/,按工作目录分文件夹。文件内部是树结构:每条记录有 id 和 parentId。这意味着"反悔回到岔路口再走另一条路"不需要另存文件。

# 会话相关的 CLI
pi -c                    # 继续最近一次会话
pi -r                    # 浏览并挑一个历史会话
pi --no-session          # 临时模式:这次不存
pi --name "我的任务"      # 启动时给会话起个名
pi --session <路径或ID>  # 指定用某个会话文件
pi --fork <路径或ID>     # 把某个会话分叉成新会话

会话树:回到任意节点重新来

把会话当作一棵树:你在每个岔路口(某条消息之后)都可能走过不同的路。用 /tree 上下选择任意历史节点,从这个节点继续,或在不同分支间切换。所有分支都在同一个文件里,历史不丢。

操作作用什么时候用
输入关键词搜索历史消息记得它说过某句话,想找回来
Ctrl+← / Ctrl+→(或 Alt)在分支间跳两条岔路之间来回比较
← / →翻页历史很长
Ctrl+O切换过滤:默认 → 只看用户消息 → 只看带标签的 → 全部只想看自己说过什么
Ctrl+X复制选中的消息把结论搬走
Shift+L / Shift+T给节点打标签当书签 / 显示隐藏标签时间戳给关键节点做记号

另外两个快捷方式是"把某条思路单独拎出来继续":/fork 从某条历史消息另起新会话;/clone 把当前分支复制成新会话。做实验性改动时很有用——改坏了主线还在。

📖 一个小限制

压缩或另一次树导航还在跑的时候,导航不能开始——等它结束再试。选点的时候如果模型正在回复,选中会取消那次回复。

上下文压缩(compaction)

会话长了会顶到模型的上下文上限。Pi 的处理办法是把较早的消息总结成摘要、保留较新的,腾出空间继续聊:

⚠️ 压缩是有损的

压缩等于"旧细节被归纳",次要信息可能丢掉。好消息是完整原始历史一直在 JSONL 文件里,必要时用 /tree 翻回去看。想控制压缩策略(按主题总结、换不同模型总结),可以通过扩展自定义。

导出、分享、继续

命令作用注意
/export 文件名.html导出成可浏览的 HTML适合发给人看、存档
/export 文件名.jsonl · /import 文件导出原始 JSONL / 从 JSONL 导入并继续跑跨机器搬会话用这个
/share上传为私有 GitHub gist,得到可渲染的分享链接先脱敏
pi --export 输入 [输出]命令行直接导出会话为 HTML批量归档时省事

会话文件长什么样(一瞥)

想理解"为什么能回退、能分支",瞄一眼 JSONL 就懂了。每行一条记录,靠 id / parentId 串成一棵树(字段为示意,结构以官方 docs/session-format.md 为准):

{"id":"m1","parentId":null,"role":"user","content":"列一下文件"}
{"id":"m2","parentId":"m1","role":"assistant","content":"我用 ls 看看","toolCalls":["ls"]}
{"id":"m3","parentId":"m2","role":"tool","name":"bash","output":"a.py  b.py  README.md"}
{"id":"m4","parentId":"m2","role":"assistant","content":"目录里有三个文件…"}   ← m2 下另一条路 = 一个分支

留意最后一条:它在 m2 下面"另起炉灶",就是你在 /tree 里看到的分叉。好处是原始记录永远在文件里——哪怕上下文被压缩成了摘要,翻文件仍能找回当时细节。所以别乱改或乱删 sessions 文件。

想知道当前会话 ID,用 /session;拿到 ID 后可以在命令行 pi --session 该ID 精确续跑,或 pi --fork 该ID 分叉。

会话会占多少空间,怎么清理

📖 顺带一提:官方鼓励开源会话分享

Pi 团队鼓励开源贡献者把会话脱敏后公开分享(用于改进模型与评测),并提供了配套工具与公开数据集。你自己用则要注意会话里可能含密钥 / 隐私,/export 和 /share 之前务必清理。

11Skills:怎么给 Pi 加一项新能力(不写代码)

Skill 是什么

一个 Skill(技能)就是一个目录,里面放一份 SKILL.md,用来说明这个能力"何时用、怎么用、注意什么",另外可以带若干脚本或文件。Pi 遵循通用的 Agent Skills 标准(agentskills.io)。

关键在于它不会把每个 Skill 都塞进上下文,而是按相关性按需加载。官网把这叫"渐进式披露而不击穿提示缓存"——既给了模型能力,又不白白烧 token。

💡 作者的核心主张:用 Skill 替代很多 MCP

与其为浏览器、数据库各配一个沉重的 MCP server,不如写一个"带清晰 README 的小 CLI 脚本"放进 Skill,让模型用 bash 去调它——占用上下文少、可组合、好扩展。这条理念贯穿 Pi 的整个设计。你会写一点脚本的话,"加能力"主要就是"写脚本 + 写说明"。

一个最小 Skill 长这样

# ~/.pi/agent/skills/my-skill/SKILL.md
# My Skill
当用户要求处理 X 类事情时使用本技能。

## 步骤
1. 先做这件事
2. 再做那件事

放哪、怎么分享

技能按"项目 < 全局 < 打包"分布,Pi 会逐层找:

# 命令行可临时指定技能目录 / 禁用技能发现
pi --skill ./my-skill-dir "..."
pi --no-skills "只用默认能力"

一个可直接复制的完整例子

假设你想让 Pi 学会"按你们团队的清单做发布前检查"。建一个 Skill 目录:

# 项目级:放进 .pi/skills/deploy-check/(从当前项目往上逐级都能识别)
# 全局级:放进 ~/.pi/agent/skills/deploy-check/

deploy-check/
├── SKILL.md        # 给模型看的"何时用、怎么用"
└── preflight.sh    # 实际干活的脚本

两份文件的内容分别是:

# SKILL.md
# 发布前检查(deploy-check)
当用户要求"发布 / 上线前检查"时使用本技能。

## 步骤
1. 读 preflight.sh,先跑一遍;任何一步失败都停下来报告,不要继续。
2. 逐条给用户列出 通过 / 失败 及失败原因。
3. 只有全部通过,才允许用户执行 git push / 部署命令。
# preflight.sh
#!/usr/bin/env bash
# 示例:三条检查,都通过才返回 0
set -e
echo "1) 语法检查:pnpm tsc --noEmit"
pnpm tsc --noEmit
echo "2) 测试:pnpm test"
pnpm test
echo "3) 无未提交改动:git status --porcelain 应为空"
[ -z "$(git status --porcelain)" ] || { echo "还有未提交改动,先提交或 stash"; exit 1; }
echo "全部通过 ✔"

用法:在会话里发"帮我做发布前检查",Pi 命中 Skill 描述后自动加载 SKILL.md,按指示执行 bash preflight.sh,并把结果逐条汇报给你。

💡 SKILL.md 里的约束就是你对模型的编程

"任何一步失败都停下来报告,不要继续"这句话,比你在对话里临时叮嘱十遍都可靠——它是写死在文档里的。改完 Skill 记得 /reload。

复用你已有的脚本

你已经有的检查脚本、一键部署脚本,包一层 SKILL.md 就是 Skill。很多"给 Pi 加能力"的需求,本质都是"把已有命令行工具用文档喂给它"。

12上下文工程:AGENTS.md、SYSTEM.md 与提示模板

Pi 官方把"控制什么进上下文"称为 上下文工程(context engineering)。这是它跟全家桶型代理最大的区别点:系统提示极短、注入内容全部可见可管。这一节讲四个控制入口和一张路径表。

AGENTS.md:项目指令,最值得先写的一个

启动时 Pi 会从三处拼接项目级指令文件(等价于 Claude Code 的 CLAUDE.md):

# 项目根目录 AGENTS.md 示例
# 项目约定
- 用 pnpm 装依赖;命令统一 `pnpm run dev` 起本地服务
- 代码注释写中文,变量名/函数名用英文
- 提交信息按 Conventional Commits:feat: / fix: / docs:
- 测试放在 test/ 目录,改动后必须跑 `pnpm test`

细节:若某目录存在 AGENTS.override.md,Pi 会用它替代该目录下的 AGENTS.md / CLAUDE.md(其余目录的仍然拼接)。想整条关掉上下文文件,用 --no-context-files(-nc)。

💡 写 AGENTS.md 的黄金法则

只写"换个人来也会照做"的硬约定(命令、目录、规范),别写空话。它是你驯服模型行为最直接、最省 token 的手段——比每次对话都叮嘱一遍高效得多。

SYSTEM.md:替换 / 追加系统提示

Pi 内置一个极简系统提示,这是它省 token 的来源之一。你可以按项目覆盖:

文件效果什么时候用
.pi/SYSTEM.md(项目)或 ~/.pi/agent/SYSTEM.md(全局)整体替换默认系统提示你已经很清楚它的默认行为,想完全换一套
APPEND_SYSTEM.md追加到默认提示后面新手推荐从这个起步:只加约束,不删原有能力
⚠️ 别轻易整体替换

系统提示决定了模型"如何当一个编码代理"——怎么用工具、怎么收尾。把它清空或换掉,模型可能就不知道怎么用工具了。想调教行为,优先用 AGENTS.md 和 APPEND_SYSTEM.md。

提示模板:把常用需求存成斜杠命令

把"经常重复的一整段要求"存成一个 Markdown 文件,之后在输入框打 /模板名 一键展开。模板支持 {{变量名}} 占位:

<!-- ~/.pi/agent/prompts/review.md -->
Review this code for bugs, security issues, and performance problems.
Focus on: {{focus}}
# 使用时
/review          # 展开模板,把 {{focus}} 替换成你想聚焦的内容再回车

动态上下文:扩展注入、RAG、长期记忆

对进阶用户,扩展可以在每轮对话前注入消息、过滤历史、实现检索增强(RAG)甚至长期记忆。也就是说,"Pi 记不记得上个礼拜的事"不是内置功能,而是可以自己用扩展做出来的东西——这正是"原语而非功能"哲学的落点。

配置与数据都在哪:一张路径表

想备份、迁移或排查,先知道东西放哪。Pi 的"地盘"以 ~/.pi/agent/ 为根(可用环境变量 PI_CODING_AGENT_DIR 改),项目级则用 .pi/:

路径(全局)项目级放什么 / 什么时候看它
~/.pi/agent/settings.json.pi/settings.json偏好设置(项目级覆盖全局)
~/.pi/agent/AGENTS.mdAGENTS.md / .pi/AGENTS.md项目指令,自动拼接进上下文
~/.pi/agent/SYSTEM.md.pi/SYSTEM.md替换 / 追加系统提示(另认 APPEND_SYSTEM.md)
~/.pi/agent/sessions/—会话 JSONL,按工作目录分文件夹
~/.pi/agent/extensions/.pi/extensions/你的 TypeScript 扩展
~/.pi/agent/skills/.pi/skills/ 等技能目录(也可放 .agents/skills/)
~/.pi/agent/prompts/.pi/prompts/提示模板,/名字 展开
~/.pi/agent/themes/.pi/themes/主题(dark / light 之外可自加)
~/.pi/agent/npm/ · git/.pi/npm/ · .pi/git/安装的第三方 Pi 包
~/.pi/agent/models.json—自定义"说兼容方言"的提供商 / 模型
~/.pi/agent/trust.json—你信任过哪些项目的记录
~/.pi/agent/keybindings.json—自定义快捷键

整体备份 = 复制 ~/.pi/agent/;换机器恢复时,重装 Pi 再把这个目录放回去即可(~/.agents/skills/ 这类系统级位置也常一起搬)。

13扩展系统:把 Pi 变成"你自己的"

一个扩展就是一个 TypeScript 模块

扩展是给 Pi 加"新器官"的正规方式:可以注册自定义工具(让模型能调用)、斜杠命令、键盘快捷键、订阅生命周期事件,甚至画整块界面。骨架如下:

// ~/.pi/agent/extensions/my-ext.ts  或  .pi/extensions/my-ext.ts
export default function (pi: ExtensionAPI) {
  // 给模型加一个能调用的新工具
  pi.registerTool({ name: "deploy", description: "部署到测试环境", ... });

  // 给自己加一个 /命令
  pi.registerCommand("stats", { ... });

  // 监听事件,比如每次工具调用后做点事
  pi.on("tool_call", async (event, ctx) => { ... });
}

默认导出也可以写成 async——Pi 会等异步初始化完成再继续启动。适合"启动时联网拉一次远程模型列表,再注册提供商"这种一次性初始化。

能做出什么(官方列举)

🧩 子代理 & Plan 模式
官方"不做"的,扩展都能做出来,官方示例里就有现成参考。
🛡️ 权限门 / 路径保护
比如"写文件前先问我""严禁碰 .env"。官方有 permission-gate、protected-paths 示例。
🔒 沙箱 / SSH 执行
把命令丢进容器跑,或在远程机上跑——官方有 sandbox、ssh 示例。
📎 MCP 接入
想要 MCP?写个扩展把 MCP server 的工具桥接进来。
🎨 自定义界面 / 状态栏
自定义编辑器、状态行、页头页脚、浮层——把 Pi 改成你喜欢的样子。
🧠 自定义压缩 / 摘要
按主题压缩上下文、换更强模型做总结,替换默认压缩策略。

改完热生效

写好或改好扩展、Skill、提示模板、主题后,不用重启:在会话里执行 /reload 即可重新加载。放扩展的目录:全局 ~/.pi/agent/extensions/、项目级 .pi/extensions/,或打进包。

打包分享:Pi Package

把自己攒的扩展、Skills、提示模板、主题一起打包成一个 Pi 包,别人(或团队)一条命令装好:

# 安装第三方包(来源:npm 或 git)
pi install npm:@foo/pi-tools
pi install npm:@foo/pi-tools@1.2.3      # 锁版本
pi install git:github.com/user/repo@v1   # 锁 tag / commit
pi install https://github.com/user/repo

# 管理
pi list                # 看装了哪些包
pi update --all        # Pi + 包一起更新
pi update npm:@foo/pi-tools   # 只更新某个包
pi remove npm:@foo/pi-tools    # 卸载
pi config              # 启用 / 禁用某个包里的资源
# 想只装进当前项目,加 -l(项目级)

包本身就是一个带 package.json 的仓库,通过 pi 字段声明要暴露的目录;没声明时,Pi 会自动识别约定的 extensions/、skills/、prompts/、themes/ 目录:

{
  "name": "my-pi-package",
  "keywords": ["pi-package"],
  "pi": {
    "extensions": ["./extensions"],
    "skills": ["./skills"],
    "prompts": ["./prompts"],
    "themes": ["./themes"]
  }
}
🚫 安全红线:装包 = 信任源码

官方文档的原话警示:Pi 包以完全的系统权限运行——扩展执行任意代码,Skill 可以引导模型执行任何动作(包括运行可执行文件)。所以装第三方包前务必先读它的源码,只装可信来源。

动手试:让 Pi 自己写你的第一个扩展

扩展不是只能你自己写——这是 Pi 很妙的一点:你可以让 Pi 写扩展给 Pi 用。流程通常是:

1
用大白话描述你要的"器官"

例:"写一个扩展,注册一个工具 call_api,让模型能调用我内网 http://127.0.0.1:9000/api 的只读接口;请求前把参数打日志。"

2
让它写文件,你审一眼再 /reload

Pi 会产出 extensions/xxx.ts 之类的文件。你通读一遍(尤其确认没有可疑的删改命令),然后 /reload,再用一句话验证:"用 call_api 拉一下 /health。"

3
把用得好的东西打包装包

在项目里建好 package.json 声明 pi 字段指向 extensions/ 目录,推到 git,以后 pi install git:... 一键复用。

⚠️ 写扩展时的三条纪律

① 扩展运行在你的完整权限下,写的每一行都可能被执行——别闭眼信代码,尤其第三方示例;② 扩展里的 API Key / 内网地址别写死进要分享的包,用环境变量;③ 一个扩展只干一件事,命名清晰,方便别人 review 与复用。

扩展 vs Skill:怎么选

维度SkillExtension(扩展)
本质文档(SKILL.md)+ 脚本,喂给模型的"说明书"TypeScript 模块,在 Pi 进程里真实跑的代码
需要什么能力会写脚本 + 写说明即可要会一点 TypeScript,或愿意让 Pi 代写
给模型加工具让模型用 bash 调你的脚本注册真正的结构化工具(可带参数 schema)
给"人/界面"加东西不行能:斜杠命令、快捷键、界面、事件监听
推荐起点大多数"加能力"需求先试它需要界面 / 事件 / 结构化工具时再上
💡 选型口诀

先想 Skill 够不够:够,就别上扩展(少写代码、好维护、天然可分享)。确认需要"模型之外的东西"(界面、快捷键、事件、进程内逻辑)再写扩展。

14安全边界:默认很"敢",护栏要自己搭

先认清默认值

Pi 没有内置权限弹窗,启动后基本就是以你的用户身份在跑命令。这既是效率(不被打断),也是风险(无人把关)。官方给的安全策略由松到严一共四档:

1
用"只读"参数跑审查类任务

只需读代码时,用 pi --tools read,grep,find,ls -p "审查..." 直接禁止写和跑命令。

2
给它一个"干净的项目目录"

别在装着重要生产数据的目录里随便让它跑 bash。Pi 的工作区越小、越可牺牲,事故损失越低。

3
写扩展加权限门 / 路径保护

参考官方示例 permission-gate.ts、protected-paths.ts:在工具调用事件里加自己的确认规则,把"写前问我""禁止动 .env"做进去。

4
要硬隔离就装进容器

在容器 / 沙箱里跑 Pi(官方 sandbox 示例即此思路),即使模型行为失控也出不了容器。这是官方最推荐的重边界方案。

"项目信任"到底在决定什么

项目里有本地设置或资源时,Pi 启动会问你是否信任该项目。它的门道是:信任决定的是"项目里的代码和设置要不要被加载",不只是弹个窗。

阶段会加载什么为什么这样分
信任之前只加载上下文文件、用户级(全局)扩展,以及命令行 -e 指定的扩展让这些扩展能处理"项目信任"事件,做二次拦截
信任之后才加载 .pi/settings.json、项目资源与项目级扩展,并允许安装缺失的项目包项目里的扩展是会真实执行的代码,必须先经你同意
决定记录写在 ~/.pi/agent/trust.json;交互里可 /trust 手动存档(含给上级目录一并信任)/trust 只写文件,当前会话不重载,需重启生效

非交互模式(-p / --mode json / --mode rpc)不弹信任框,按全局的 defaultProjectTrust 处理:ask 是默认值(忽略项目资源),never 忽略,always 信任。可以针对单次运行用 -a/--approve(临时信任)或 -na/--no-approve(临时忽略)覆盖。

日常最佳实践清单

✅ 干活前先写进 AGENTS.md
命令、目录、提交规范这类"每次都一样"的约束写进项目 AGENTS.md,别每次口头叮嘱——省 token,也更稳定。
✅ 重要的重构先让它读文件再动手
大改动先说清目标,允许它先用 read / grep 摸底;必要时 /fork 一条实验分支,改坏不心疼。
✅ 关注底部 token 与成本
界面底部实时显示 ↑↓ 与缓存命中(R/W/CH)、成本。发现某次特别费,多半是历史太长——及时 /compact 或开新会话。
✅ 危险命令留个心眼
git push / rm / 覆盖文件这类"难撤销"的动作,宁可先用 !命令 自己看一眼再放行,或交给权限门扩展把关。
✅ 隐私与分享前脱敏
/export、/share 以及官方鼓励的"开源会话分享"都可能带出密钥。发之前扫描一遍。
✅ 联网行为是可关的
在意隐私可以设 PI_OFFLINE=1 或加 --offline 一次性关掉全部启动联网操作;单关更新检查用 PI_SKIP_VERSION_CHECK=1,单关遥测用 PI_TELEMETRY=0。注意"更新检查"和"遥测"是两件事,各关各的。

给三类人的起步配方

🧍 只打算自己日常用

① 跑一遍 §07 的待办清单演练,建立"我发话、它执行、我验收"的手感;② 给常干的项目写一份 AGENTS.md;③ 审查类任务一律用 --tools read,grep,find,ls;④ 养成"历史太长就 /compact"的习惯。

🧑‍💻 想重度定制

① 从把现有脚本"技能化"开始(性价比最高);② 再看官方仓库 examples/extensions/ 里的 permission-gate、sandbox、ssh、plan-mode 示例;③ 写不出来的部分直接让 Pi 自己写,你只负责审;④ 顺手的整理成包。

🏢 团队 / 开源协作

① 仓库根部维护 AGENTS.md,把命令、目录、提交规范写死;② 把团队检查脚本做成 Skill,"失败就停"的约束写进 SKILL.md;③ 打成 pi install git:... 包分发,版本锁在 tag 上;④ 贡献会话前脱敏。

15常见坑:九种典型翻车与怎么绕开

开工前最容易踩的三个

这三个的共同点是:出事的那一刻你还没意识到自己在出错。它们排在最前面,是因为代价最大、也最容易避免。

坑会发生什么怎么绕开
🚀 没 cd 进目录就开跑Pi 只看得到当前工作区,在错误目录启动可能"找不到文件"或改错项目先进目录再敲 pi
🪓 默认就敢跑命令没有权限弹窗 = 模型能执行任何 shell 命令审查用 --tools read,grep,find,ls;重活套容器,别裸奔
🧨 装了第三方扩展 / 包不 reviewPi 包有完全系统权限,扩展代码会真实执行装 pi install 的东西前先读源码

用着用着才暴露的三个

这三个通常发生在你已经用它干了几天活之后——不是它坏了,是它的工作方式和你以为的不一样。

坑会发生什么怎么绕开
🔄 改完扩展 / SKILL 忘了 /reload改文件后不会自动生效,你会以为坏了在会话里执行 /reload 热重载
📚 型号手滑 / 目录过期型号名随时会变,写死的名字很容易失效先 /model 或 pi --list-models 看,找不到就 pi update --models
🔑 误以为 -c 接的是"上个项目"会话按工作目录分文件夹存储pi -c 续的是当前目录最近那次,不是全局最近

长会话与协作时的三个

这三个跟"用得久"有关:上下文越攒越多、分享的东西越来越杂,风险也跟着变。

坑会发生什么怎么绕开
🌪️ 上下文顶爆长会话会撞到模型上下文上限手动 /compact 或开新会话;压缩有损,但原始历史在 JSONL 里可翻 /tree
🪟 Alt+Enter 没反应Windows Terminal 默认把 Alt+Enter 当全屏在终端设置里改键,Pi 才能收到"追问"快捷键
📤 分享 / 导出带出密钥/export、/share 含完整对话聊过 API Key 或隐私内容的,先清理再发
⚠️ 还有一个"心理坑"

Pi 不是"开箱即全会"。别拿它对标"自带 Plan 模式 + 权限弹窗"的工具,然后用不顺手就断定它不行——它把那些开关留给你了。判断自己适不适合它,取决于你愿不愿意花半小时把工作流调成自己的形状。

99速查表:命令、环境变量、键位

命令速查

你要做命令
装 Pinpm install -g --ignore-scripts @earendil-works/pi-coding-agent
版本 / 帮助pi --version · pi --help
开始对话pi(先进目标目录)
单发一问pi -p "问题" · 管道喂文 cat f | pi -p "摘要"
带文件问pi @src/a.ts @src/b.ts "审这两份文件"
指定模型pi --model openai/gpt-... "..." · pi --provider anthropic --model ...
看模型目录pi --list-models anthropic · 会话内 Ctrl+L
只读审查pi --tools read,grep,find,ls -p "Review..."
续上次 / 挑历史pi -c · pi -r
不存会话pi --no-session
热重载配置会话内 /reload
刷新模型目录pi update --models
装 / 列 / 卸包pi install npm:@foo/pi-tools · pi list · pi remove ...
完全离线一次pi --offline

环境变量速查

变量作用什么时候设它
ANTHROPIC_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEY…各提供商的 API Key(谁家认谁的变量名)不想用 /login 时
PI_CODING_AGENT_DIR覆盖配置目录(默认 ~/.pi/agent)想把配置放到别处 / 多套配置隔离
PI_CODING_AGENT_SESSION_DIR覆盖会话存储目录想单独归档会话(会被 --session-dir 覆盖)
PI_PACKAGE_DIR覆盖包目录Nix / Guix 这类 store 路径特殊的环境
PI_OFFLINE=1关闭所有启动联网操作(更新检查 / 包更新检查 / 遥测)隐私优先或网络不通
PI_SKIP_VERSION_CHECK=1只跳过版本更新检查不想它启动时访问 pi.dev
PI_TELEMETRY=0关掉安装 / 更新遥测与提供商归因头只在意遥测,不介意更新检查
PI_CACHE_RETENTION=long延长提示缓存留存(Anthropic 1h、OpenAI 24h)省长会话的钱
PI_SESSION_ID / PI_MODEL 等Pi 执行 shell 工具时注入给子进程的会话元数据你写的脚本需要知道当前上下文时
VISUAL / EDITORCtrl+G 打开外部编辑器时的兜底想让长文本编辑用你习惯的编辑器

键位速查

按键作用
Ctrl+L打开模型选择器(选好后 Ctrl+S 存默认)
Ctrl+P / Shift+Ctrl+P收藏模型循环切换(前 / 后)
Shift+Tab循环思考强度
Enter / Alt+Enter(运行中)转向消息 / 排队追问
Escape / 连按两次取消当前运行 / 打开会话树 /tree
Ctrl+O / Ctrl+T折叠工具输出 / 折叠思考块
@ · Tab · Ctrl+G@ 文件引用 · 补全路径 · 外部编辑器
!cmd / !!cmd执行命令并给模型看输出 / 执行命令不给他看

想深入某块?官方文档地图

本文是"把 Pi 用起来"的入门。官方仓库 packages/coding-agent/docs/ 里每块都有专门文档,按需查:

你想搞懂看哪份文档
加自定义提供商 / 模型docs/models.md · docs/custom-provider.md · docs/providers.md
写 / 调扩展docs/extensions.md + examples/extensions/(权限门、沙箱、plan-mode、子代理等)
写 Skilldocs/skills.md(另有提示模板 docs/prompt-templates.md)
改快捷键 / 主题docs/keybindings.md · docs/themes.md
打包分享docs/packages.md
会话格式 / 压缩机制docs/session-format.md · docs/compaction.md
全部设置项docs/settings.md
JSON 输出 / RPC / SDKdocs/json.md · docs/rpc.md · docs/sdk.md
环境变量细节docs/environment-variables.md
接本地 llama.cppdocs/llama-cpp.md
Windows / Termux / tmux / 终端别名docs/windows.md · termux.md · tmux.md · terminal-setup.md · shell-aliases.md

17参考来源与证据边界

来源用它核对了什么为什么信它
pi.dev(官网)定位、slogan、安装脚本、四种形态、提供商概览、Skill / 扩展 / 提示模板 / 主题 / 包讲解对象的官方门面,最贴近"它自己怎么介绍自己"
github.com/earendil-works/pi → packages/coding-agent/README.mdQuick Start、提供商与模型清单、交互命令、快捷键、会话 / 压缩、设置与信任、上下文文件、CLI 全参数、环境变量一手文档,参数表与路径表的最终依据
npmjs.com/package/@earendil-works/pi-coding-agent当前版本 0.85.1、运行环境 Node ≥ 22.19.0、MIT、包名与 bin版本锚点的唯一权威来源
Pi News:0.85.1 发布说明0.85.1 新增 GPT-6 Astra、SDK 相关修复官方 changelog,用来判断"现状"而不是凭记忆
docs.ollama.com/integrations/piOllama 接入 Pi 的官方说明本地模型那条路径的第三方官方佐证
作者博客:What I learned building an opinionated and minimal coding agent、What if you don't need MCP at all?设计动机、极简理念、为什么不做 MCP作者本人的一手叙述,用来解释"为什么这样设计"
📖 证据边界与时效说明

Pi 迭代很快(本文核对时 npm 上从 0.80 到 0.85.1 只隔了很短时间,模型目录与提供商清单还在持续扩充)。本文锚定 @earendil-works/pi-coding-agent @ 0.85.1,核对日期 2026-09-13。

命令名、提供商、快捷键、配置路径都可能随版本变化。如果你装的版本和本文写的对不上,以你的版本为准——用 pi --help、/hotkeys、/model 现场核对。

⚠️ 两处口径不一致,两边都留在这

一、提供商数量:官网首页写的是"15+ providers, hundreds of models",而 README 里逐个列出的内置提供商目录已经有三十多个。差的不是事实,是口径——首页说"至少",README 是清单本身。本文按后者展开。

二、界面示意图:本文 §09 那张框图画的是简化示意,不是真实截图。字段含义按官方 README 的说明写,具体排版会随版本变。

16术语对照表

只收正文里反复出现、值得回头查的词。第三列回答的是"为什么重要 / 什么时候用 · 别当什么用",不是翻译。

术语含义为什么重要 / 何时用 · 别当什么用
Agent harness(代理驱动框架)跑起"模型 ↔ 工具循环"的那层壳这是 Pi 对自我的定位。理解它,就知道 Pi 是框架而非成品功能集合;别指望它替你定义工作流。
Tool-use loop(工具调用循环)模型"决定调工具 → Pi 执行 → 结果回填 → 再决定"的循环,直到完成Pi 干活的基本盘。用它解释"为什么它会一步步自己读文件、跑命令";看懂循环就能预判它下一步,别把它当玄学。
read / write / edit / bash四个默认内置工具:读 / 写 / 精准改 / 执行命令Pi 的全部出厂能力就这些,极简省 token。想要更多就加 Skill 或扩展;别抱怨"它连 MCP 都没有"——那是设计选择。
Extension(扩展)TypeScript 模块,给 Pi 加工具 / 命令 / 快捷键 / 界面 / 事件定制力的主力,重度改造时用;只想"装上就用"的普通用户可以一直不碰。
Skill / SKILL.md一个目录 + 一份"何时用、怎么用"的说明,按需加载进上下文轻量加能力、渐进披露省 token,能替代很多 MCP 场景;别把它当重型常驻服务来写。
AGENTS.md项目指令文件,启动时自动拼接进上下文(Pi 也认 CLAUDE.md)把命令 / 规范 / 约定固化、让每个会话都遵守,是最省心的驯化手段。只写"换个人也会照做"的硬约定,别写空话。
System prompt / SYSTEM.md系统提示,定义模型"怎么当一个编码代理";可用 SYSTEM.md 替换、APPEND_SYSTEM.md 追加Pi 的系统提示极短,是它 token 高效的原因。新手优先追加而非整体替换;别随意清空,否则模型不知道怎么用工具。
Session / JSONL一次会话 = 一条 JSONL 文件,内部是树结构,存在 ~/.pi/agent/sessions/树结构让你能"反悔回岔路口"。别担心存档占空间,但也别忘了 /export 与 /share 会带走完整内容(含可能的密钥)。
/tree · /fork · /clone会话树导航 / 从历史消息另起新会话 / 复制当前分支为新会话实验性改动的安全网:改坏了随时回。别在主线上一路莽——分支很便宜。
Compaction(上下文压缩)把较早消息总结成摘要、保留近期消息,腾出上下文空间长会话续命的关键,自动默认开。它有损,但原始历史仍在 JSONL——别以为压缩后信息就永久丢了,可翻 /tree。
Prompt Template(提示模板)存成 Markdown 的常用需求,输入 /名字 展开,支持 {{变量}}把重复需求变一条斜杠命令。适用:同一段要求你敲过三次以上;别用它装需要频繁变通的长流程。
Pi Package把扩展 / Skill / 模板 / 主题打包,经 npm 或 git 分发安装的单元团队共享工作流的正式通道(pi install)。它有完全系统权限——装前必读源码,别当普通 npm 包随手装。
Provider / 模型目录提供商(Anthropic、OpenAI、Ollama…)及各自可用的模型清单决定你能用什么模型、花多少钱。型号名易变,认准 /model 与 pi update --models;别把某个型号名当永久事实写进脚本。
Context engineering(上下文工程)刻意控制"什么内容进入上下文、如何管理"的整套做法Pi 的核心卖点——上下文里放什么直接决定输出质量与费用。AGENTS.md / 压缩 / 极简系统提示都是它的抓手,别把它当玄学。
Prompt caching(提示缓存)重复的系统提示与上下文命中缓存,只按增量计费省长会话钱的关键,底部 R/W/CH 就是它的状态。Pi 刻意保持提示稳定正是为吃满缓存;别频繁大改系统提示,那等于主动弃缓存。
MCP(Model Context Protocol)一种"给模型挂外部工具"的通用协议;Pi 刻意不内置,想用自己接作者观点:多数场景"CLI + Bash + Skill"更省上下文。别默认"必须 MCP",先想你的需求能否用一个带 README 的小脚本解决。
Print mode(-p / --mode json)不交互、问一次拿结果就退出的运行形态(含 JSON 事件流)脚本化、管道、给别的程序喂结果的正确姿势;别用它做需要连续多轮修改的任务,那是交互模式的活。
Project trust(项目信任)Pi 在加载项目本地设置 / 资源前征求的"你信任这个目录吗"决定,存于 trust.json它决定项目级扩展与设置会不会被加载,是本地安全的闸门。非交互模式不弹框,按 defaultProjectTrust 走;别图省事一律 always。
YOLO by default作者自嘲式的默认行为:不弹权限窗,直接以你的权限执行提醒你"护栏要自己搭"。别把这句话当成"它很安全"——恰恰相反,正因默认没人拦,才要 --tools read,...、容器或权限门扩展兜底。
Scoped models(收藏模型)用 /scoped-models 圈定的一组模型,供 Ctrl+P 快速循环日常在"贵而强"与"便宜够用"之间秒切的关键。别把几十个全放进去——轮换太多反而难找。

18一句话总结

🎯 核心要点

Pi 是一个"内核极简、能力随你装"的终端 AI 编码代理——出厂只给模型读、写、改、跑命令四把工具,把子代理、Plan 模式、权限弹窗、MCP 都留给你用 Skill、扩展、Pi Package 按需拼装。它省 token、可接本地模型、适合愿意花一点时间把工具调成自己形状的人;代价是默认没有权限护栏,安全边界要你自己负责。

⚠️ 如果只带走一件事

先把 AGENTS.md 写好,再决定要不要给自己加权限门。不是 Pi 适配你,而是你把它调成你的形状。

⌂