# Pi 包

> pi 包的安装管理、三种来源、创建方法、目录结构、依赖与过滤配置。

---

LLMS 索引： [llms.txt](/llms.txt)

---

> pi 可以帮你创建 pi 包。可以让它把你的扩展、技能、提示词模板或主题打包。

Pi 包把扩展、技能、提示词模板和主题打包在一起，让你可以通过 npm 或 git 分享它们。一个包可以在 `package.json` 的 `pi` 键下声明资源，也可以使用约定目录。

## 目录 {#table-of-contents}

- [安装与管理](#install-and-manage)
- [包来源](#package-sources)
- [创建 Pi 包](#creating-a-pi-package)
- [包结构](#package-structure)
- [依赖](#dependencies)
- [包过滤](#package-filtering)
- [启用与禁用资源](#enable-and-disable-resources)
- [作用域与去重](#scope-and-deduplication)

## 安装与管理 {#install-and-manage}

> **安全提示：** Pi 包以完整的系统权限运行。扩展会执行任意代码，技能可以指示模型执行任何操作，包括运行可执行文件。安装第三方包之前，请先审查其源代码。

```bash
pi install npm:@foo/bar@1.0.0
pi install git:github.com/user/repo@v1
pi install https://github.com/user/repo  # raw URLs work too
pi install /absolute/path/to/package
pi install ./relative/path/to/package

pi remove npm:@foo/bar
pi list                     # show installed packages from settings
pi update                   # update pi only
pi update --all             # update pi, update packages, and reconcile pinned git refs
pi update --extensions      # update packages and reconcile pinned git refs only
pi update --models          # refresh model catalogs only
pi update --self            # update pi only
pi update --self --force    # reinstall pi even if current
pi update npm:@foo/bar      # update one package
pi update --extension npm:@foo/bar
```

这些命令管理 pi 包，其中 `pi update` 还能更新 pi CLI 本身。对于实验性的安装器托管安装，`pi update` 会把确切的已检出版本安装到一个分阶段的、由锁文件支撑的发布中，并且只有在验证通过后才激活它；更新失败时当前发布保持不变。托管安装不支持 `--force`；要修复请重新运行安装器。要卸载 pi 本身，请参阅[快速开始](/book/pi/quickstart/#uninstall)。

默认情况下，`install` 和 `remove` 写入用户设置（`~/.pi/agent/settings.json`）。使用 `-l` 可以改为写入项目设置（`.pi/settings.json`）。项目设置可以与团队共享；项目受信任之后，pi 会在启动时自动安装缺失的包。

要临时试用一个包而不正式安装，可以使用 `--extension` 或 `-e`。这只会在本次运行中安装到临时目录：

```bash
pi -e npm:@foo/bar
pi -e git:github.com/user/repo
```

## 包来源 {#package-sources}

Pi 在设置和 `pi install` 中接受三种来源类型。

### npm {#npm}

```
npm:@scope/pkg@1.2.3
npm:pkg
```

- 带版本号的规格会被固定，包更新（`pi update --extensions`、`pi update --all`）会跳过它们。
- 用户级安装位于 `~/.pi/agent/npm/` 之下。
- 项目级安装位于 `.pi/npm/` 之下。
- 在 `settings.json` 中设置 `npmCommand`，可以把 npm 包查找和安装操作固定到某个特定的包装命令，例如 `mise` 或 `asdf`。

示例：

```json
{
  "npmCommand": ["mise", "exec", "node@20", "--", "npm"]
}
```

### git {#git}

```
git:github.com/user/repo@v1
git:git@github.com:user/repo@v1
https://github.com/user/repo@v1
ssh://git@github.com/user/repo@v1
```

- 不带 `git:` 前缀时，只接受带协议的 URL（`https://`、`http://`、`ssh://`、`git://`）。
- 带 `git:` 前缀时，接受简写格式，包括 `github.com/user/repo` 和 `git@github.com:user/repo`。
- HTTPS 和 SSH URL 都受支持。
- SSH URL 会自动使用你配置的 SSH 密钥（遵循 `~/.ssh/config`）。
- 在非交互运行（例如 CI）中，可以设置 `GIT_TERMINAL_PROMPT=0` 来禁用凭据提示，并设置 `GIT_SSH_COMMAND`（例如 `ssh -o BatchMode=yes -o ConnectTimeout=5`）以便快速失败。
- ref 是固定的 tag 或 commit。`pi update --extensions` 和 `pi update --all` 不会把它们移动到更新的 ref，但会把已有克隆对账到配置的 ref。
- 使用 `pi install git:host/user/repo@new-ref` 可以更新设置，并把已有包移动到新的固定 ref。
- 克隆到 `~/.pi/agent/git/<host>/<path>`（全局）或 `.pi/git/<host>/<path>`（项目）。
- 当对账改变了检出内容时，pi 会重置并清理克隆，然后在存在 `package.json` 时运行 `npm install`。

**SSH 示例：**
```bash
# git@host:path shorthand (requires git: prefix)
pi install git:git@github.com:user/repo

# ssh:// protocol format
pi install ssh://git@github.com/user/repo

# With version ref
pi install git:git@github.com:user/repo@v1.0.0
```

### 本地路径 {#local-paths}

```
/absolute/path/to/package
./relative/path/to/package
```

本地路径指向磁盘上的文件或目录，会被加入设置而不做复制。相对路径相对于其所在的设置文件解析。如果路径是文件，则作为单个扩展加载；如果是目录，pi 会按照包规则加载其中的资源。

## 创建 Pi 包 {#creating-a-pi-package}

在 `package.json` 中添加 `pi` 清单，或使用约定目录。加上 `pi-package` 关键字便于被发现。

```json
{
  "name": "my-package",
  "keywords": ["pi-package"],
  "pi": {
    "extensions": ["./extensions"],
    "skills": ["./skills"],
    "prompts": ["./prompts"],
    "themes": ["./themes"]
  }
}
```

路径相对于包根目录。数组支持 glob 模式和 `!` 排除项。清单中的正向 glob 会按字典序发现可见路径。以点开头的路径需要直接列出。如果某个 glob 需要穿越符号链接继续匹配，请直接列出该符号链接指向的资源根目录。

### 展示页元数据 {#gallery-metadata}

[包展示页](https://pi.dev/packages)会展示带有 `pi-package` 标签的包。添加 `video` 或 `image` 字段可以显示预览：

```json
{
  "name": "my-package",
  "keywords": ["pi-package"],
  "pi": {
    "extensions": ["./extensions"],
    "video": "https://example.com/demo.mp4",
    "image": "https://example.com/screenshot.png"
  }
}
```

- **video**：仅限 MP4。桌面端悬停时自动播放，点击后打开全屏播放器。
- **image**：PNG、JPEG、GIF 或 WebP。以静态预览的形式展示。

两者同时设置时，video 优先。

## 包结构 {#package-structure}

### 约定目录 {#convention-directories}

如果没有 `pi` 清单，pi 会从这些目录自动发现资源：

- `extensions/` 加载 `.ts` 和 `.js` 文件
- `skills/` 递归查找 `SKILL.md` 文件夹，并把顶层的 `.md` 文件作为技能加载
- `prompts/` 加载 `.md` 文件
- `themes/` 加载 `.json` 文件

## 依赖 {#dependencies}

第三方运行时依赖应放在 `package.json` 的 `dependencies` 中。不注册扩展、技能、提示词模板或主题的依赖也属于 `dependencies`。当 pi 从 npm 或 git 安装一个包时，会运行 `npm install`，因此这些依赖会被自动安装。

Pi 为扩展和技能打包了核心包。如果你导入了其中任何一个，请把它们列在 `peerDependencies` 中并使用 `"*"` 范围，而且不要打包它们：`@earendil-works/pi-ai`、`@earendil-works/pi-agent-core`、`@earendil-works/pi-coding-agent`、`@earendil-works/pi-tui`、`typebox`。

其他 pi 包必须打包进你的 tarball。把它们加入 `dependencies` 和 `bundledDependencies`，然后通过 `node_modules/` 路径引用它们的资源。Pi 加载包时使用各自独立的模块根，因此分开安装的包不会冲突，也不会共享模块。

示例：

```json
{
  "dependencies": {
    "shitty-extensions": "^1.0.1"
  },
  "bundledDependencies": ["shitty-extensions"],
  "pi": {
    "extensions": ["extensions", "node_modules/shitty-extensions/extensions"],
    "skills": ["skills", "node_modules/shitty-extensions/skills"]
  }
}
```

## 包过滤 {#package-filtering}

在设置中使用对象形式，可以过滤一个包加载的内容：

```json
{
  "packages": [
    "npm:simple-pkg",
    {
      "source": "npm:my-package",
      "extensions": ["extensions/*.ts", "!extensions/legacy.ts"],
      "skills": [],
      "prompts": ["prompts/review.md"],
      "themes": ["+themes/legacy.json"]
    }
  ]
}
```

`+path` 和 `-path` 是相对于包根目录的精确路径。

- 省略某个键表示加载该类型的全部资源。
- 使用 `[]` 表示不加载该类型的任何资源。
- `!pattern` 排除匹配项。
- `+path` 强制包含某个精确路径。
- `-path` 强制排除某个精确路径。
- 过滤器叠加在清单之上，只会收窄已经允许的范围。

## 启用与禁用资源 {#enable-and-disable-resources}

使用 `pi config` 可以启用或禁用来自已安装包和本地目录的扩展、技能、提示词模板和主题。`pi config` 默认从全局设置（`~/.pi/agent/settings.json`）开始；按 Tab 可以在全局与项目级模式之间切换。使用 `pi config -l` 可以从项目覆盖（`.pi/settings.json`）开始，继承自全局的资源会以暗淡方式显示。

## 作用域与去重 {#scope-and-deduplication}

包可以同时出现在全局和项目设置中。如果同一个包同时出现在两处，项目条目优先，除非项目条目设置了 `autoload: false`，此时它作为对全局条目的增量应用。包的同一性由以下方式确定：

- npm：包名
- git：不带 ref 的仓库 URL
- 本地路径：解析后的绝对路径

---

反链：

- [扩展](/book/pi/extensions/)
- [快速开始](/book/pi/quickstart/)
- [设置](/book/pi/settings/)
- [使用 Pi](/book/pi/usage/)
