1. 为什么有人会嫌 Claude Code “太全能”
第一次用 Claude Code 的人,大概率都会被它的能力密度震一下:读写文件、跑命令、搜代码、调工具、连外部服务,几乎你能想到的编码动作它都能接。但用得久了,尤其是把它塞进日常开发流里之后,另一类声音就冒出来了——“太全能”本身也是一种负担。
我自己的体感很直接。Claude Code 像一把瑞士军刀,功能全、上限高,但每次开工之前,你得先想清楚“这次到底让它干什么、给它多大权限、它会不会顺手改了我没让它改的东西”。工具越多,心智负担越重;能力越强,边界越模糊。对于只想让它老老实实读代码、改文件、跑测试的人来说,这种“全能”反而变成了一种干扰。
于是就有了标题里这个思路:与其用一把全能军刀,不如只用 4 个工具的 pi,再配一套全家桶 oh-my-pi。这里的 pi 是一个刻意做减法的编码代理,核心工具就 4 个,把“能做的事”收窄到“该做的事”;oh-my-pi 则是围绕它搭起来的一整套配置、脚本、工作流集合,相当于给这个精简内核配了个“全家桶”。
这篇文章我想聊的不是“谁比谁强”,而是在什么场景下,做减法比堆功能更划算。如果你也遇到过下面这些情况,那这篇内容应该对你有用:
- 用全能型代理时,总担心它越权操作,改错文件、跑错命令;
- 每次任务都要重新交代一堆上下文,没有稳定的工作流;
- 想要一个“看得懂、改得动、跑得起来”的最小闭环,而不是一堆用不上的能力;
- 愿意花点时间搭一套自己的配置,换取长期稳定的使用体验。
我会把 pi 的 4 个工具逐个拆开讲清楚它们各自解决什么问题、为什么是这 4 个而不是别的,再讲 oh-my-pi 这套全家桶怎么配、怎么用,最后把我踩过的坑和排查经验一并倒出来。全程按“从业者分享实操”的路子来,不堆概念,能抄作业的地方直接给方案。
2. pi 的极简哲学:4 个工具如何覆盖 90% 的编码场景
2.1 从“能力清单”到“最小闭环”的思路转变
大多数编码代理的设计逻辑是“能力清单”:能读、能写、能搜、能跑、能联网、能调 API,清单越长越显得强。但清单式设计的副作用是,你永远不知道它下一步会动用哪个能力。就像给一个新人开了全公司所有系统的权限,他确实什么都能干,但你也什么都不敢放心让他干。
pi 走的是另一条路:先定义“最小闭环”,再往里塞工具。所谓最小闭环,就是“读进来 → 想清楚 → 改出去 → 验证”这一条链路。任何不服务于这条链路的工具,一律不进核心。按这个标准筛下来,能留下来的其实就那么几个。
这个思路的好处很实在。第一,权限边界清晰,你知道它最多只能做这几件事,心里有底;第二,行为可预测,工具少意味着组合少,出问题的路径也少;第三,上下文更省,不用把一堆工具说明塞进提示里,留给真正代码的预算更多。
提示:做减法的前提是“减法之后仍然能完成闭环”。如果砍到连验证都做不了,那就不是极简,是残缺。pi 的 4 个工具之所以成立,是因为它们刚好把闭环补全了。
2.2 4 个核心工具的分工与边界
具体是哪 4 个工具,不同版本叫法可能略有差异,但按职责划分,基本落在下面这四类里。我用一张表先把分工讲清楚,后面再逐个展开。
| 工具职责 | 解决的核心问题 | 典型动作 | 边界(不做什么) |
|---|---|---|---|
| 读取/检索 | 把相关代码和上下文拿进来 | 读文件、按关键词搜、列目录 | 不修改任何内容 |
| 编辑/写入 | 把想清楚的结果落盘 | 改文件、新建文件、批量替换 | 不做验证、不跑命令 |
| 执行/验证 | 确认改动真的能用 | 跑测试、跑构建、跑脚本 | 不主动改源码 |
| 任务/编排 | 把上面几步串成流程 | 拆任务、记状态、调度步骤 | 不直接碰文件系统 |
这四类工具合起来,刚好对应“读 → 改 → 验 → 串”四个动作。你会发现,没有一个是“为了炫技”存在的,每一个都在闭环里有不可替代的位置。这就是 pi 和全能型代理最本质的区别:前者是“够用就好”,后者是“多多益善”。
2.3 为什么是这 4 个,而不是 5 个或 3 个
有人会问,为什么偏偏是 4 个?少一个行不行,多一个行不行?我按自己的理解拆一下。
少一个会怎样:如果去掉“执行/验证”,那代理就只能改代码不能验证,改完对不对全靠你自己跑,闭环断了;如果去掉“读取/检索”,它就只能凭记忆瞎改,上下文全靠你喂,效率暴跌;如果去掉“编辑/写入”,那它只能给建议不能落地,退化成聊天;如果去掉“任务/编排”,复杂任务就没法拆步,只能一问一答,长任务容易跑偏。
多一个会怎样:每多一个工具,就多一份权限、多一份上下文开销、多一条出错路径。比如加个“联网搜索”,听起来很美,但实际编码时大部分信息本地就有,联网反而引入不确定性和延迟。加个“部署发布”,那权限就大到离谱了,一个误操作可能直接上线。
所以 4 个这个数字,不是拍脑袋定的,而是**“闭环完整性”和“权限最小化”两条线交汇出来的结果**。这也是我建议你在自建工作流时参考的原则:先保证闭环,再砍到最少。
2.4 极简带来的三个实际收益
讲完思路,说点实际的。我把 pi 这套极简方案用下来,最明显的收益有三个。
第一是信任成本低。因为工具就 4 个,我大概花十分钟就能把它的行为边界摸清楚,之后基本不用盯着它干活。全能型代理我用了很久,仍然时不时要回头检查它有没有“顺手”干了别的。
第二是上下文利用率高。工具说明占的 token 少了,留给代码本身的预算就多了。实测下来,同样长度的对话,极简方案能塞进去的相关代码明显更多,回答的针对性也更强。
第三是工作流容易固化。工具少,组合就少,我很容易把常用流程写成固定脚本,下次直接复用。全能型代理因为能力太多,每次都得重新交代,很难沉淀成稳定流程。
3. oh-my-pi 全家桶:把极简内核武装成完整工作流
3.1 全家桶到底“全”在哪:配置、脚本、模板三件套
pi 本身是个精简内核,单用它也能干活,但每次都要手动交代上下文、手动跑验证,时间长了还是累。oh-my-pi 的价值就在这儿——它把重复性的准备工作都打包好了,让你开机即用。
我理解的全家桶,主要由三部分组成:
- 配置层:预设好的模型参数、工具开关、权限规则、上下文策略。相当于把“每次都要调的东西”固化成默认值。
- 脚本层:常用任务的封装脚本,比如“读某个模块 → 改指定逻辑 → 跑对应测试”这种固定套路,一条命令触发。
- 模板层:任务描述模板、提交信息模板、验证清单模板。让你不用每次从零组织语言。
这三层叠起来,pi 就从“一个能用的工具”变成了“一套顺手的系统”。这也是为什么标题说“再配个全家桶”——内核负责能力,全家桶负责体验。
3.2 配置层:让 pi 记住你的偏好和红线
配置层是最值得先花时间的地方。我的做法是把配置分成“偏好”和“红线”两类。
偏好类包括:默认用哪个模型、回答详细程度、是否自动跑格式化、上下文保留多少轮。这些是“锦上添花”的,调错了顶多体验差一点。
红线类包括:哪些目录绝对不许碰、哪些命令绝对不许跑、改动超过多少文件必须停下来确认。这些是“保命”的,必须写死。
下面是我自己用的一份配置骨架,你可以按需改:
# pi 配置骨架(示意,字段名以实际版本为准) model: name: default-coder temperature: 0.2 # 编码任务偏低,减少发散 max_context_turns: 12 # 保留最近 12 轮,够用且省 token tools: read: true edit: true exec: true task: true # 其余一律关闭,保持极简 guard: protected_paths: # 红线:这些目录只读 - "config/" - "secrets/" forbidden_commands: # 红线:这些命令禁止执行 - "rm -rf" - "git push --force" max_files_per_change: 8 # 单次改动超过 8 个文件就暂停确认注意:
temperature别设太高。编码任务要的是稳定复现,不是创意发散。我试过 0.7,结果它改代码时总爱“顺手优化”无关逻辑,后来压到 0.2 才老实。
3.3 脚本层:把高频操作封装成一键流程
脚本层是我觉得最省时间的部分。日常开发里,很多任务是高度重复的,比如“改一个函数 → 跑它的单测 → 看结果”。这种流程完全可以封装成脚本。
我常用的一个套路脚本大概长这样:
#!/usr/bin/env bash # 用法: ./fix-and-test.sh <目标文件> <测试文件> set -euo pipefail TARGET="$1" TEST="$2" echo "[1/3] 读取目标与测试..." pi read "$TARGET" "$TEST" echo "[2/3] 执行修改..." pi edit --instruction "按测试预期修正 $TARGET 中的逻辑,不改动无关代码" echo "[3/3] 运行验证..." pi exec "run tests for $TEST"这个脚本把“读 → 改 → 验”三步串起来,我只需要传两个参数。用久了之后,我甚至给不同模块准备了不同的脚本,改前端一套、改后端一套,各跑各的验证。
脚本层的关键是别贪多。一开始我只封装最高频的两三个流程,用顺了再慢慢加。一上来就搞十几个脚本,维护成本比收益还高。
3.4 模板层:让每次任务描述都稳定可控
模板层最容易被忽略,但收益很直接。你有没有发现,同样一个任务,描述方式不同,代理的表现能差出一大截?模板就是用来消除这种波动的。
我常用的任务模板结构是固定的四段:
- 目标:一句话说清要达成什么;
- 范围:明确只改哪些文件、哪些函数;
- 约束:不许动什么、必须遵守什么;
- 验收:怎么算完成,跑哪个测试。
举个例子,同样是“修 bug”,用模板写出来是这样:
目标:修复用户列表分页在最后一页多显示一条的问题。 范围:仅修改 pagination 相关逻辑,文件限定在 src/list/ 下。 约束:不改动接口返回结构,不引入新依赖。 验收:跑 test/list/pagination.test,全部通过。对比一下“帮我修下分页的 bug”,你会发现模板版本几乎不会跑偏。这就是模板层的价值——把模糊需求翻译成可执行指令。
3.5 全家桶的组装顺序与依赖关系
最后说下组装顺序,这个顺序错了会走弯路。我的建议是:
- 先配配置层,尤其是红线部分,先把安全边界立起来;
- 再搭模板层,因为模板不依赖任何脚本,纯文本,随时能用;
- 最后写脚本层,等模板用顺了,你自然知道哪些流程值得封装。
依赖关系上,脚本层依赖配置层(脚本里的命令要符合配置的权限),模板层相对独立。所以先做独立且收益快的,再做有依赖的,节奏最舒服。
4. 从零搭一套 pi + oh-my-pi 的实操过程
4.1 环境准备与安装:先把地基打平
动手之前,先把环境理清楚。我踩过的第一个坑就是环境没对齐,导致后面工具调用各种报错。
需要准备的东西不多:
- 一个可用的运行环境(本地或容器都行,我倾向容器,干净、可复现);
- 目标代码仓库,最好是有测试的,方便验证;
- 基础的命令行操作能力,会看日志、会改配置。
安装步骤我按顺序列一下:
- 拉取 pi 本体,按官方说明完成基础安装;
- 验证
pi --version能正常输出版本; - 拉取 oh-my-pi 全家桶,放到配置目录;
- 把全家桶里的示例配置复制成你的实际配置;
- 跑一个最小任务,确认“读 → 改 → 验”能走通。
提示:第 5 步别跳过。很多人装完就直接上真实项目,结果一出问题分不清是环境问题还是用法问题。先用一个玩具仓库跑通闭环,心里有底再上真项目。
4.2 配置文件的逐项填写与参数计算
配置这块我重点讲两个需要“算”的参数,很多人是拍脑袋填的。
第一个是max_context_turns。这个值决定保留多少轮对话。填太小,代理记不住前面的上下文,容易重复问;填太大,token 消耗飙升。我的算法是:先估算单轮平均 token 数,再用你的上下文预算除以它。比如预算 8k token,单轮平均 600 token,那大概能留 13 轮,取整填 12。这样既不浪费预算,也够用。
第二个是max_files_per_change。这个值决定单次改动多少文件就暂停确认。填太小,正常重构会被频繁打断;填太大,一次改崩一大片。我的经验值是 8 到 12 之间。小于 8 的文件改动,基本是局部修改,风险可控;超过 12 个文件,大概率是跨模块重构,值得停下来看一眼。
其余参数大多是布尔开关,按“用不到就关”的原则处理即可。
4.3 跑通第一个最小闭环:读、改、验
配置好了,跑第一个闭环。我建议选一个有测试覆盖的小函数来练手,比如一个字符串处理函数。
完整流程是这样的:
# 第一步:读进来 pi read src/utils/format.js test/utils/format.test.js # 第二步:改出去(假设测试期望某种边界行为) pi edit --instruction "让 format 函数在输入为空字符串时返回空字符串,而不是抛错" # 第三步:验证 pi exec "run test/utils/format.test.js"跑完之后,重点看两件事:一是改动是否只落在指定文件,二是测试是否真的通过。如果改动跑到了别的文件,说明你的范围约束没写清楚;如果测试没通过,说明验收标准没对齐。
我第一次跑的时候,它顺手把测试文件也改了,理由是“测试预期不对”。这就是典型的越界。后来我在模板里加了“不许修改测试文件”的约束,才治住。
4.4 把闭环扩展成日常开发流
单次闭环跑顺之后,就可以往日常流程里嵌了。我的做法是把它接到几个固定节点上:
- 写新功能前:先让它读相关模块,输出一份改动计划,我确认后再动手;
- 改 bug 时:用模板描述问题,限定范围,改完自动跑对应测试;
- 提交前:让它跑一遍全量测试,把失败项列出来,我再决定怎么处理。
这样一套下来,pi 就从“偶尔用用的工具”变成了“每天都在跑的流程”。关键是每个节点都有明确的输入和输出,不模糊、不越界。
5. 常见问题与排查技巧实录
5.1 工具调用失败:从日志里找线索
工具调用失败是最常见的问题,表现五花八门:读文件读不到、命令跑不起来、编辑没生效。我的排查顺序是固定的:
- 看日志:pi 一般会输出调用详情,先看它到底调了什么、返回了什么;
- 看权限:是不是被配置里的红线拦住了;
- 看路径:是不是相对路径和绝对路径搞混了;
- 看环境:命令依赖的工具是不是没装。
大部分问题在前两步就能定位。我遇到最多的是权限拦截——配置里写了保护目录,结果任务正好要改那个目录,自然失败。这时候要么调整任务范围,要么临时放开权限,别硬扛。
5.2 改动越界:如何用约束把范围锁死
改动越界是极简方案里最需要防的问题。虽然工具少,但“编辑”这个工具本身没有范围概念,你不锁它就乱跑。
我的锁法有三层:
- 模板层锁:任务描述里明确写“仅修改 X 文件”;
- 配置层锁:
max_files_per_change设小一点,超了就暂停; - 流程层锁:改完先
git diff看一眼,确认没跑偏再继续。
三层叠起来,基本能兜住。实测下来,光靠模板层还不够,因为代理有时候会“自作主张”认为别的文件也该改。加上配置层的硬限制,才真正稳。
5.3 上下文丢失:长任务怎么保持连贯
长任务跑到后面,代理容易“忘事”,前面说过的约束后面就不认了。这是上下文窗口的固有限制,没法完全消除,但可以缓解。
我的做法是把关键约束外置。不指望它记住,而是每次关键步骤都重新贴一遍。比如模板里的“约束”段落,我在每个子任务开始时都重复一次。听起来笨,但有效。
另一个技巧是把长任务拆短。与其让它一口气改十个文件,不如拆成五轮,每轮改两个,每轮结束都验证。这样每轮的上下文都新鲜,不容易丢。
5.4 常见问题速查表
把上面这些整理成一张表,方便你对照排查。
| 现象 | 可能原因 | 排查动作 | 解决方向 |
|---|---|---|---|
| 读文件失败 | 路径错误/权限拦截 | 看日志中的路径与权限 | 修正路径或调整红线 |
| 命令跑不起来 | 依赖缺失/环境不对 | 手动跑一遍同命令 | 补依赖或换环境 |
| 编辑没生效 | 范围约束冲突 | 看 diff 是否为空 | 放宽范围或改指令 |
| 改动越界 | 约束不足 | 看 diff 涉及文件数 | 加模板约束+配置硬限 |
| 长任务跑偏 | 上下文丢失 | 看后期是否违背早期约束 | 拆任务+重复贴约束 |
| 测试不通过 | 验收标准不清 | 看测试报错详情 | 明确验收再重跑 |
注意:排查时优先怀疑“配置和约束”,而不是“工具本身有 bug”。我踩过的坑里,九成以上是配置没写对,工具本身其实没问题。
6. 我踩过的坑和几条实在建议
6.1 别一上来就追求“全自动”
我最初的想法是“配好之后全自动跑,我只看结果”。结果第一次全自动就翻车了——它在一个我没注意的模块里做了改动,测试还没覆盖到,差点提交上去。
后来我调整了策略:关键节点必须人工确认。读计划要确认,改动范围要确认,提交前要确认。全自动听起来爽,但在编码这种高风险的场景里,人工卡点不是负担,是保险。
6.2 配置要版本化,别只存在本地
配置这东西,改着改着就忘了当初为什么这么改。我有一次把max_files_per_change从 8 调到 20,过了两周完全想不起来原因,结果一次重构改崩了才发现是这个值放太宽。
从那以后,我把配置纳入版本管理,每次改动都写一句原因。这样回头看的时候,能立刻想起当时的考量。配置也是代码,值得同等对待。
6.3 极简不等于简陋,该补的还得补
pi 只有 4 个工具,但这不代表你的工作流只能有 4 步。工具是内核,工作流是外围。该加的检查、该跑的测试、该做的确认,一个都不能少。
我见过有人为了“保持极简”,连测试都不跑,改完直接提交。这不是极简,是偷懒。极简的是工具数量,不是质量标准。
6.4 最后分享一个小技巧
如果你也在用这套方案,有个小技巧能省不少事:把最常用的三条约束写成一个片段,每次任务开头直接粘贴。比如“不改测试文件、不动配置目录、改动不超过 8 个文件”。这三句话我几乎每个任务都贴,贴久了就形成了肌肉记忆,代理也慢慢“习惯”了这个边界。
这个技巧没什么技术含量,但实测下来,它比任何复杂配置都管用。因为约束这东西,写一次容易被忽略,反复强调才真正生效。