分类 默认分类 下的文章

| 撰写日期:2026 年 9 月 19 日

一、省流

Pi 是开源终端编码代理,官方定位是 minimal agent harness——让 Pi 适配你的工作流,而不是反过来。我在它上面搭了 24 个插件、52 个 skill、7 个 MCP server、跨会话记忆系统和默认本地推理,把它变成能多代理协作、省 token、跑浏览器、跨会话记住上下文的全能终端代理。核心不是包的数量,是三档扩展体系(Skill/MCP/Extension)和持续审计的纪律。

二、正文

(一)起点:裸代理循环与四个目标

Pi(npm 包 @earendil-works/pi-coding-agent)是一个开源的终端 AI 编码代理:给它一个任务,它在你本地的项目里读写文件、跑命令、调用工具。

npm install -g @earendil-works/pi-coding-agent   # 安装
pi                                                # 进入交互界面

开箱的 Pi 是一个裸的代理循环:收 prompt → 调模型 → 执行工具 → 回传结果,循环直到不再调工具。它故意保持最小——没有内置记忆、没有浏览器、没有代码智能,官方态度是 "Adapt Pi to your workflows, not the other way around"。

最小不是限制,是起点。我的配置目标有四个:

  1. 多代理协作:多个 Pi 会话互发消息,手机远程接管
  2. 省 token:基础上下文压到最低,长任务不爆窗
  3. 跑浏览器:真实 Chrome 的点击、截图、网络抓包
  4. 跨会话记忆:关掉终端,下次还知道我是谁、踩过什么坑

(二)三档扩展体系:改造 Pi 的骨架

Pi 的所有扩展能力分三档,从轻到重:

档位形态成本适合
Skill一个 SKILL.md,描述某类任务怎么做零代码,模型按需加载流程知识:怎么调试、怎么发版、怎么运维
MCP server任何语言写的服务,注册进 mcp.json中量,接外部进程外部能力:数据库、API、浏览器、文档源
ExtensionTypeScript 模块,订阅生命周期事件重量,可拦截/修改/阻止工具调用深度改造:安全钩子、自定义工具、UI 接管

Extension 是最强的一档。它能订阅 tool_call(拦截/修改/阻止工具调用)、tool_result(改写结果)、before_agent_start(注入消息、改提示词)等事件,还能注册自定义工具、命令、快捷键、主题:

import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

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("危险", "允许 rm -rf?");
      if (!ok) return { block: true, reason: "用户阻止" };
    }
  });
}

生态方面,所有带 pi-package 关键字的 npm 包都会出现在官方包市场pi add npm:@scope/pkg 一条命令装包。Skill 实现了 Agent Skills 标准,Claude Code / Codex 的 skill 可以直接用——我本机 15 个共享 skill 就是多个 agent 复用的同一份文件。

选型逻辑很简单:能用 Skill 解决的绝不写 Extension,能用现成包解决的绝不自己写。24 个插件里只有 3 个是自写扩展(自定义启动头、任务计时、提示词片段),其余全是社区包。

(三)按用途选型:六个方向

1. 记忆:pi-hermes-memory

跨会话记忆是四个目标里最难的。我最终选了 pi-hermes-memory:SQLite FTS5 全文索引,记忆条目分 memory/user/project/failure 四个目标,配 memory_searchsession_search(搜历史会话原始记录)、skill_manage(程序化生成 skill)等工具。

它最有价值的设计是失败记忆:踩过的坑、被纠正的判断自动归档,下次遇到同类问题先搜记忆再动手。我本机已积累 220 条记忆、252 个会话。

迁移过程本身是个经验:从 pi-memory 迁过来,两个包都注册 memory_search 无法并存,走"全量备份 → 格式转换 → 卸旧装新 → 自动迁移"四步,终验 35/35 条目全入库,零丢失。教训是记忆系统选型要早,数据量大了迁移成本指数上升

2. 代码智能:pi-lens + tokensave 双轨

pi-lens 提供 AST 级代码理解:基于 ast-grep 的结构化搜索/替换(比纯文本 grep 精准)、tree-sitter 语法规则检查、LSP 诊断(跑构建前主动查类型错误)。tokensave 维护一个 485M 的符号索引库,按调用关系和影响范围分析,是代码任务的第一入口——先符号定位,禁止盲目 grep 翻文件。

两者并行不冲突:tokensave 索引最深,pi-lens 实时性最好(LSP 诊断是现算的)。双轨冗余看着浪费,实际是保险——任一索引过期时另一个兜底。

