发布扩展
最后更新: 2026年8月7日
$ pi –publish
TL;DR. 本地优先:把文件丢进 ~/.pi/agent/extensions/ 或 .pi/extensions/,或用 pi -e ./my-extension.ts 快速试;/reload 热加载。要分发就发一份 package.json,带上 pi: { extensions: [...] } 字段指向编译后的 JS,并把所有运行期依赖放进 dependencies(不能放 devDependencies —— Pi 用 --omit=dev 安装)。npm link + pi install link: 验证,再发布到 npm 或推到 git 主机通过 pi install git:... 安装。扩展以完整系统权限运行 —— 在 README 里写清楚你用到什么权限。
Pi 扩展最初就是一个 TypeScript 文件。当你想让别人 —— 或者跨多台机器的未来的自己 —— 通过 pi install 装上它时,它就升级为一个可分发的包。本文覆盖扩展包的结构、package.json 里的 pi 字段、发布前的本地测试,以及围绕运行期依赖的几个坑。事实依据是 Extensions 文档、Packages 文档,以及 packages/coding-agent/examples/extensions 下的可运行示例。
最小可用的扩展
在操心打包之前,先确保你的扩展能作为单文件跑起来。最小的实用形态:
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";
export default function (pi: ExtensionAPI) {
pi.registerTool({
name: "greet",
label: "Greet",
description: "Say hello to someone",
parameters: Type.Object({
name: Type.String({ description: "Name to greet" }),
}),
async execute(_id, params) {
return {
content: [{ type: "text", text: `Hello, ${params.name}!` }],
details: {},
};
},
});
}
存为 greet.ts,无需安装即可测试:
pi -e ./greet.ts
TUI 里 LLM 现在能用 name 参数调用 greet 工具。可用工具列表里会看到它已被注册。
扩展发现路径
本地开发时,Pi 自动从以下位置拾取 .ts 文件:
~/.pi/agent/extensions/*.ts—— 全局,单文件~/.pi/agent/extensions/*/index.ts—— 全局,子目录.pi/extensions/*.ts—— 项目级,单文件.pi/extensions/*/index.ts—— 项目级,子目录
项目级扩展只在项目被信任后才会被加载(通过 project_trust 事件解析)。/reload 可在不重启的情况下重新加载。
对于非标准路径 —— 你自己的临时目录、某人的 checkout —— 在 settings.json 里列出来:
{
"extensions": [
"/path/to/local/extension.ts",
"/path/to/local/extension/dir"
]
}
把文件升级为包
当扩展超过单个文件、或者需要第三方依赖时,就该打包了。最小的 package.json 长这样:
{
"name": "pi-greet",
"version": "0.1.0",
"description": "为 Pi 添加 greet 工具。",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"dependencies": {
"typebox": "^0.32.0",
"@earendil-works/pi-coding-agent": "^0.83.0"
},
"pi": {
"extensions": ["./dist/index.js"]
}
}
两个容易踩坑的细节:
pi.extensions是入口清单。它指向编译后的 JS(不是 TS 源码),这样 Pi 在运行期无需 TypeScript 工具链即可加载。- 写在
dependencies,不是devDependencies。 包安装默认走生产安装(npm install --omit=dev),所以任何运行期import的东西都必须放在dependencies。
可选地,在 @earendil-works/pi-coding-agent 上声明 peerDependencies 是推荐做法 —— 它由 Pi 自身提供。宽松钉版本(^0.83.0)能避免用户在各自升级 Pi 时出现版本冲突。
发布前测试包
推到 npm 之前,先把包本地 link 起来,让 pi install 本地路径与终端用户安装的方式完全一致:
# 在扩展仓库内
npm link
# 全局可见;在任意项目里测试
pi install link:pi-greet
# 或者直接指向编译后的目录
pi -e /absolute/path/to/pi-greet/dist/index.js
link 完成后,覆盖每个入口点:注册工具、订阅会话事件、渲染自定义 UI。/reload 验证热重载,重新启动 Pi 验证冷启动也能加载。
发布到 npm
标准 npm 发布流程即可:
npm login
npm publish --access public
确保 dist/ 是最新的(用你偏好的工具编译 TypeScript —— tsc、tsup、unbuild),package.json 列全所有运行期依赖,并通过 files 字段(或 .npmignore)把 source map 与开发产物挡在 tarball 外。
发布后,在新 shell 里安装验证:
pi install npm:pi-greet
pi
新会话里 greet 工具应当与本地测试时一样可用。
发布到 git 托管平台
Git 包适合私有 fork 或钉到某个具体 commit。包本身仍需要带 pi 字段的 package.json,用户这样安装:
pi install git:github.com/your-org/pi-greet@v1.0.0
Packages 文档覆盖支持的 URL 形态,以及如何指向 monorepo 中的子目录。注意:配置了 npmCommand 时,git 安装走普通的 npm install(而非 --omit=dev),所以包装器与有 hoisted 依赖的 monorepo 都能正常工作。
可以基于哪些包构建
扩展作者可以引用几个官方包:
| 包 | 用途 |
|---|---|
@earendil-works/pi-coding-agent |
扩展类型(ExtensionAPI、ExtensionContext、events) |
typebox |
工具参数的 JSON Schema 定义 |
@earendil-works/pi-ai |
AI 工具(StringEnum 等 Google 兼容枚举) |
@earendil-works/pi-tui |
自定义渲染用的 TUI 组件 |
如果你的包是要新增一个自定义 provider,而不是只新增工具,看 Custom providers 文档。完整 provider 扩展接口(注册、模型刷新、过滤、自定义流式)在 v0.81.0 引入。
权限、信任与披露
Pi 扩展以你的完整系统权限运行,可以执行任意代码。agent 不做沙箱,所以安装信任模型就是“谁发布包谁负责代码”。两条实践能保护用户、也提升你包的可信度:
- 在 README 里写明扩展需要的权限。 如果你访问网络、在工作目录外写文件、或调用子进程,都写清楚。
- 入口面尽量收窄。 单条
pi.extensions入口重新导出所有内容,比一片铺开的副作用 import 更容易审计。
项目级扩展由 project_trust 事件把关 —— 在用户显式信任之前,扩展不会在新克隆的仓库里自动加载。
一份精简的发布清单
在打 1.0.0 tag 之前:
-
package.json含name、version、description、type: "module"、pi.extensions,以及所有运行期依赖。 -
npm pack --dry-run只列出你打算发布的文件。 - 在干净目录里
npm install产出能用的包。 - 在新 Pi 会话里
pi install npm:your-package能加载扩展。 - README 写明安装、配置以及扩展使用的权限。
- 版本相对
@earendil-works/pi-coding-agent钉好,避免 API 变更时的破坏性升级。
想在生态里更显眼一点,可以在本站资源地图的 extensions 或 tools 分类下提交一条 —— 见 Contributing 页面的 schema 与提交流程。
延伸阅读
- Extensions —— 事件、自定义工具、斜杠命令、项目信任
- Packages —— 通过 npm 或 git 安装、
pi字段形态、--omit=dev规则 - Custom providers —— 当扩展不止是工具时
packages/coding-agent/examples/extensions—— 仓库内的可运行示例- Releases —— v0.81.0 完整 provider 扩展、v0.84.1 终止被阻塞的工具调用