# my-pi 个人维护的 Pi 扩展组合包。安装一次即可加载并配置: - `@ff-labs/pi-fff@0.10.5`:使用官方 `override` 模式接管 `find`、`grep` 和 `multi_grep`。 - 本仓库维护的 `pi-rtk-optimizer`:只处理 Bash/read 等输出压缩,默认不改写命令,也不处理搜索工具结果。 - `context-mode@1.0.169`:通过 Pi adapter 提供 `ctx_*` 工具、上下文隔离和会话连续性。 - `@tavily/pi-extension@0.1.2`:提供 Tavily 广泛搜索与页面提取;通过本地 override 暴露为 `tavily_web_search` / `tavily_web_fetch`。 - `@keenable/pi-search@0.1.2`:提供紧凑的 `keenable_search` / `keenable_fetch`,并加载其搜索 skill;API key 可选。 - `pi-mcp-adapter@2.26.0`:通过单个共享 adapter 实例接入机器现有的 CodeGraph 和 Exa 托管 MCP,避免重复注册 Pi 的全局 MCP flag 与命令。 - `pi-context-view@0.4.2`:查看上下文占用。 - 本仓库维护的 `pi-extension-codex-fast-mode`:基于 `@firstpick/pi-extension-codex-fast-mode@0.1.1`,为 Codex provider 提供跨会话持久化的 `/fast-mode`。 - `pi-lsp@0.1.7`:为 TypeScript/JavaScript、Kotlin 和 Java 提供 LSP 诊断、跳转与符号工具;TypeScript 后端由组合包内置。 - `hippo-memory-pi/`:从官方 `hippo-memory v1.33.0` 源码导入的 Pi Extension,提供项目记忆注入、错误捕获和 sleep consolidation。 - `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程压缩。 - 本仓库维护的 `pi-minimal-footer`:基于 `@ogulcancelik/pi-minimal-footer@0.1.10`,用紧凑的上下文仪表和订阅用量条替换默认 footer,并在 Codex Fast 模式开启时显示 `Fast on`。 - 本仓库维护的 `pi-notify`:基于 `@smoose/pi-notify@0.1.1`,使用 Kitty OSC 99 在 Pi 完全 settled 后通知,并支持点击精确聚焦来源 Kitty 窗口。 - `pi-condense@2.9.1`:把已完成的工具调用批次总结为可恢复的短摘要,并通过 `context_tree_query` 按需取回原始输出;组合包首次加载时默认开启。 - 本仓库维护的 `pi-ask-user`:提供模型主动调用的 `ask_user_question`,用一个顺序 TUI 同时支持单题、多题、选择题、文本题、自定义回答与提交前复核。 - 本仓库维护的 `pi-tool-search`:从完整工具定义生成并缓存经过校验的工作流分组,默认以最多 5 个动态组、28 个动态工具的 LRU 策略加载原始完整 schema,并支持原子批量激活。 - 本仓库维护的 `pi-chrome`:从上游 `0.15.46` 源码导入,通过显式会话授权接入用户当前已登录的 Chrome Profile;大体积页面快照写入 Session 临时文件并交给 Context Mode 隔离分析,21 个 `chrome_*` 工具仍由 Tool Search 按工作流加载。 - 本仓库维护的 `pi-permission-auto-review`:作为 `pi-permission-system` authorizer,使用 Codex Guardian 风格策略自动复核 `ask` 请求。 - 本仓库维护的 `pi-permission-system`:从 `@gotgenes/pi-permission-system@26.2.1` 源码导入,负责工具、路径、MCP、硬拒绝和兜底权限基线。 - 本仓库保留维护的 `pi-subagents` 源码及权限集成实现,但当前已从根组合包依赖和默认扩展加载列表中移除,不会随核心包启用。 - 本仓库维护的 `pi-ssh`:通过纯 Node `ssh2` 持久连接、显式 `ssh_cd` 远端工作区切换、SFTP 与自适应有界搜索提供独立的远端工具;Agent 只在用户明确指定已导入主机及具体任务后发起受 AutoReview 复核的连接。 - `extensions/tool-routing.ts`:保留 Pi 默认系统提示词,并按当前激活工具追加简短的工具与搜索路由规则;提供 `/dump-system-prompt` 导出当前有效提示词。 ## 安装、升级与卸载 推荐从仓库检出目录运行安装脚本: ```bash ./install.sh ``` 脚本会先执行: ```bash pi install git:git@bitbucket.org:siakitem/my-pi.git ``` 安装组合包成功后,脚本会依次检查终端环境和机器级 CLI。所有缺失项目都逐项显示 `[y/N]`,默认拒绝,仅在用户明确选择 `Y` 后修改机器或用户配置: - 检查 Kitty;macOS 使用 Homebrew cask 安装,其他系统使用 Kitty 官方安装器。Kitty 可用后继续检查并可通过官方 `themes` kitten 配置 `Solarized Dark`。 - 检查 Oh My Zsh。安装采用官方 unattended 模式,不切换默认 shell、不立即启动 Zsh, 也不覆盖现有 `.zshrc`。 - 检查 Powerlevel10k;可克隆到 Oh My Zsh 的 custom themes 目录,并把仓库内置的 `config/p10k.zsh` 原子同步到 `~/.config/my-pi/p10k.zsh`(遵循 `XDG_CONFIG_HOME`)。 该配置来自当前使用的 Powerlevel10k Rainbow/ASCII 单行紧凑主题;用户自己的 `~/.p10k.zsh` 不会被覆盖。脚本只在 `.zshrc` 中写入带首尾标记的主题和加载受管块。 - 逐项检查 `git`、`zsh-autosuggestions` 和 `zsh-syntax-highlighting` 是否已经在 `.zshrc` 的 `plugins` 数组中启用。后两个插件缺少源码时会先克隆到 Oh My Zsh 的 custom plugins 目录;语法高亮按最后一个插件处理。 - 最后继续检查 `codegraph`、`kotlin-lsp`、Java 21+ 和 `jdtls`。Kotlin、Java 和 JDT LS 的自动安装使用 Homebrew。 脚本首次实际改动 `.zshrc` 前会在同目录创建带时间戳的备份。Oh My Zsh loader、 Powerlevel10k 主题/配置和各 Zsh 插件使用 `# >>> my-pi: >>>` 到 `# <<< my-pi: <<<` 的受管块协议;以后只替换块内内容,块外用户配置保持不变。 标记缺失、重复或不完整时脚本会拒绝修改。若机器没有所需的 Homebrew、`curl` 或 `git`, 脚本会保留已完成的安装结果、继续检查其他项目,并最终返回非零状态。 `rtk` 只供默认关闭的命令改写使用,因此不会作为必装依赖检查。 也可以绕过脚本,直接运行上面的 `pi install` 命令,此时机器级 CLI 不会被检查。 升级已安装的组合包请使用独立脚本: ```bash ./update.sh ``` 升级脚本先执行: ```bash pi update git:git@bitbucket.org:siakitem/my-pi.git ``` 默认 Git 组合包若在 Pi 内部清理大型 `node_modules` 时因目录仍非空而留下 `.pi-update-incomplete` 标记,脚本不会在升级前破坏性预清理。首次 `pi update` 失败后,它只对默认来源推导出的缓存 checkout 进行恢复,并同时校验中断标记、canonical Git 根目录和精确 `origin`;校验通过后最多连续执行 4 次依赖清理,再只重试一次 `pi update`,由 Pi 自己重新安装依赖并清除标记。自定义来源、缺少标记或身份不匹配仍立即失败,不会清理猜测出的路径。 随后只处理已经安装的项目,未安装项直接跳过且不会询问安装:Kitty 及已启用的 Solarized Dark、Oh My Zsh、Powerlevel10k、两个第三方 Zsh 插件、CodeGraph,以及由 Homebrew 管理的 Kotlin LSP、Java 21 和 JDT LS。升级前会先刷新或查询对应的远端版本: Git checkout 在 `fetch` 后比较本地与上游提交,Homebrew 包在刷新元数据后通过 `brew outdated` 判断,Kitty 官方安装和 CodeGraph 则比较本地版本与官方最新发布版本。只有检测到版本不同时才 下载并替换;无法确认安装来源或无法可靠比较版本时保留现状并报告。 日志中的“Zsh 插件未安装,升级流程跳过”不是升级失败:升级脚本不会新增用户此前未选择的 插件。需要补装时重新运行 `./install.sh`,并在对应的逐项询问中明确选择 `Y`。 升级时会优先从 `pi update` 后的已安装组合包目录读取最新配置。对于 Pi agent 目录中的 `settings.json`,只有 `toolSearch` 完整匹配旧组合包生成的 `3` 组 / `20` 工具默认快照时,才会备份并原子迁移到当前 `5` / `28` 默认值;任何字段不同、结构无效或存在自定义工具时都不会被覆盖。Powerlevel10k 受管副本只在内容不同时备份并原子同步;`.zshrc` 也只更新已有的 my-pi 受管块,不触碰块外配置。因此安装流程负责补齐缺失项,升级流程只升级已安装项并同步可明确识别的受管配置。 首次获得这项迁移能力时需要执行已经包含该逻辑的新版 `update.sh`;旧脚本正在运行时不会因为 `pi update` 替换包内容而自动获得后半段迁移步骤。如果刚通过旧脚本升级到含迁移逻辑的版本,可再运行一次更新后的脚本。 卸载组合包: ```bash ./uninstall.sh ``` 卸载脚本只调用 `pi remove`,不会删除 Kitty、终端主题、Oh My Zsh、Powerlevel10k、Zsh 插件、CodeGraph、Kotlin LSP、JDT LS 或 Java,因为这些用户环境或机器级工具可能仍被其他 项目使用。三个脚本都可通过 `PI_PACKAGE_SOURCE` 覆盖默认包源, 例如在本地检出中测试: ```bash PI_PACKAGE_SOURCE="$PWD" ./install.sh PI_PACKAGE_SOURCE="git:git@bitbucket.org:siakitem/my-pi.git" ./update.sh ``` 根 `package.json` 对外部依赖使用精确版本,对本仓库维护的包(包括 Codex Fast mode)使用 `file:` 路径;`package-lock.json` 固定完整依赖树。不要再用项目级 `.pi/settings.json` 重复安装这些扩展,否则同一扩展可能被加载两次。 Hippo 官方 Pi Extension 存在于上游 Git 仓库的 `extensions/pi-extension/`,但没有包含在 `hippo-memory@1.33.0` npm tarball 中。本仓库从官方 `v1.33.0` / `e928179a3b35e8fe5837878aed071d6025ced45c` 导入源码到 `hippo-memory-pi/` 并直接加载; 匹配的 CLI 版本由 `config/hippo-memory-version` 声明。`install.sh` 会在 CLI 缺失时询问是否执行 `npm install -g hippo-memory@<固定版本>`,但安装脚本不会选择或初始化项目。进入目标项目后可在 Pi 中执行 `/plugin_init`:命令会显示当前目录并要求确认,以 `.codegraph/codegraph.db` 和 `.hippo/hippo.db` 为 初始化标志,只为缺失状态运行 `codegraph init` 与 `hippo init`;全部成功后通过 Pi 官方热重载重新连接 CodeGraph MCP 并重新触发 Hippo session start。也可以继续在终端手动执行两个 CLI 的 `init` 命令。 默认配置不需要系统 `rtk` CLI。只有以后在 `/rtk` 中主动开启 RTK command rewriting 时,才需要另外安装 `rtk` 可执行文件。 CodeGraph 本体不由组合包安装。需要使用 CodeGraph 的机器应自行确保 `codegraph` 在 启动 Pi 的 `PATH` 中。组合包只有在用户显式调用 `/plugin_init` 并确认当前项目后才会创建 `.codegraph/`;安装、升级和普通启动流程不会创建或维护索引,也不会修改 CodeGraph 的更新或遥测设置。 ## 组合行为 ### 模型主动提问 `pi-ask-user/` 把 Pi 上游的单题与多题示例合并为唯一的 `ask_user_question` 工具;不提供 `/qna` 或其他用户命令。模型只有在继续任务确实缺少用户决定、偏好、确认或澄清时才应加载 `user-interaction` 组并调用它,不得重复询问直接消息中已有的信息。工具仅在交互式 TUI 中运行,最多一次提交 8 个问题,支持选择、自由文本、显式跳过、返回修改和最终复核;取消结果不会作为 AutoReview 的授权证据。 ### 工具与搜索路由 `extensions/tool-routing.ts` 不替换 Pi 默认系统提示词,而是在每轮开始前根据当前激活工具追加简短规则。代码结构、调用关系和待修改 symbol 优先使用 CodeGraph,定义、引用、类型和修改后诊断优先使用 LSP;仓库字面搜索先用 FFF `find` 缩小文件或目录范围,再在已收敛的路径中用 `grep`/`multi_grep` 获取行号。宽泛搜索命中大量结果、发生截断或达到上限时,应继续缩小路径、glob 或 pattern,而不是提高 limit 或输出全部结果。 在线搜索默认按任务只选一个服务:关键词不确定、新闻/近期话题或需要较多候选来源时优先 Tavily;官方/API 文档、版本信息、论文和高确定性事实确认优先 Exa;中文政策、政府公告、中文网页、站点限定和日期筛选优先 Keenable。只有来源质量或不确定性确实需要时才跨服务复核,避免默认把三套结果全部塞进上下文。 日志、测试/构建输出、工作区内大文件的探索/分析/总结以及不可预测的大输出优先交给 Context Mode。只有确实需要精确源码或准备修改时,才用带 `offset/limit` 的 Hashline `read` 读取最小区域并取得 `LINE#HASH` 锚点,随后用锚定 `edit` 修改;成功编辑返回的新锚点可继续复用,只有锚点过期或下一目标区域尚未展示时才重新读取。已有工具结果足够时停止检索,避免对同一问题依次重复调用 CodeGraph、FFF 和 `read`。 使用 `/dump-system-prompt` 可将当前扩展所见的有效提示词写入当前项目的 `.pi-debug/effective-system-prompt.md`。`.pi-debug/` 属于本地诊断输出,默认不提交。 ### 接管当前 Chrome 组合包固定加载 `pi-chrome@0.15.46`,但不会自动取得浏览器控制权。首次安装后在 Pi 中运行 `/chrome onboard`,按提示在 `chrome://extensions` 以 Developer mode 加载组合包内的 unpacked Chrome 扩展,再执行 `/reload` 与 `/chrome doctor`。每个 Pi session 仍需由用户显式运行 `/chrome authorize`;可用 `/chrome revoke` 立即撤销。Bridge 只监听 `127.0.0.1:17318`,Chrome 扩展具有广泛的 tabs/scripting/debugger 权限,应只从可信组合包安装。 授权后注册的 21 个 `chrome_*` 工具不会常驻提示词;Tool Search 将它们分为 `chrome-navigation`、`chrome-interaction` 和 `chrome-debugging`。普通网页资料发现仍使用 Tavily/Exa/Keenable,只有需要读取登录态页面或实际操作当前 Chrome 时才加载 Chrome 组。 `chrome_snapshot`、`chrome_find` 和带 `includeSnapshot=true` 的交互不会再把完整页面结构直接塞进模型上下文:完整 JSON 只写入当前项目 `.pi/chrome-context/` 下按 Session/目标隔离的临时文件,工具结果仅返回相对路径和小型摘要。模型应立即用 `ctx_execute_file` 从该文件提取下一步所需的 uid、文本或状态,不能用 `read` / `cat` 重新读入全文。每个目标只保留最新快照;页面操作后旧快照失效,Session 结束、`/chrome revoke` 或授权过期时清理。 ### 按需加载工具 schema `pi-tool-search/` 从上游 的 `v0.3.6`、commit `ddfb23646fd3957b791214de278e23aa393c9b13` 导入,并像 `pi-rtk-optimizer/` 一样由本仓库直接维护;它不是 submodule,不加载 npm 预编译入口,也不保留嵌套 `.git`、上游 `.pi` 状态或构建产物。来源、许可证说明和本地差异记录在 `pi-tool-search/UPSTREAM.md`。 本地源码直接使用 `@earendil-works/pi-coding-agent`、当前 `typebox`、`ModelRegistry.complete()` 与 `setActiveTools()`,不安装、别名映射或加载旧 `@mariozechner` runtime,也不使用 provider payload 改写、代理执行或隐藏 `sendMessage` 循环。 新 session 默认常驻 Pi 核心 `read`、`write`、`edit`、`bash`、`grep`、`find`,以及 `codegraph_explore`、`lsp_diagnostics`、`ctx_execute`、`ctx_execute_file`、`ctx_batch_execute` 和 `tool_search`;Windows 上额外把内置 `powershell` 与 `bash` 作为同类本地 Shell 核心工具固定启用,非 Windows 平台则从目录中过滤它。组合包在 `pi-tool-search/extensions/bundle-groups.ts` 中为自身暴露的工具预置权威分组,包括本地文件导航、SSH 远端文件/命令、Chrome 导航/交互/调试、用户交互、CodeGraph/LSP、Tavily、Exa、Keenable、Context Mode 执行/知识库/观测/管理、Memory 查询/维护、Skill 和 MCP 管理。不可用、已固定或尚未授权而未注册的可选工具会自动从动态组中滤除。 标准组合包的全部隐藏工具都能命中预置目录,因此首次使用不调用模型、不生成用户缓存,也不把完整隐藏 schema 发送给 provider。只有用户另外安装了未识别工具,并且当前调用不是精确加载已有分组时,才可使用当前已认证模型补充目录;精确已有分组始终立即按当前确定性目录激活,不等待无关未知工具的模型增强。模型结果必须保留组合包预置分组,否则直接拒绝。有效增强缓存以 `0600` 写到 agent 目录的 `tool-search/catalog-v1.json`,调用用量计入工具结果。用户 `groupOverrides` 的优先级高于预置目录;`/tool-search-rebuild` 会恢复预置目录,`/tool-search-status` 显示目录来源、容量、LRU 顺序和最近淘汰原因。 动态组默认最多同时加载 5 个、每个模型生成组最多 8 个工具、全部动态组最多 28 个工具。`tool_search.groups` 可在一次调用中原子加载最多 5 个精确组;完整请求本身超限时保持原状态。加载或调用组内工具会更新 LRU,超限时先卸载最久未使用且不在本次请求内的组。自然语言 query 对精确工具名和已提交 workflow alias 加权,弱匹配或近似同分只返回候选。首次纯增加载继续使用 Pi 原生增量传播;发生卸载和加载的替换由 Pi 自动走安全 fallback。 Pi 的用户级配置文件通常是 `~/.pi/agent/settings.json`(准确位置为 Pi agent dir 下的 `settings.json`)。组合包首次加载仅在其中缺少对应字段时写入: ```json { "toolSearch": { "alwaysEnabled": [ "codegraph_explore", "lsp_diagnostics", "ctx_execute", "ctx_execute_file", "ctx_batch_execute" ], "showToolSearchFooterStatus": false, "maxActiveGroups": 5, "maxToolsPerGroup": 8, "maxDynamicTools": 28, "groupOverrides": {}, "bundleDefaultsVersion": 2 } } ``` 扩展正常加载只补充缺失字段,不覆盖用户已有配置;首次创建完整 Tool Search 默认段时也写入 `bundleDefaultsVersion: 2`。用户显式运行新版 `update.sh` 时,脚本会在 `pi update` 成功后使用更新后组合包中的 Node helper 检查完整旧默认快照:只有精确匹配旧版 `3`/`20` 默认值才会创建权限 `600` 的时间戳备份并原子替换为当前配置;任何自定义或无效配置都会保留,提交前检测到文件内容变化也会中止。`alwaysEnabled` 中的精确工具名属于固定工具,不占动态组额度;`groupOverrides` 可把指定工具强制归入命名组。默认关闭状态行,避免与 minimal footer 叠加。 ### 精确读写归 Hashline 组合包固定加载 `pi-hashline-edit@0.8.3`,以带 `LINE#HASH` 行锚点的实现覆盖 Pi 内置 `read` 和 `edit`。`extensions/hashline.ts` 在加载扩展前把 `config/pi-hashline-edit.json` 同步到 `~/.pi/agent/hashline.json`:`hashLength` 保持最小的 `2`,`grep` 强制关闭以避免与 FFF 冲突,`replaceText` 关闭以要求修改使用可验证锚点。 Hashline 不负责压缩大文件;每行锚点本身还会增加少量 token。上下文节省来自先用 CodeGraph/LSP 定位、再用 Context Mode 隔离分析,最后只对真正准备修改的区域执行小范围 Hashline `read`。因此不应为了探索、计数、比较或总结而直接读取完整大文件。 ### 搜索归 FFF `extensions/fff-override.ts` 强制设置 FFF 官方的 `PI_FFF_MODE=override`(显式传入 `--fff-mode` 仍按 FFF 官方优先级覆盖它)。FFF 替换 Pi 的 `find` 和 `grep`,并提供 `multi_grep`;RTK 对所有 `grep` 工具结果直接跳过, 也默认关闭 Bash 命令改写,因此不会把 `rg`、`grep`、`find` 或 `fd` 改写到 RTK。 ### 输出压缩归 RTK RTK 保留 Bash、read、build、test、lint 和 Git 输出压缩。默认 `read` 的有损压缩 仍关闭;可用 `/rtk` 查看或调整。旧机器已有的 RTK 配置若没有 `commandRewritingEnabled` 字段,也会按 `false` 归一化,不需要迁移配置。 ### 大输出归 Context Mode Context Mode 直接加载 npm 包内置的 Pi adapter 和 skills,不需要额外写入 `~/.pi/agent/mcp.json`,也不需要全局安装 `context-mode` 命令。它提供 `ctx_*` 工具, 将批量读取、命令研究和网页内容先在隔离进程中处理,再把收敛后的结果送入上下文。 FFF 仍负责精确字面搜索;RTK 继续压缩未走 Context Mode 的 Bash、build、test、lint 和 Git 输出。Context Mode 不替换这两个扩展的现有配置。 ### SSH 服务器配置 `pi-ssh` 运行时使用纯 `ssh2`,不依赖系统 `ssh` 或 `sshpass`。首次使用前显式导入需要的 OpenSSH alias: ```bash ./ssh_config.sh import packaging-server ``` 脚本只在导入阶段调用 `ssh -G` 解析用户选中的 alias,随后交互选择 SSH Agent(包括 1Password)、私钥文件或密码认证、显示并确认服务器 Host Key、测试连接,再把完整配置写入 `${XDG_CONFIG_HOME:-$HOME/.config}/my-pi/pi-ssh/hosts.enc`。Agent 模式只保存 socket 路径,私钥仍留在 Agent 中;邻接的随机 `vault.key` 用于 AES-256-GCM 解密,目录与两个文件在 POSIX 上分别是 `700` / `600`。该加密只避免误看或单独泄漏密文,能读取两文件的同一用户仍可解密。 可用 `./ssh_config.sh list|update|remove|rotate-key` 管理已导入主机。第一版拒绝 `ProxyJump` / `ProxyCommand`,且不会自动读取远端 `AGENTS.md` 或 `CLAUDE.md`。连接不再通过 `/ssh`、`--ssh` 或 session resume 建立:用户在具体远端任务中明确指定已导入 host ID 后,Agent 把受复核、串行且可取消的 `ssh_connect` 作为独立步骤调用并等待成功,再使用其他 `ssh_*` 工具;连接动作及后续操作均进入 `ask → auto-review`,相对远端路径会在预览中显示请求值和解析后的绝对路径,会话结束自动断开。SSH transport 在会话内持久,独立命令最多使用 4 路有界并发 exec channel,但每次 `ssh_bash` 都启动独立的非交互 Shell;需要持续改变后续远端操作的工作目录时,Agent 同样必须把受复核且串行执行的 `ssh_cd` 作为独立步骤调用并等待成功,而不是依赖某次 Shell 中临时执行的 `cd`。 远端文件搜索使用独立的 `ssh_find` / `ssh_grep`:在每次获批调用内按服务器现有能力选择 `fd/fdfind → git ls-files → find` 或 `rg → git grep → find+grep`,不安装远端软件,并以最大 200 条结果、单行截断和 `truncated` 标记约束返回。搜索目标作为绝对参数与当前远端执行 cwd 分离,因此 `ssh_grep` 可直接搜索单个文件而不会尝试把文件当目录进入;30 秒超时会报告解析后的 root 并提示先用 `ssh_find` 缩小范围。远端 HOME/cwd 通过可取消、有界随机标记探测获得,畸形结果不会更新连接状态。RTK 只压缩 `ssh_bash` 的非搜索输出,不改写远端命令,也不处理 `ssh_find`、`ssh_grep` 或 `ssh_read`。详细说明见 [`pi-ssh/README.md`](pi-ssh/README.md)。 ### 在线搜索服务 运行 `./search_config.sh` 可用隐藏输入依次配置 Tavily、Exa 和 Keenable;也可一次无交互配置: ```bash ./search_config.sh --tavily '...' --exa '...' --keenable '...' ``` 只传部分参数时保留其他服务的已有值。脚本把 key 原子写入 `${XDG_CONFIG_HOME:-$HOME/.config}/my-pi/search.env` 并设置权限为 `600`; `MY_PI_SEARCH_CONFIG` 或 `--config` 可覆盖路径。组合包在搜索扩展初始化前加载该文件, 但调用 Pi 时显式传入的同名环境变量优先。配置文件不属于仓库,不会随安装包提交。 Tavily 通过 `extensions/tavily-override.ts` 加载官方扩展。override 只改工具身份,不改官方执行逻辑:上游 `web_search` / `web_fetch` 被注册为 `tavily_web_search` / `tavily_web_fetch`,label 和提示词中的内部工具引用也同步带上 Tavily 标识。使用前需设置 `TAVILY_API_KEY`。Tavily 适合广泛发现,但来源可能混杂且输出较长,应从较小的 `max_results` 开始,非必要不返回 raw content。 Keenable 直接加载 npm 包的扩展和 skill,默认无需 key;设置 `KEENABLE_API_KEY` 可提高速率限制。它适合中文内容、`site` 限定和发布日期筛选。搜索结果保持紧凑,只对选中的 URL 调用 `keenable_fetch`。 `extensions/mcp.ts` 通过单个 `pi-mcp-adapter` 实例同时连接 Exa 与 CodeGraph,避免两个 adapter 重复注册 `--mcp-config`、`/mcp` 和 `/mcp-auth`。其中 Exa 连接 `https://mcp.exa.ai/mcp`,并把 MCP 原始工具映射为统一的来源前缀形式:`exa_web_search`、`exa_web_fetch` 和 `exa_web_search_advanced`。配置 `EXA_API_KEY` 后通过 `x-api-key` 请求头认证,不把 key 放进 URL。Exa 适合官方文档、技术资料、版本信息和论文;高级搜索必须显式限制结果数量与返回文本长度,避免响应过大。 根测试会扫描所有本地扩展入口,强制只有 `extensions/mcp.ts` 可以创建或导入 `pi-mcp-adapter`。新增 MCP 服务必须合并进这个共享实例,不能再增加独立 adapter 入口;隔离 Pi 加载仍作为发布前的运行时验证。 ### CodeGraph 只负责连接 同一个 `extensions/mcp.ts` adapter 配置启动 `codegraph serve --mcp`,不会读取或覆盖用户已有的 MCP 配置。连接采用 `keep-alive`,并只把官方当前主工具 `codegraph_explore` 作为同名 Pi 工具暴露; CodeGraph 的文件 watcher 由该 MCP 进程自身维护。 若机器没有 `codegraph`,或当前项目尚未建立索引,CodeGraph 会报告连接/初始化错误, 其他扩展仍可正常工作。安装与索引状态可在机器上自行检查: ```bash codegraph --version codegraph status ``` 在当前项目需要同时初始化 CodeGraph 和 Hippo 时,可直接执行: ```text /plugin_init ``` 该命令拒绝文件系统根目录和用户主目录,先确认两个 CLI 均可用,再依次初始化缺失数据库状态。任一步失败都不会热重载,也不会回滚此前已成功完成的初始化;两者已初始化时仍可用该命令快速热重载扩展。 ### 权限基线自动部署 `pi-permission-system/` 从上游 `pi-permission-system-v26.2.1` tag 导入,初始源码快照为 `ec4fdb11343dc94f7185b113e559a4cf9f8dc035`。根包通过本地 `file:` 依赖提供其运行时依赖,并由包装入口直接加载仓库源码,不再加载 npm 包中的实现。 `extensions/permission-system.ts` 在权限扩展注册前,把仓库中的 `config/pi-permission-system.json` 同步到 Pi agent 目录。仓库文件是权威配置;直接在 运行目录通过 UI 修改的策略会在下次加载组合包时被覆盖,长期调整应提交到本仓库。 当前策略按类别划分: - 默认工具:默认允许,避免常规编码操作反复确认;FFF 的 `grep`、`find`、 `multi_grep` 明确允许。 - 搜索边界:直接通过 Bash 调用 `rg`、`grep`、`find`、`fd`、`git grep` 拒绝,统一走 FFF。 - 路径与凭据:外部目录询问;环境文件、SSH/GPG、云凭据、Keychain 和 Pi 认证文件拒绝; `.env.example` 作为无密钥模板允许。 - Git:状态、diff、日志、对象查看等只读命令允许;其他 Git 命令进入 `ask`,由自动复核 authorizer 裁决。 - Bash 变更操作:Git 非只读操作、包管理、文件变更、系统操作、网络访问和环境导出均由权限基线先判定;命中 `ask` 后再进入自动复核。 - MCP 与 Skill:列举 MCP 状态允许,调用其他 MCP 工具进入 `ask`;本地 Skill 加载允许。 `permissionReviewLog` 已开启,后续可依据真实命中记录继续收敛规则。 ### Permission Auto Review 与权限基线的边界 `pi-permission-auto-review/` 从上游源码仓库的 `@mzwing/pi-permission-auto-review@0.2.0` tag 导入,初始源码快照为 `8d196e4ef0884cac8326c366191dad3f585d470a`。该目录与 `pi-rtk-optimizer/` 一样由本仓库直接维护,不依赖 npm 中的预编译扩展包。 扩展以 `auto-review` 名称注册到 `pi-permission-system` 的 authorizer chain。只有权限基线先得到 `ask` 时才调用 reviewer:模型返回 `allow` 时自动批准,返回 `deny` 时直接拒绝,配置、模型、认证、超时或响应异常时返回 `defer` 并继续走正常人工提示。这样只有一条权限链,不再存在两个独立 `tool_call` gate 造成的重复审批。 边界保持如下: - `allow`:权限基线已明确允许的常规操作不会调用 reviewer。 - `deny`:Bash 直搜、敏感凭据路径等硬拒绝不会交给 reviewer,也不能被其绕过。 - `ask`:Git 非只读操作、包管理、文件/系统/网络/环境操作和普通 MCP 调用交给 reviewer;`path` 仍全部受 delegation envelope 保护。`external_directory` 允许内置只读路径工具(`read`、`find`、`grep`、`ls`)接受 reviewer 的 `allow`,`write`、`edit`、Bash、未知工具及其他外部目录访问仍降级为人工确认。 reviewer 默认使用 `openai-codex/codex-auto-review`、low reasoning 和内置 Codex Guardian 风格策略,并读取当前 session active branch 中的可信用户证据。可通过 `/permission-auto-review` 查看或调整全局/项目配置;无配置时使用源码内置默认值。 ### TypeScript、Kotlin 与 Java LSP `extensions/lsp.ts` 会把 `config/lsp.json` 部署到全局 `~/.pi/agent/lsp.json`,其中启用: - `typescript-language-server@5.3.0 --stdio`:匹配 TypeScript/JavaScript 及 JSX/TSX、MTS/CTS、MJS/CJS;组合包同时固定 `typescript@6.0.3` 作为 `tsserver` 后端。 - `kotlin-lsp --stdio`:匹配 `.kt`、`.kts`。 - `jdtls`:匹配 `.java`;官方 wrapper 会按当前项目工作目录选择 cache data 目录。 TypeScript LSP 通过组合包内 Node 和 `typescript-language-server` CLI 直接启动,不依赖、调用或拉起 VS Code GUI;部署配置时会把包内 CLI 的绝对路径写入全局配置。它优先使用项目自身可用的 TypeScript,否则回退到组合包固定的 TypeScript 6 后端。 Kotlin 与 Java 按 Gradle、Maven 或 Git marker 定位项目根,忽略常见构建输出,并为大型 Android/Gradle 项目预留 120 秒启动时间。Kotlin 与 Java 的 language server 可执行文件不由根包安装;使用前需 确保 `kotlin-lsp` 和 `jdtls` 位于启动 Pi 的 `PATH`。Kotlin 官方 Homebrew 安装方式为: ```bash brew install JetBrains/utils/kotlin-lsp ``` JDT LS 需要 Java 21 或更高版本;可使用带 `jdtls` wrapper 的官方发行包或系统包。 ### Hippo Memory 官方扩展要求全局 `hippo` CLI,并要求目标项目存在 `.hippo/`。组合包加载仓库内官方扩展源码, 注册 `hippo_recall`、`hippo_remember`、`hippo_outcome`、`hippo_status` 和 `hippo_context` 五个工具。 Session 启动时它注入项目记忆上下文,失败工具结果经过噪声过滤、每 Session 上限和去重后自动记录, Session 关闭时运行 `hippo sleep`,从 Git 学习、整理记忆并执行官方共享逻辑。项目 `.hippo/` 是 本机记忆状态,本仓库默认忽略提交。 Hermes 的 `memory_add` / `session_search` / `skill_manage` 与 Markdown/SQLite 数据不会被 Hippo 自动迁移; 切换扩展不会删除 `~/.pi/agent/pi-hermes-memory/` 或 `~/.pi/agent/projects-memory/` 中的旧数据。需要保留的 旧记忆应另行审核后导入,不在安装、升级或卸载流程中自动转换或删除。 `install.sh` 只对缺失的 Hippo CLI 询问一次,默认拒绝;缺少 npm 时保留已完成的组合包安装并报告失败。 脚本不会扫描仓库、选择目录或执行 `hippo init`。`update.sh` 只处理已经存在且确认属于 npm 全局安装的 Hippo CLI:从升级后的组合包读取固定版本,先通过 npm 确认版本存在,再比较本地版本,只有不同时才升级。 `uninstall.sh` 移除组合包后询问是否一并执行 `npm uninstall -g hippo-memory`,默认保留;无论选择什么, `.hippo/` 和用户记忆数据都不会被脚本删除。 ### Kitty 完成通知 `pi-notify/` 直接加载本地维护源码。它只在交互式 TUI 中监听 `agent_settled`,因此自动重试、自动 compaction 和排队 follow-up 完成前不会提前通知。Kitty 后端使用 Base64 OSC 99、每个 Pi Session 独立的稳定通知 ID、显式 `a=focus`,并默认设置 `o=always`:即使来源 Kitty window/pane 正在接收 键盘输入也会显示通知,点击通知由 Kitty 返回原始来源;仍可通过环境变量改用 `unfocused` 或 `invisible`。 默认忽略不足 3 秒的短任务。`/notify on|off|test|status` 可控制当前 Session;持久默认通过 `PI_NOTIFY_ENABLED`、`PI_NOTIFY_MIN_SECONDS`、`PI_NOTIFY_VISIBILITY`、`PI_NOTIFY_ACTION`、 `PI_NOTIFY_MESSAGE_SOURCE` 等环境变量配置。`PI_NOTIFY_MESSAGE_SOURCE=none` 可避免把回复摘要发送到 macOS 通知中心。Kitty 位于 tmux 内时需要 `set -g allow-passthrough all` 并重启 tmux server。 完整配置和上游差异见 [`pi-notify/README.md`](pi-notify/README.md)。 ### Codex 原生远程压缩 远程压缩只对 `openai-codex/openai-codex-responses` 生效,使用上游默认配置:在 turn boundary 达到 90% 上下文占用时触发,并写入 Pi 原生 compaction boundary。失败时保持原历史且不静默 回退到文本摘要;checkpoint 与创建它的 Codex model 绑定。 ### Pi Condense 组合包加载时会只为 `contextPrune` 中缺失的字段补入默认策略,任何用户显式值(包括 `/pruner off` 写入的 `enabled: false`)均优先且不会被覆盖。默认使用 `agent-message` 触发模式和 `turn` 批处理;正常上下文达到窗口的 73.5% 时中途整理,单轮增长达到窗口的 4% 时提前整理。对于 272K 上下文模型,两者约为 200K 和 11K tokens;其他模型按各自窗口比例计算。摘要使用当前默认模型和默认 thinking,连续 90 秒无输出才判定空闲超时,每次最长运行 5 分钟,并保留未压缩或摘要过大等跳过提示。 同一用户任务中的多轮工具调用通常在最终文本回复后触发整理,预算触发器则可在长任务中提前处理;后续上下文只保留摘要和 `t1`、`t2` 等引用。需要原文时,模型可调用 `context_tree_query({ toolCallIds: ["t1"] })` 恢复。 常用命令:`/pruner status` 查看状态,`/pruner settings` 调整配置,`/pruner now` 立即处理待总结批次,`/pruner tree` 浏览已归档调用,`/pruner stats` 查看累计成本和节省,`/pruner off` 关闭。配置保存在 Pi agent 目录 `settings.json` 的 `contextPrune` 字段。建议保留默认的 skill 路径保护,并把必须逐字复用输出的工具加入 `protectedTools`。 它与 Context Mode 的职责不同:Context Mode 避免大型原始输出进入当前模型上下文,Pi Condense 则压缩已经进入会话、且已完成使用的历史工具结果。它也不替代 Codex 原生远程 compaction;不希望自动整理历史时可运行 `/pruner off`。 ### Codex fast mode 该扩展只在 `openai-codex` provider 的 Responses 请求上加入 `service_tier: "priority"`。使用 `/fast-mode on|off` 修改当前分支状态时,也会把全局默认值原子写入 Pi agent 目录下的 `extensions/pi-extension-codex-fast-mode/config.json`;新会话继承该默认值,恢复已有会话时仍由分支内最新记录优先。`/fast-mode status` 同时显示当前分支状态和新会话默认值。配置目录与文件分别使用 `0700` / `0600` 权限;配置缺失或无效时安全回退为关闭。其他 provider 不受影响。