pi 是什么
pi(npm 包 @earendil-works/pi-coding-agent)是 Mario Zechner 开发的开源编码智能体,跑在终端里。
它的设计立场写在官方文档里:内核保持极小,工作流相关的行为全部推进扩展、技能(skill)、提示模板与包里。
所以它默认不内置 MCP、子代理、权限弹窗、计划模式、待办清单、后台 bash——这些在别的智能体里是标配的东西,
在 pi 里统统是你自己选择装或不装的扩展。
内核自带
四个工具:read / write / edit / bash,
外加三个可选只读工具 grep / find / ls。
会话树、压缩(compaction)、多 provider、TUI 都是原生能力。
生态补齐
MCP → pi-mcp-adapter;子代理 → pi-subagents; 计划模式 → 官方示例 plan-mode;危险命令确认 → permission-gate。 都在 §05 讲怎么搜、怎么装。
这个立场带来的直接后果:pi 的全部个性化状态都收敛在两处文件里——全局的
~/.pi/agent/ 与项目的 .pi/。
内核可以从 npm 随时重装,环境本质上就是这两摞文本文件。这正是 §06「快速恢复」能成立的前提。
# 最短上手:装好、进项目、开聊
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
cd /path/to/project && pi安装与升级
1.1安装
官方推荐 npm 全局安装;curl 安装器底层也是走 npm。
# npm(推荐;--ignore-scripts 跳过依赖的生命周期脚本) npm install -g --ignore-scripts @earendil-works/pi-coding-agent # 或者一键脚本 curl -fsSL https://pi.dev/install.sh | sh # 验证 pi --version # → 0.85.1
pnpm / Yarn / Bun 装的就用各自命令卸;--ignore-scripts 是安全默认——pi 的正常安装不依赖任何 install 脚本。
1.2升级
pi update 一条命令身兼三职:升级 pi 自身、升级包、刷新模型目录,按旗标取用:
| 命令 | 做什么 |
|---|---|
| pi update | 只升级 pi 自身 |
| pi update --all | 升级 pi + 全部包,并把 git 包收敛到 settings 里钉住的 ref |
| pi update --extensions | 只升级包 + 收敛 git ref(pi 自身不动) |
| pi update --models | 只刷新模型目录 |
| pi update npm:@foo/bar | 只升级指定的一个包 |
带 @版本 的 npm 源和带 ref 的 git 源属于钉住(pinned),
pi update --all 不会把它们推向新版本,只会把已有克隆校准回钉住的 ref——要不要升级由你显式决定(§04)。
1.3卸载
npm uninstall -g @earendil-works/pi-coding-agent
卸载只删二进制。设置、凭据、会话、已装的 pi 包全部留在 ~/.pi/agent/,
重装后原样回来。想彻底清空才需要手动删这个目录。
配置体系
2.1两级 settings,递归合并
- 所有项目共享的默认值
packages全局清单在这里defaultProjectTrust只在此层生效
- 当前项目覆盖,可入 git 与团队共享
- 同名键:项目胜出
- 嵌套对象按字段合并,不是整块替换
.pi/ 设置与资源,只有在项目被信任后才会加载;
信任决定记录在 ~/.pi/agent/trust.json,交互模式首次进入会弹询问,
/trust 可保存决定,-a / -na 可对单次运行强制信任或忽略。
合并是「深」的:项目只改一个字段不会丢掉全局其他字段。
// 全局:~/.pi/agent/settings.json { "compaction": { "enabled": true, "reserveTokens": 16384 } } // 项目:.pi/settings.json —— 只覆盖一个字段 { "compaction": { "reserveTokens": 8192 } } // 生效结果:enabled=true(承自全局) + reserveTokens=8192(项目)
2.2高频配置速查
| 键 | 作用 |
|---|---|
| defaultProvider / defaultModel | 启动时的模型;/model 里按 Ctrl+S 可交互保存 |
| defaultThinkingLevel | 启动思考等级:off→max 七档;/thinking + Ctrl+S 同理 |
| enabledModels | Ctrl+P 快速轮换的模型池,支持通配("claude-*") |
| packages | 包清单,扩展管理的核心,§04 整节展开 |
| extensions / skills / prompts / themes | 本地资源的额外加载路径,支持 glob 与 !排除 |
| defaultTools | 启动启用的内置工具子集;空数组 = 裸奔(扩展工具不受影响) |
| compaction.* | 自动压缩开关与 token 预算,可按模型覆盖 |
| retry.* | 瞬时错误自动重试(指数退避,默认 3 次) |
| httpProxy | 全局 HTTP(S) 代理,仅全局层生效 |
| npmCommand | 把 npm 操作钉到包装器,如 ["mise","exec","node@20","--","npm"] |
| defaultProjectTrust | 非交互模式的信任兜底:ask(默认)/ always / never |
| theme | dark(默认)/ light / 自定义主题名 |
2.3凭据:三条通道
- 订阅登录:交互内
/login,支持 Claude Pro/Max、ChatGPT(Codex)、GitHub Copilot 的 OAuth; - 环境变量:启动前 export 对应 key(如
ANTHROPIC_API_KEY),适合 CI 与一次性运行; - auth 文件:
/login选 API-key provider 后写入~/.pi/agent/auth.json。
命令行还有 pi auth 子命令可打印凭据状态、检查 provider 就绪情况。
2.4一份真实的全局 settings
本机在用的全局配置(值已一般化),两个看点:packages 登记了 MCP 适配器包;模型指向自建网关:
// ~/.pi/agent/settings.json { "defaultModel": "deepseek-flash", "defaultProvider": "senv-deepseek", "packages": [ "npm:pi-mcp-adapter" ], "lastChangelogVersion": "0.85.1", "theme": "dark" }
就这么短。pi 的设置不需要一次配全——缺省值都能直接用,有偏好再加。
交互内 /settings 可改常用项;改了上下文文件或扩展,/reload 立即生效。
扩展:写一个
扩展就是一个 TypeScript/JS 模块:默认导出一个工厂函数,pi 启动时把
ExtensionAPI 递给它。能做的事:订阅生命周期事件、注册自定义工具(供 LLM 调用)、
注册斜杠命令、往会话里写持久条目、以及用 ctx.ui 做交互 UI。
3.1放哪才会被加载
| 位置 | 作用域 | 说明 |
|---|---|---|
| ~/.pi/agent/extensions/*.ts | 全局 | 子目录形式 */index.ts 同样生效 |
| .pi/extensions/*.ts | 项目 | 项目信任后才加载 |
| settings.extensions | 随所在层 | 指向任意本地路径或目录,支持 glob |
| pi -e ./x.ts | 临时 | 只活在当次运行,用来快试;不支持 /reload 热重载 |
放在自动发现目录(上两行)里的扩展,改完无需重启——会话内 /reload 即可;
-e 快试路径和 settings 的 packages 走各自的装载时机。
3.2最小可用示例
一个文件同时演示三件事:事件拦截(危险命令确认)、自定义工具、斜杠命令:
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { // ① 事件:拦下 rm -rf,先问人 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 by user" }; } }); // ② 自定义工具:LLM 可直接调用 pi.registerTool({ name: "greet", description: "Greet someone by name", parameters: Type.Object({ name: Type.String({ description: "Name to greet" }) }), async execute(toolCallId, params) { return { content: [{ type: "text", text: `Hello, ${params.name}!` }], details: {} }; }, }); // ③ 斜杠命令:/hello pi.registerCommand("hello", { description: "Say hello", handler: async (args, ctx) => { ctx.ui.notify(`Hello ${args || "world"}!`, "info"); }, }); }
# 临时加载试跑(不落任何配置)
pi -e ./my-extension.ts3.3API 面貌速览
| 能力 | 入口 | 典型用途 |
|---|---|---|
| 订阅事件 | pi.on(event, handler) | tool_call 拦截、input 改写、session_start 初始化 |
| 注册工具 | pi.registerTool(def) | 给 LLM 添加新能力(参数用 typebox 描述) |
| 注册命令 | pi.registerCommand(name) | /plan、/preset 这类自定义斜杠命令 |
| 会话持久化 | pi.appendEntry(type, data) | 状态写进会话文件,重启不丢(待办、连接池…) |
| 用户交互 | ctx.ui.* | select / confirm / input / notify,以及 custom() 全自定义 TUI |
| 注入消息 | pi.sendMessage / sendUserMessage | 程序化地向会话投递内容 |
| 改请求 | before_provider_request | 发往模型前最后改一次请求体/头 |
事件全表很长(会话、agent、消息、工具、模型五族 30+ 个),写在官方 extensions.md;
日常写扩展最常用的就是 tool_call、input、session_start、model_select 这几个。
3.4官方示例库:先抄再造
仓库 examples/extensions/ 下有几十个可跑的实现,挑几个有代表性的:
| 示例 | 做什么 |
|---|---|
| permission-gate.ts | 危险 bash 命令(rm -rf、sudo…)先确认——权限门的参考实现 |
| protected-paths.ts | 禁止写 .env、.git/、node_modules/ 等受保护路径 |
| todo.ts | 待办工具 + /todos 命令,自定义渲染 + 会话持久化 |
| plan-mode/ | 类 Claude Code 的计划模式:只读探索 + /plan 命令 |
| subagent/ | 把任务委托给隔离子上下文的专用子代理 |
| preset.ts | 命名预设:模型 + 思考等级 + 工具 + 指令一键切换 |
| handoff.ts | /handoff 把当前上下文移交到聚焦的新会话 |
| notify.ts | agent 跑完发桌面通知(OSC 777,Ghostty/iTerm2/WezTerm) |
| ssh.ts | 把全部工具委托到远程机器执行 |
| snake.ts | 等模型时玩贪吃蛇——展示 ctx.ui.custom() 的上限 |
扩展以你的完整系统权限运行任意代码。装第三方扩展前读源码,和装 npm 包一个警惕级别。
包:扩展的发行形态
单文件扩展适合自己用;包(package)解决「分发」:把扩展、技能、提示模板、主题打包,
通过 npm 或 git 发布,一条命令装进任何人的 pi。一个包可以在 package.json 的
pi 键里声明资源,也可以什么都不写、直接用约定目录:
// package.json { "name": "my-package", "keywords": ["pi-package"], // ← 打上这个标签才能进官方画廊 "pi": { "extensions": ["./extensions"], "skills": ["./skills"], "prompts": ["./prompts"], "themes": ["./themes"] } } // 没有 pi 键时,约定目录 extensions/ skills/ prompts/ themes/ 自动发现
4.1三种源
| 源 | 写法 | 落盘位置 | 更新行为 |
|---|---|---|---|
| npm: | npm:@foo/bar@1.2.3npm:pkg |
全局 ~/.pi/agent/npm/项目 .pi/npm/ |
带版本 = 钉住,update 不动它 |
| git: | git:github.com/user/repo@v1ssh://… / https://… |
~/.pi/agent/git/<host>/<path> |
钉 ref;校准 = reset 到 ref + npm install |
| 本地路径 | /abs/path 或 ./rel/path |
原位引用,不复制 | 随文件系统,即时生效 |
4.2命令全家福
pi install npm:@foo/bar@1.0.0 # 装(写进全局 settings) pi install -l git:github.com/u/r # -l = 写进项目 .pi/settings.json pi remove npm:@foo/bar # 卸(uninstall 同义) pi list # 看 settings 里已登记的包 pi config # TUI 逐项开关包里的资源,Tab 切全局/项目 pi -e npm:@foo/bar # 试用:临时目录,只在本次运行存活
pi install -l 写的是项目 .pi/settings.json——把它提交进 git,
队友 clone 后首次信任项目时,缺的包会自动补装。这是 pi 官方设计的团队分发路径。
4.3细粒度控制:过滤与关闭
packages 数组里可以用对象形式,只取包的一部分资源:
{
"packages": [
"npm:simple-pkg", // 字符串形式:全量加载
{
"source": "npm:my-package",
"skills": ["brave-search", "transcribe"], // 只要这两个 skill
"extensions": ["extensions/*.ts", "!extensions/legacy.ts"] // glob + 排除
}
]
}
规则:省略键 = 该类全要;[] = 全不要;!pattern 排除;+path/-path 强制含/舍。
同一包同时出现在全局与项目时,项目条目胜出;项目条目写 autoload: false 则变成对全局条目的「增量修正」。
不想动配置、临时关掉某次加载:pi --no-extensions(目录发现)配 -e(精确指定)可以组合出「只加载这一个」的干净环境。
4.4实战:给 pi 接 MCP
pi 不内置 MCP 客户端——这是理解它扩展生态的最佳案例。社区做法是装
pi-mcp-adapter 包(上面的 settings 里已经登记),MCP server 定义放在同目录的
mcp.json:
// ~/.pi/agent/mcp.json { "mcpServers": { "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest", "--browser", "chromium"] }, "web-reader": { "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer <your-token>" } } } }
stdio 型用 command/args,HTTP 型用 url/headers。启动后这些 server 的工具会以
MCP 工具的形式出现在会话里。注意:mcp.json 里常有凭据,进备份/仓库前先脱敏或改成环境注入(§06)。
搜索扩展
5.1官方包画廊
pi.dev/packages
是官方画廊,收录所有发布了 pi-package 关键字的 npm 包(2026-09 时点约 5400 个)。
支持按名称/描述/作者搜索,按类型筛选(extension / skill / theme / prompt),
按下载量、最新发布或字母排序;每张卡片直接给出安装命令。
# 画廊卡片上的安装命令,复制即用
pi install npm:pi-web-access5.2命令行搜索
画廊本质是 npm 的视图,所以 npm 命令都能用,而且能看到画廊没展示的元数据:
# 按关键字搜(与画廊同一收录条件) npm search pi-package # 装前验明正身:关键字、README、最近发布 npm view pi-mcp-adapter keywords description npm view pi-mcp-adapter time.modified
5.3值得认识的包(2026-09,按下载量)
| 包 | 一句话 |
|---|---|
| pi-mcp-adapter | MCP 适配器,pi 接 MCP 生态的事实标准 |
| pi-web-access | 网页搜索、抓取、GitHub 克隆、PDF 提取、YouTube 理解 |
| pi-subagents | 子代理委托与脚本化多代理工作流 |
| pi-lens | 实时代码反馈:LSP、lint、类型检查、结构分析 |
| pi-background-tasks | 持久化后台 shell 任务 + 只读委托代理 |
| pi-plan-task | 可配置、可审批、可恢复的计划-执行工作流 |
| pi-spark | 日常体验打磨集合(交互细节增强) |
| bigpowers | 73 个技能包,软件工程方法论浓缩 |
| billion-context | 上下文压缩代理,面向超长任务 |
| @eko24ive/pi-ask | 交互式 ask_user 澄清工具,让模型别瞎猜 |
| @tryinget/pi-session-compaction | 自定义会话压缩摘要策略 |
| @gotgenes/pi-permission-system | 权限执行框架 |
5.4装之前,四问
- 下载量与更新时间——画廊卡片直接标;久未更新的慎装;
- 有没有开放源码仓库——
npm view看 repository 字段,闭源包跳过; - 权限面——扩展是全权限任意代码,审查它注册了什么工具、拦截了什么事件、往哪发网络请求;
- 要不要钉版本——生产环境
npm:pkg@1.2.3钉住,升级走显式决策。
新环境快速恢复
pi 的全部状态就在文件系统上,没有隐藏的云端配置。恢复 = 装二进制 + 摆对几份文件, 剩下的(pi 补装包、收敛 git ref)它启动时自己做。
6.1先认清:状态都放在哪
~/.pi/agent/ ├── settings.json ★ 核心档案:配置 + packages 清单(唯一必须备份) ├── AGENTS.md ★ 全局指令(有就备份) ├── SYSTEM.md ★ 自定义系统提示(可选) ├── extensions/ ★ 自写扩展目录(有就备份) ├── skills/ prompts/ themes/ ★ 自有本地资源 ├── mcp.json ◐ MCP server 定义(备份,但先脱敏!) ├── trust.json ◐ 项目信任决定(可选;不备就重新逐项目信任) ├── auth.json ✗ 凭据——敏感,不走 dotfiles;拷贝或重新 /login ├── npm/ ✗ 包实体(node_modules),settings 在就能重建 ├── git/ ✗ git 包克隆,同上可重建 ├── sessions/ ✗ 会话历史,按需另存,不算「环境」 └── mcp-cache.json 等 ✗ 缓存,不备份 <project>/.pi/ ├── settings.json ★ 项目包清单 → 入 git,clone 即恢复 └── extensions/ ★ 项目扩展 → 入 git
★ = 备份候选(进 dotfiles 或私有仓库);✗ = 可重建/敏感,不进;◐ = 看情况。
6.2恢复五步
装二进制
npm install -g --ignore-scripts @earendil-works/pi-coding-agent或 curl 安装器。这一步之后 pi 本体就绪,但还没有任何扩展。
还原全局档案
cp -R dotfiles/pi-agent/. ~/.pi/agent/至少 settings.json;连 AGENTS.md、extensions/、skills/ 一起放回。关键是 packages 清单回来了。
启动 pi,包自动补装
pi
核心机制:启动装载资源时,npm/git 包若在磁盘上缺失,pi 会自动安装(非 --offline 模式下)。
这一步在源码里坐实(resolvePackageSources → installMissing),settings 有什么就长回什么。
恢复凭据
cp auth.json ~/.pi/agent/ # 同机迁移可直接拷 # 或 pi # → /login 重新走一遍 OAuth / API-key环境变量通道不受影响;auth.json 含凭据,只在可信机器间手递手,不进仓库。
核对 + 项目级收尾
pi list # 与备份的清单逐条对 cd ~/some-project && pi # 首次进入 → 信任 → .pi/ 里缺的包自动装启动头里的 Extensions / Skills 行数对上了,恢复完成。
6.3一键恢复脚本(dotfiles 风格)
#!/usr/bin/env bash set -euo pipefail # 1) pi 本体 command -v pi >/dev/null || npm install -g --ignore-scripts @earendil-works/pi-coding-agent # 2) 全局档案(仓库内 pi-agent/ ↔ ~/.pi/agent/,凭据除外) mkdir -p ~/.pi/agent rsync -a --exclude='auth.json' --exclude='sessions/' \ --exclude='npm/' --exclude='git/' \ "$(dirname "$0")/pi-agent/" ~/.pi/agent/ # 3) 起一次 pi(非交互)触发补装,然后对清单 pi --no-session -p "reply ok" >/dev/null pi list
6.4两个约定让恢复永远轻松
-
一切经 settings:手动
npm i -g装的东西 pi 不认识; 装扩展永远走pi install,让清单成为唯一事实源——恢复时才存在「照单全收」。 -
项目包进 git:团队/个人项目统一用
pi install -l,.pi/settings.json提交;新 clone 信任项目即自动补装,项目环境零手工。
6.5排障速查
| 症状 | 先查什么 |
|---|---|
| 项目扩展/包没加载 | 项目信任了吗?/trust 保存;非交互模式看 defaultProjectTrust,或跑一次 -a |
| npm 包装不上 | npm 在 PATH 吗?用 mise/asdf 时设 npmCommand |
| 启动变慢/离线环境想跳过补装 | --offline(或 PI_OFFLINE=1)跳过全部启动网络操作 |
| git 包 ref 不对 | pi update --extensions 会把克隆 reset 回 settings 钉的 ref |
| MCP 工具没出现 | npm:pi-mcp-adapter 在 packages 里吗?mcp.json 语法/凭据对吗? |
速查卡
── 生命周期 ────────────────────────────────────────── npm i -g --ignore-scripts @earendil-works/pi-coding-agent # 安装 pi update --all # 升级 pi + 包 + 收敛 git ref pi update --self # 只升级 pi npm uninstall -g @earendil-works/pi-coding-agent # 卸载(数据保留) ── 扩展与包 ────────────────────────────────────────── pi install npm:pkg@1.2.3 # 安装(全局);-l → 项目级 pi install git:github.com/u/r@v1 pi -e ./ext.ts # 临时加载,当次有效 pi remove npm:pkg # 卸载 pi list # 已装清单 pi config # TUI 开关包内资源(Tab 切作用域) pi update --extensions # 只升级包 ── 会话内 ──────────────────────────────────────────── /reload # 热重载扩展/技能/上下文 /trust # 保存项目信任决定 /model /thinking # 切模型/思考等级;Ctrl+S 存默认 /settings # 交互改配置 ── 常用旗标 ────────────────────────────────────────── -p 非交互一炮 -c 续最近会话 -r 选会话恢复 -a / -na 单次信任/忽略项目资源 --offline 跳过启动网络