3. Web 接入:pi-web-access + 7 个 lazy MCP

pi-web-access 提供 web_search(20+ 搜索引擎)、fetch_content(URL 转 markdown,支持 YouTube 转录、PDF 提取)、source_check(结构化来源核查)三个工具,是 web 能力的主力。

MCP 侧 7 个 server 全部设 lifecycle: lazy(按需启动,不常驻),各管一摊:

  • context7:实时拉取第三方库最新文档,避免用过时训练知识
  • chrome-devtools:真实 Chrome 的 29 个工具(点击/截图/网络抓包/性能分析),headless 跑
  • context-mode:大输出沙箱 + FTS5 知识库,11 个工具用 directTools: "search" 接入——基础 prompt 只多一个服务器名,需要时当场激活
  • tokensave / tavily / sequential-thinking / firecrawl:符号索引、搜索、多步推理、网页抓取

lazy 是省 token 的关键设计之一,下一节细说。

4. 工作流:让代理按纪律干活

这一组不增加能力,增加纪律:

  • ponytail:YAGNI 审查,强制"最懒但能用的方案",先质疑任务是否该存在
  • superpowers-zh:20 个流程 skill(TDD/系统化调试/代码审查/计划/头脑风暴),全部设为显式调用,不自动注入
  • rpiv-todo / rpiv-ask-user-question:多步任务进度浮层 + 结构化选择题,模型不容易跑偏
  • pi-plan-mode:Codex 式只读 /plan 模式,计划批准前不动手
  • remote-pi:手机经 relay 扫码配对,实时看工具调用;本地 broker 让多个 Pi 会话互发消息(agent_send/list_peers),多代理协作靠它

5. 安全:cc-safety-net 强制层

规则写在 AGENTS.md 里只是软约束——模型可能忘。cc-safety-net 是 hook 层强制:bash 触碰 auth.json~/.env 这类密钥文件直接 block,破坏性命令先过拦截。软约束给人看,硬约束给代理跑。

6. 本地推理:ninfer 默认 + 4 provider 备援

默认模型走本地:一台跑 llama.cpp 的机器经 Tailscale 直连,qwen3.8-27b-uncensored,280K 上下文,成本趋近于零。云端 4 个 provider 共 14 个模型全部探针可达,白名单只启用 5 个,按任务难度切换。

本地推理的代价是速度,收益是:不限量、代码不出内网。日常编码任务本地跑,高难任务切云端,这是成本结构最舒服的组合。

(四)token 优化:41.6K → 24K

基础上下文(system prompt + 工具定义 + skill 描述)是每轮对话的固定成本。我把它从 41.6K 压到 24K,省 43%,四个手段:

  1. disable-model-invocation:29 个低频 skill 加这个 flag,不进 system prompt,需要时 /skill:name 显式调用。skill 描述是纯开销,不用的就别占位
  2. MCP lifecycle: lazy:7 个 server 的工具定义不预载,按需启动
  3. directTools: "search":context-mode 的 11 个工具只注册服务器名,基础 prompt 代价约等于 0
  4. 输出压缩:pi-rtk-optimizer 对工具输出做 ANSI 剥离、截断、聚合,超长 read 输出自动截断

原则只有一条:基础 prompt 里的每个 token 都是常驻成本,加东西前先判断它是否每轮都要在场

(五)踩坑区

  1. pi-lens 升级会覆盖其 4 个 skill 的 disable-model-invocation flag:每次升级后必须重打,否则基础上下文悄悄回涨
  2. extensions/ 目录被递归扫描:备份目录(如 xxx.bak-*)放里面会被当扩展加载,备份一律挪到 backups/
  3. 安全 hook 会拦 bash 触碰密钥文件:审计 auth.json 这类文件用 read 工具,别在 bash 命令里混敏感路径
  4. MCP/包/skill 变更需新会话或 /reload 才生效:改完不重启就测,会得出"没生效"的假结论
  5. 状态快照必须随配置同步:我维护一份 PLUGINS.md 记录运行时状态,过期条目比缺失更危险
  6. 路径字面量会被键入失真.pi.Pi 大小写互换):脚本里用 $HOME 展开,别手敲完整子路径

三、总结

三档扩展体系是骨架,按用途选型是血肉,持续审计是维护方式。配置不是一次性工程,是随使用演进的活系统:全面体检、MCP 冒烟、provider 探针、清孤儿条目、同步快照,每轮审计都让配置更贴近真实用法。Pi 的 minimal 是起点,改造空间留给使用者。

参考链接