Pi实战 11:上手陌生代码库篇——用 Pi 快速吃透一个新项目
来源:super-productivity 的 AI onboarding 指南、matthewswong 博客、OpenAI Codex use-case、社区 package
codecartographer-pi/@artale/pi-codebase-map/@init,以及 Pi 自我文档化的特性。
一、使用场景
- 刚接手一个陌生仓库,几千个文件,不知道从哪读起。
- 要改一个功能,但不知道请求从哪进、数据往哪落。
- 新人入职,想快速搞懂服务的整体架构和关键模块。
- 想给 Agent 建立这个项目的"说明书",以后它就不用每次重新摸索。
二、能解决什么问题
把**“人肉读代码几周"压缩成"Agent 几小时给你一张带证据的地图”**。
关键不是让它给你一堆文件名,而是给它一套结构化的提问框架,逼它产出带证据、标不确定性、可验证的地图——而不是看似专业实则瞎编的清单。
三、解决思路
思路 1:要"地图",不要"文件名列表"
OpenAI 的 codex onboarding 指南点出好坏之分:
“A useful onboarding answer should leave you with a concrete map, not just a list of filenames. By the end, it should have explained the main flow, highlighted the risky parts, and pointed you to the next files or checks that matter before you start editing.”
(有用的 onboarding 回答应该给你一张具体的地图,而不是一堆文件名。它应该讲清主流程、标出危险部分、并指出你动手前该读的下一批文件。)
思路 2:五个层层递进的问题
super-productivity 给了一套被验证有效的提问序列,从"是什么"一直问到"我还不懂啥":
1. Map —— 从 README、包文件、入口点梳理项目结构,每个结论都要引用文件。 2. Trace —— 追踪一个 [用户操作/API 请求/任务] 从入口到持久化的完整路径,标出假设。 3. Tests —— 把 [某模块] 的测试总结成"行为规则",而不是实现细节。 4. Uncertainties —— 列出你不确定的地方,以及每个点该查哪个文件/测试/人。 5. Questions—— 把那些不确定转化成我问 onboarding 搭子的问题。思路 3:只留能追溯到代码的结论
matthewswong 的硬规矩:
“…write the findings to a committed instruction file, and delete every claim you cannot trace to a file and a line.”
(把发现写进一个提交进 git 的指令文件,并删掉每一个无法追溯到"某个文件的某一行"的断言。)
这是防 Agent 幻觉的关键:凡是它说的,必须能指到具体文件+行号;指不到的,一律当它胡说、删掉。
思路 4:把地图沉淀成项目说明书
一旦跑通,就把结果写进CLAUDE.md/AGENTS.md并提交。以后每次开会话,Agent 自动读这份说明书,不用重新摸索。社区@init包就是干这个的:Claude Code 风格的代码库初始化,自动写出CLAUDE.md。
四、如何实战(含例子)
实战 0:先建立直觉——「烂地图」和「好地图」长啥样
在深入之前,先看同一个问题「这个项目怎么做用户登录的?」两种回答的对比。看完你就知道该怎么要求 Pi 了。
烂地图(一堆文件名,看着专业,读完还是懵):
这个项目用了 Express、Prisma 和 React。主要文件有: - src/app.ts - src/routes/userRoutes.ts - src/controllers/userController.ts - src/services/userService.ts - src/middleware/auth.ts - prisma/schema.prisma ……(一共列了 40 个文件)评价:文件名列了一大堆,但你还是不知道"登录"这件事从哪个文件进、到哪一步落库、哪里最容易出 bug。这就是 OpenAI 说的"文件名列表"——Agent 很可能在瞎编一份看着专业的清单。
好地图(有主流程、有危险点、有下一步):
【主流程:用户登录】 POST /login → src/routes/auth.ts:12 → loginController.login → src/controllers/authController.ts:28 → authService.verifyPassword → src/services/authService.ts:45 (用 bcrypt 比对密码) → 生成 JWT → src/services/authService.ts:60 ⚠️ 危险点:密钥从 .env 的 JWT_SECRET 加载 → 更新 users.last_login → prisma/schema.prisma:34 【动手前你该读的 3 个文件】 1. src/middleware/auth.ts —— 改登录逻辑可能绕过它,必须先看懂 2. src/services/authService.ts:60-75 —— JWT 签发逻辑 3. tests/auth.test.ts —— 现有测试覆盖了哪些登录场景评价:一眼能看到主流程、标出了"密钥加载"这个危险点、还告诉你下一步该读啥。这才是地图。你要求 Pi 时,就要的是右边这种,不是左边那种。
实战 1:完整走查一个真实项目(五问 + 真实风格输出)
下面拿一个具体的项目bookmark-api(一个用 Express + Prisma + PostgreSQL 写的书签管理后端)做完整演示。你把自己的项目名和关注点换进去即可。
第一步,丢给它"五问"提示词:
我要上手 bookmark-api 这个仓库,帮我建立整体认知。请按下面五步来, 每一步都要引用具体文件和行号,不确定的地方明确写「假设」: 1. 【Map】从 README、package.json、入口文件梳理项目结构,每个结论注明来自哪个文件。 2. 【Trace】追踪「收藏一个网址」这个操作,从 HTTP 入口一直到写库的完整调用链。 3. 【Tests】把 bookmark 模块的测试总结成几条「行为规则」(它保证了什么),不要罗列实现。 4. 【Uncertainties】列出你还不能确定的地方,并说明每点该查哪个文件/测试/问谁。 5. 先只读、只报告,不要改任何代码。Pi 大致会回你这样一份东西(真实风格,文件/行号为示例):
## 1. Map —— 项目结构 - 入口:`src/index.ts:1` 调用 `app.listen(3000)` 启动服务。 - Express app 在 `src/app.ts:8` 创建,挂载了三个 router(bookmark / user / auth)。 - ORM 用 Prisma,schema 在 `prisma/schema.prisma`,Bookmark 和 User 两个 model。 - 依据:`package.json:14` 的 dependencies、`src/index.ts:1`、`src/app.ts:8`。 ## 2. Trace —— 「收藏网址」调用链 POST /bookmarks → src/routes/bookmarkRoutes.ts:9 → bookmarkController.create → src/controllers/bookmarkController.ts:21 → authenticate 中间件 → src/middleware/authenticate.ts:6 (校验 JWT,失败返回 401) → bookmarkService.create → src/services/bookmarkService.ts:15 → prisma.bookmark.create → src/lib/db.ts:4 (Prisma client 单例) 落库到 `bookmarks` 表(prisma/schema.prisma:18,字段 id/url/title/userId/createdAt) ⚠️ 假设:没看到对 url 做长度或 scheme 校验,可能在 bookmarkService.ts:15 缺输入校验。 ## 3. Tests —— bookmark 模块的行为规则 - 规则1:未登录(无 Bearer token)创建书签 → 必须返回 401。(tests/bookmark.test.ts:12) - 规则2:合法的 url + title → 返回 201 且落库。(tests/bookmark.test.ts:30) - 规则3:删除不存在的书签 → 返回 404。(tests/bookmark.test.ts:58) ## 4. Uncertainties —— 我还不确定 - url 到底有没有校验? → 查 src/services/bookmarkService.ts:10-25,或跑 tests 看有没有覆盖。 - createdAt 是 DB 默认还是代码生成? → 查 prisma/schema.prisma:20 的 @default。 - 鉴权中间件对 /health 这类公开路由怎么放行? → 查 src/app.ts:15-20。注意第 4 步的价值:它主动承认自己不确定,并告诉你每点该查哪个文件。这比一份"看似什么都知道"的回答可靠得多——因为你能顺着它给的线索去验证。
实战 2:把地图固化成AGENTS.md(看最终产出长啥样)
走查完别让它停在对话框里。让 Pi 把结论整理成一份只保留能追溯到文件+行号的说明书并提交:
把上面梳理出的架构、入口、调用链、行为规则、以及已知的不确定点, 整理成一份 AGENTS.md(放仓库根目录)。 要求:每条结论都要能追溯到具体文件和行号;无法追溯的一律删掉,不要写进文件。 然后 git add AGENTS.md 并 commit,message 写 "docs: add project onboarding map"。它大致会生成这样一份文件(这就是以后每次开会话 Agent 自动读的东西):
# bookmark-api — 项目说明书 ## 架构 - Express 服务,入口 `src/index.ts:1`,app 在 `src/app.ts:8` 创建。 - ORM:Prisma,model 定义见 `prisma/schema.prisma:10-40`。 ## 关键流程:收藏书签 `POST /bookmarks` → `bookmarkRoutes.ts:9` → `bookmarkController.create`(`bookmarkController.ts:21`) → `authenticate` 中间件(`authenticate.ts:6`)→ `bookmarkService.create`(`bookmarkService.ts:15`) → `prisma.bookmark.create`(`db.ts:4`)→ 写入 `bookmarks` 表(`schema.prisma:18`)。 ## 行为规则(来自测试) - 无 token → 401(`tests/bookmark.test.ts:12`) - 合法 url+title → 201(`tests/bookmark.test.ts:30`) - 删不存在 → 404(`tests/bookmark.test.ts:58`) ## 已知坑 / 待确认 - ⚠️ url 输入校验缺失(疑似,见 `bookmarkService.ts:10-25`,待测试确认)。这就是社区
@init/codecartographer-pi这类包在自动做的事——你也可以直接装,或者干脆让 Pi 自己写一个(见第 03 篇"让 Pi 自己造")。一份文件换永久复用:以后每次开会话,Agent 自动读它,不用重新摸索。
实战 3:用语义搜索补 grep 的不足(带真实查询)
有时候你想找的是"意思相关、但措辞不同"的代码,grep 关键字搜不到。比如你隐约记得"有个地方会把书签导出成 HTML 文件",但函数名可能叫export、download、serialize任何一个,grepexport会淹没在一堆export const里。
这时用语义搜索。社区@artale/pi-codebase-map用 TF-IDF 给代码建索引,零依赖,“比 grep 聪明一点”:
piinstallnpm:@artale/pi-codebase-map装完后你这样问(自然语言):
哪个文件负责把书签导出成 HTML?给我文件路径和那段的行号范围。它大致会回:
最相关:src/services/exportService.ts:34-52 (函数 renderHtmlBookmarks,把书签列表序列化成 HTML 书签格式) 次相关:src/routes/bookmarkRoutes.ts:44 (路由 POST /bookmarks/export 调到上面那个函数)适合"我记得要干嘛、但不知道函数名叫啥"的场景。注意它是 TF-IDF 不是真·语义模型,复杂查询还是得靠实战 1 的 Trace,它更适合快速定位。
实战 4:先自己猜,再让 Agent 验证(别当甩手掌柜)
super-productivity 有个反直觉但高效的建议:
“Before asking AI about unfamiliar code, spend 5 minutes forming your own hypothesis. Then check with AI. This builds the mental model that makes you fast.”
(问 AI 陌生代码前,先花 5 分钟自己形成一个假设,再用 AI 去验证。这能建立让你变快的心理模型。)
具体这么做。打开仓库先扫一眼目录结构,自己猜:
我猜:这是个三层架构(routes → controllers → services),入口在 src/index.ts, 鉴权应该是个中间件,数据库用 Prisma。然后让 Agent 证实/证伪:
我猜这个项目是 routes→controllers→services 三层架构,入口在 src/index.ts, 鉴权是中间件,ORM 用 Prisma。请逐条告诉我:哪些猜对了、哪些错了、实际是怎样的, 都给出行号依据。为什么这步不能省:你主动猜的过程,大脑在建立"钩子",Agent 的纠正会挂到这些钩子上,记得特别牢。直接读答案则像看一遍就忘。先猜后验,比直接问快。
五、小结 & 避坑
- 要地图不要列表:好的 onboarding 给你主流程 + 危险点 + 下一步该读啥。
- 套五问:Map → Trace → Tests → Uncertainties → Questions。
- 只信能追溯到文件+行号的结论:指不到的当幻觉删掉。
- 沉淀成 AGENTS.md 并提交:一次梳理,永久复用。
- 先自己猜,再用 Agent 验证:建立你自己的心智模型,别当甩手掌柜。
参考资料
- Super Productivity《AI Codebase Onboarding: Understand Unfamiliar Repos》:https://super-productivity.com/blog/ai-codebase-onboarding-guide
- matthewswong《Onboarding an AI Coding Agent to an Unfamiliar Codebase》:https://www.matthewswong.com/en/blog/ai-agent-onboarding-unfamiliar-codebase
- OpenAI Codex use-case《Understand large codebases》:https://developers.openai.com/codex/use-cases/codebase-onboarding
- Awesome Pi Coding Agent(
codecartographer-pi、@artale/pi-codebase-map、@init等):https://awesome-pi.site/misc
上一篇:10 · 重构与避坑篇 | 下一篇:12 · TDD 测试驱动篇