一、本章写给谁
代码场景是 Claude Code 最闪亮的那张王牌,但它绝不只属于"科班程序员"。这一章我把读者拆成五类,请你对号入座。
| 你是谁 | 你能从这一章拿到什么 |
|---|---|
| 专职程序员(前端、后端、全栈、移动端) | 把日常 80% 的"读代码、修小 bug、写测试、改 commit、开 PR"都丢给 Claude,把脑力留给真正难的设计与决策 |
| 想学编程的非程序员 | 不再被"环境配置、命令行、Git"挡在门外。Claude 帮你跑通第一段 Python、第一个 Node 项目、第一次提交 |
| 兼职做点小工具的产品、设计、运营 | 学会让 Claude 替你写"批量改文件名、抓数据、自动加水印"这种 1 天搞定 1 个月省事的小工具 |
| 全栈型独立开发者 | 一个人当一个团队用:Claude 当后端、Claude 当前端、Claude 当 QA、Claude 当 PM |
| 技术管理者、Tech Lead | 不再每天熬夜 Code Review。让 Subagent 替你打第一遍分,你只看真正需要拍板的部分 |
一个心态前置说明:Claude Code 是会写代码的助理,不是替代你的工程师。它能把你想做的事按你描述的样子做出来,但"想做什么"、"做成什么样"、"出了 bug 谁背"这些问题永远在你自己。把它当一双能动的手,而不是一颗能拍板的脑。这条心法,本章会贯穿始终。
如果你属于"完全没写过代码"的人,建议先看完前七章,回头再读这一章。本章的提示词模板对你依然有用,但前期需要 Claude 多解释几步术语,你别嫌烦。
这一章不会教你的事
| 不会教 | 为什么 |
|---|---|
| 编程语言基础语法(变量、循环、函数) | 不是这本书的目的,市面上免费教程很多 |
| 算法和数据结构 | 同上 |
| 某个具体框架的全部细节(比如 Next.js 全 API) | 太具体,看官方文档更快 |
| 怎么"让 Claude 替你完全无人值守地写一个 SaaS" | 不现实,所有靠谱产品都需要"人 + AI"协作 |
二、第一步:用 /init 让 Claude 认识你的项目
任何一个新项目,你和 Claude Code 的第一次"见面礼"只有一句话:/init。它相当于让 Claude 走完"新员工入职"的流程——翻文档、看代码库结构、问"我们用什么测试框架"、"提交 PR 的流程是什么"。
2.1 先 cd 进项目目录
Claude Code 是"上下文敏感"的——它默认把你启动它时所在的目录当作"工作根目录"。所以新项目的第一步永远是:
cd /path/to/your-project
claude
如果你已经在 Claude Code 里了,可以用 /cd 切目录:
/cd ~/work/your-project
进根目录之前先确认你站对了位置:
ls
# package.json src/ public/ README.md ...
如果看不到 package.json(Node)、pyproject.toml(Python)、go.mod(Go)、Cargo.toml(Rust)等"项目身份证",说明你还在外层目录,再 cd 一层。
2.2 跑 /init
进到正确目录之后,第一句话就是:
/init
接下来 Claude 会做一连串你看得见的事:
- 扫描根目录结构:
ls -la、看package.json、requirements.txt、go.mod、Cargo.toml、pom.xml等等,判断你用的是哪门语言、什么框架。 - 读 README.md:如果有,它会先看你已有的项目说明。
- 采样关键源文件:通常会挑 5 到 15 个最具代表性的文件读一遍,弄清架构。
- 查看 git 历史的最近几条:知道这个项目最近在改什么。
- 生成
CLAUDE.md:把它"理解到的东西"写成一份"项目说明书"放在项目根目录。
整个过程通常 30 秒到 2 分钟,看项目大小。完成后你会看到:
Created CLAUDE.md (1.4 KB)
You can edit this file to add project-specific guidance.
2.3 自动生成的 CLAUDE.md 长什么样
下面是一个真实的 React + TypeScript 项目跑完 /init 之后生成的 CLAUDE.md:
# CLAUDE.md
This file provides guidance to Claude Code when working in this repository.
## Project overview
This is a React 18 + TypeScript single-page application using Vite as the
build tool. It is a personal finance dashboard that aggregates bank account
data from multiple providers via a Node.js backend (see ../api).
## Tech stack
- Framework: React 18.3 + TypeScript 5.5
- Build: Vite 5.4
- Styling: Tailwind CSS 3.4 + shadcn/ui
- State: Zustand 4.5
- Data fetching: TanStack Query 5.51
- Testing: Vitest 2.0 + React Testing Library
- Linting: ESLint 9 + Prettier 3
- Package manager: pnpm 9
## Common commands
| Task | Command |
| --- | --- |
| Install deps | `pnpm install` |
| Dev server | `pnpm dev` |
| Build | `pnpm build` |
| Run tests | `pnpm test` |
| Lint | `pnpm lint` |
| Type check | `pnpm typecheck` |
## Architecture
- `src/pages/` - Route-level components, one folder per route
- `src/components/` - Shared UI components
- `src/hooks/` - Custom hooks, especially data hooks
- `src/lib/` - Pure utilities (formatters, date helpers)
- `src/api/` - API client (Axios) and TanStack Query definitions
- `src/store/` - Zustand stores
## Key files
- `src/main.tsx` - App entry, providers wired here
- `src/router.tsx` - Route definitions
- `src/api/client.ts` - Axios base instance, attaches auth token
- `vite.config.ts` - Build config, proxy for /api during dev
## Conventions (auto-detected)
- Components are PascalCase named exports.
- Hooks start with `use`, default-exported.
- Imports use the `@/` alias (mapped to `src/`).
这份文件已经把"一个新人想了解的所有事"列得差不多了。但它还不够——下一步是你要做"人工补充"。
2.4 你必须人工补的四件事
/init 自动生成的 CLAUDE.md 是从"代码能看出来的事"反推的,所以它永远不知道你脑子里那些约定。打开 CLAUDE.md,自己加上下面四类内容。
第一类:永远不要做的事
## Never do(强禁)
- 永远不要 `git push --force` 任何分支,包括我自己的 feature 分支。
- 永远不要直接 commit 到 `main` 或 `develop`,必须走 PR。
- 永远不要修改 `package-lock.json` 之外的锁文件。
- 永远不要把 API key、token、密码写进任何文件,包括测试代码。
- 永远不要在没有我明确同意的情况下删除 `.env*` 文件。
- 永远不要跑 `rm -rf node_modules && pnpm install`,先问我。
这些"永远不要"看起来啰嗦,但真的能救命。Claude Code 是个执行力极强的实习生——你不说"不要做",它在某些极端场景下还真会做。把禁令写下来,等于给你的项目装一道安全门。
第二类:团队约定
## Team conventions
- 所有 React 组件文件名用 PascalCase(`UserCard.tsx`),工具函数用 camelCase(`formatDate.ts`)。
- 导出统一用 named export,不要默认导出(测试发现易拼错且重构困难)。
- 异步函数命名以动词开头:`fetchUser`、`createOrder`、`syncAccounts`。
- 注释只写"为什么",不写"做了什么"——做了什么读代码就知道。
- Commit 信息走 Conventional Commits:`feat:`、`fix:`、`refactor:`、`docs:`、`test:`、`chore:`。
第三类:测试与发布流程
## Testing & release
- 改任何 `src/api/` 下的代码,必须同步更新 `src/api/__tests__/` 的对应测试。
- PR 前本地必须跑过:`pnpm typecheck && pnpm lint && pnpm test`。
- 主分支(main)的 push 会触发 GitHub Actions 自动部署到 staging,所以 main 要永远绿。
- 生产部署由专人手动从 GitHub Releases 触发,你不要尝试直接 deploy。
第四类:这个项目的"潜规则"
## Gotchas(踩过的坑)
- `useAccounts` hook 在 SSR 环境下会报错,只能在客户端组件用。
- 时间字段全部按 UTC 存,前端展示时用 `formatLocalDate` 转换。
- `react-pdf` 在 Vite dev server 下需要单独配 `optimizeDeps.include`。
- 后端的分页参数是 1-indexed(`page=1` 是第一页),不是 0-indexed。
把这四类补完之后,你的 CLAUDE.md 就从 1.4 KB 涨到 3 到 5 KB。这 3 到 5 KB 的投资,接下来三个月每一次和 Claude Code 对话都能省你 2 分钟解释。
2.5 多个 CLAUDE.md 的层级
CLAUDE.md 可以多层叠加,Claude Code 会自动按下面的顺序读:
~/.claude/CLAUDE.md ← 全局,你所有项目都生效
└─ /path/to/project/CLAUDE.md ← 项目级,这个项目生效
└─ src/api/CLAUDE.md ← 子目录级,只对 src/api/ 下的工作生效
举个例子,你可以在 src/api/CLAUDE.md 里写:
# src/api/CLAUDE.md
这个目录下的所有改动,必须遵守:
1. 任何新接口都要在 `__tests__/` 下加对应测试,覆盖成功 + 至少 1 个错误路径。
2. 不要直接用 `axios.get`,必须用 `apiClient` 实例(已自动加鉴权)。
3. 接口返回的时间字段全部用 ISO 8601 字符串,不要传 timestamp。
之后 Claude Code 在 src/api/ 下工作时,会自动叠加这些规则,不用你每次手动提。
三、第二步:让 Claude 读懂你的代码库
/init 让 Claude 知道项目大概是什么。下一步是让它理解项目细节。这一节给你三类提问技巧。
3.1 提问技巧:从"宏观"到"微观"问
宏观:理解一个模块
解释 src/auth 这个模块做什么。
要求:
- 一句话定位它的职责
- 列出它对外暴露的关键 API(函数、组件、类)
- 列出它依赖的外部模块
- 指出它的状态在哪里管理(全局 store 还是局部)
- 如果有不合理的设计,顺便指出来
Claude 会去读 src/auth/ 下的文件,跨文件 join 信息,给你一份这样的报告:
src/auth负责用户的认证状态管理与登录、登出流程。对外暴露:
useAuth()hook:返回当前用户、loading、login()、logout()<AuthProvider>:在src/main.tsx包裹整个 ApprequireAuth():Route Guard 的高阶函数依赖:
@/api/auth提供loginRequest、refreshToken@/store/userStore:Zustand store 持久化当前用户react-router-dom用于在 401 时跳转状态管理: Token 存在
localStorage,内存里挂在userStore.user.token。不合理的地方:
useAuth内部有 5 个useEffect,其中两个在做相同的事(都在监听 user 变化做 redirect),会造成重复跳转。requireAuth在 SSR 下会报错(读 localStorage),建议加typeof window判断。
这种回答的价值在于:它不仅告诉你"是什么",还顺手给你指出"哪里有坑"。
中观:理解一个流程
用户登录的完整流程是怎样的?画一个序列图,
从用户点"登录"按钮开始,到首页加载完成结束。
覆盖前端、后端 API、token 持久化、路由跳转这四层。
Claude 会输出一份 Mermaid 序列图:
```mermaid
sequenceDiagram
participant U as 用户
participant L as LoginPage
participant A as authApi.login
participant S as userStore
participant R as Router
participant H as HomePage
U->>L: 输入账号密码点登录
L->>A: POST /api/auth/login
A->>A: 验证 + 生成 JWT
A-->>L: { token, user }
L->>S: setUser({ token, user })
S->>S: 持久化到 localStorage
L->>R: navigate("/")
R->>H: render HomePage
H->>S: useAuth() 拿到 user
H->>A: GET /api/dashboard
A-->>H: dashboard data
```
这种图你贴到 Notion 或飞书文档里,直接可以当架构文档用,比让你自己手画快 100 倍。
微观:剖析一个文件
@src/api/user.ts 这个文件有什么坑?
重点看:
- 异步错误处理是否完整
- 有没有重复代码可以抽
- 类型定义是否准确
- 有没有 N+1 查询风险
- 单元测试覆盖了多少分支
@src/api/user.ts 是 Claude Code 的文件引用语法,等于把这个文件的内容塞进上下文。Claude 会逐行扫一遍,给你输出形如:
src/api/user.ts共 184 行,我发现 6 个值得注意的点:
行号 严重 问题 23 到 31 高 getUser在 401 时只 console.error,没把错误抛上去,调用方不知道失败47 到 62 中 updateUser和patchUser90% 重复,可以抽成内部_putUser89 中 User.tags类型是any[],实际后端返回{id, name}[],改成强类型110 到 145 高 loadFriends串行调了 N 次getUser(id),标准 N+1,改getUsersByIds批量接口全局 低 没有任何 JSDoc 注释,IDE 提示能力弱 测试 高 __tests__/user.test.ts只测了 happy path,完全没测错误路径你想我先修哪一条?
这就是 Claude Code 真正的价值——它能在 30 秒内做你做半小时的事。
3.2 用 Plan Mode 探索复杂代码
读懂大型项目时,你会担心一件事:Claude 一不留神改了某个文件。Plan Mode 就是为这件事设计的。
怎么进入 Plan Mode
两种方法,任选一种:
按键:Shift + Tab(在普通模式下连按一次)
命令:/plan
进入后,你会看到提示符变成:
[Plan Mode] >
Plan Mode 的核心特性
| 维度 | 普通模式 | Plan Mode |
|---|---|---|
| 能读文件 | 是 | 是 |
| 能改文件 | 是 | 否 |
| 能跑命令 | 是(高危的会问) | 只能跑只读命令(如 ls、cat、git log) |
| 能搜索 | 是 | 是 |
| 能给计划 | 是 | 是,而且是它的本职 |
| 适用场景 | 真正动手干活 | 探索、规划、理解、画图 |
简单说:Plan Mode 是 Claude 的"图书馆模式"——它只读不写。在这个模式下,你可以放心大胆地让它"逛"你的代码库,完全不用担心它手滑。
Plan Mode 三大典型场景
场景 A:理解你接手的烂摊子
[Plan Mode]
我刚接手这个项目,前任工程师离职了文档不全。
帮我:
1. 先列出整个项目最重要的 10 个文件,按重要性排序
2. 给每个文件一句话说明它的作用
3. 指出 3 个最容易让新人踩坑的"潜规则"
4. 给我一份"上手路径":如果我要从零开始读懂这个项目,应该按什么顺序?
场景 B:规划一次大重构
[Plan Mode]
我准备把现在的 Redux 全部换成 Zustand。
请你:
1. 列出所有用到 Redux 的文件
2. 估算改造工作量(以"小时·人"为单位)
3. 给我一个分阶段执行计划,每阶段最大 3 小时,可以独立提交 PR
4. 标出"风险最高"的 3 个点
5. 不要写一行代码,先给我计划
场景 C:做架构评审
[Plan Mode]
我们准备给用户中心加"双因子认证"功能。
当前架构图:见 @docs/architecture.md
新需求:用户除了密码外,还要短信或 TOTP。
帮我评估:
1. 现有 auth 模块需要改哪些地方
2. 数据库需要新增什么表、字段
3. 前端需要新增哪些组件
4. 需要新增哪些后端接口
5. 需要新增哪些环境变量、配置
6. 给一个推荐实施顺序
只出方案,不动代码。
Plan Mode 出的方案我建议先复制到 Notion、飞书、钉钉文档里,让真正会拍板的人(可能是你自己,可能是技术 Leader)审一遍。计划过审之后,再切回普通模式,逐项执行。这是真正"工程化"用 Claude 的关键习惯。
3.3 配合"模型切换"做更深的探索
复杂代码探索,你可能想用更聪明的模型。Claude Code 内置三档模型,切换非常简单:
/model opus ← 切到最聪明的 Opus,适合规划、架构、深度推理
/model sonnet ← 切到默认的 Sonnet 4.5,日常使用平衡之选
/model haiku ← 切到最便宜的 Haiku,适合写脚手架、简单任务
实战技巧:
1. 用 /model opus + /plan 让 Opus 出方案(算贵的脑子,出主意)
2. 把方案 review 一遍
3. /model sonnet 切回 Sonnet 4.5
4. 退出 /plan 模式,让 Sonnet 干活(算便宜的手,真执行)
这一招本书后面会反复用到,记住它:Opus 出谋,Sonnet 实施。
四、第三步:让 Claude 帮你修 Bug
读懂代码之后,我们干第一件真正生产力的事:修 Bug。
4.1 一个真实案例:用户报告"上传图片失败"
我们用一个完整案例走一遍。客服群里突然出现这条消息:
用户 @张三 反馈:在"上传头像"页面,选择文件后大概 80% 的概率会失败, 错误提示是"上传失败,请重试"。我自己试了好几次,有时成功有时失败, 没有明显规律。麻烦排查一下。
4.2 提示词:把"故事"完整告诉 Claude
我有一个 bug 需要你排查,过程要让我看见每一步,不要直接改代码,先定位。
【背景】
- 项目:本仓库(已有 CLAUDE.md)
- 报障人:用户 @张三
- 现象:"上传头像"页面,选文件后约 80% 概率失败,提示"上传失败,请重试"
- 频率:间歇性,无明显规律
- 复现:本机暂时没复现成功
【相关文件(已知)】
- 前端入口:@src/pages/profile/AvatarUpload.tsx
- 上传工具:@src/lib/upload.ts
- 后端日志:@logs/error.log(最近 24 小时的)
【你的任务】
1. 把可能的原因列出来,按可能性从高到低排序
2. 对最可能的 1 到 2 个,给出"我该跑哪条命令、看哪段日志"的具体定位步骤
3. 不要直接改代码,先告诉我你怀疑的根因
完成第 3 步停下来等我回复,确认根因后再动手。
4.3 Claude 的反应
它会做下面这一连串动作,你看着就行:
1. read_file: src/pages/profile/AvatarUpload.tsx
2. read_file: src/lib/upload.ts
3. read_file: logs/error.log(最近 200 行)
4. grep: "upload" 在 logs/error.log 中
5. grep: "timeout" 在 logs/error.log 中
6. read_file: vite.config.ts(看看 dev proxy 设置)
7. read_file: src/api/client.ts(看 axios 全局 timeout)
然后给你输出:
我大致定位到三个可能根因,按可能性排序:
概率 根因 证据 70% 超时配置过低: src/api/client.ts第 12 行设了全局timeout: 5000,但日志里 17 条上传失败记录全部是 5.0 到 5.1s 触发的ECONNABORTED,显然图片大就超时20% 后端 multipart 解析限制:nginx 默认 client_max_body_size = 1M,日志里 3 条413 Request Entity Too Large印证了这个10% 前端没正确处理重试: upload.ts47 行的retryCount = 0,实际从来没启用,失败就直接 throw我最怀疑根因 1。你可以做两件事确认:
- 让用户截一张失败时浏览器 Network 面板的截图,看具体是哪种错误(
net::ERR_TIMED_OUT、413、502)- 我可以先把
client.ts的全局 timeout 从 5s 调到 60s,但这是治标——根因可能要根据上一步确认调整要我接着改吗?如果改,我建议先只改 timeout这一条,提一个最小 PR,观察 24 小时效果。
4.4 你怎么 review、怎么放行
你看了这个分析,觉得逻辑通,回它:
确认根因 1 是主要原因。我也刚问了运维,nginx 已经早就把 client_max_body_size 调到 50M 了,所以根因 2 排除。
请你:
1. 把全局 timeout 从 5000 改到 60000
2. 同时把 src/lib/upload.ts 改成"图片上传专用"的接口,带进度条,允许 120s 超时
3. 不要影响其他接口的 5s 超时(只对上传接口单独调长)
4. 加一个简单测试,模拟"上传超过 5s 但小于 60s"的场景,确保不再失败
5. 改完跑一遍 pnpm typecheck && pnpm test,确认通过
6. 给我一份 PR 描述草案,说明改了什么、为什么、怎么验证
按上面步骤来,完成后告诉我。
Claude 会严格按你说的步骤做完,期间任何一步如果遇到不确定(比如发现你没说清楚的边界),会停下来问你。
4.5 修 Bug 的三条铁律
| 铁律 | 解释 |
|---|---|
| 1. 把堆栈完整贴进去 | 不要只贴错误信息,把完整 stack trace 贴进去——Claude 能从堆栈里读出大量隐含信息 |
2. 用 @ 引用相关文件 |
比起让它自己 grep,你直接用 @ 引用又快又准 |
| 3. 先复现,再修 | 复现不了的 bug 不要急着改。让 Claude 先写一个能稳定复现的测试,再针对测试改代码 |
第 3 条特别重要。下面这段话就是"先复现,再修"的标准提示词:
这个 bug 我现在还无法稳定复现。请你:
1. 根据日志和代码,推断出能稳定触发 bug 的最小输入条件
2. 用现有测试框架写一个测试,这个测试在 bug 修复前必须失败、修复后必须通过
3. 让我先看测试,确认能复现
4. 我确认后,再开始改源码
这套流程下来,你修的 bug 不会"修完三天又来一遍",因为有测试守门。
五、第四步:让 Claude 帮你写测试
很多人写代码不写测试,因为写测试又烦又花时间。但让 Claude 写测试,是它最擅长的事之一——它读完源码就能精准列出该测的边界条件。
5.1 一个完整的"写测试"提示词
为 @src/utils/dateFormat.ts 写完整的单元测试。
【要求】
- 框架:Vitest
- 覆盖率目标:行覆盖 > 95%
- 必须覆盖的边界情况:
* 空字符串、null、undefined 输入
* 非法日期字符串(如 "2026-13-45")
* 极端日期(1970-01-01、2099-12-31)
* 跨时区(UTC、Asia/Shanghai、America/New_York)
* 闰年的 2 月 29 日
* 浮点 timestamp(带小数位)
- 测试名用中文描述,例:`it("应在输入为空字符串时返回空字符串", ...)`
- 写完后跑一遍 `pnpm test src/utils/dateFormat.test.ts`,确认全部通过
- 如果发现源码本身有 bug,先告诉我,不要私自改源码
5.2 Claude 输出的测试长这样
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { formatDate } from "./dateFormat";
describe("formatDate", () => {
describe("基础格式化", () => {
it("应将合法 Date 对象格式化为 YYYY-MM-DD", () => {
const d = new Date("2026-04-19T10:00:00Z");
expect(formatDate(d)).toBe("2026-04-19");
});
it("应在输入为空字符串时返回空字符串", () => {
expect(formatDate("")).toBe("");
});
it("应在输入为 null 时返回空字符串", () => {
expect(formatDate(null)).toBe("");
});
it("应在输入为 undefined 时返回空字符串", () => {
expect(formatDate(undefined)).toBe("");
});
});
describe("非法输入", () => {
it("应在输入非法日期字符串时返回空字符串", () => {
expect(formatDate("2026-13-45")).toBe("");
});
it("应在输入纯数字字符串时返回空字符串", () => {
expect(formatDate("not-a-date")).toBe("");
});
});
describe("跨时区", () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
it("应按 Asia/Shanghai 时区返回当地日期", () => {
vi.setSystemTime(new Date("2026-04-19T16:00:00Z"));
expect(formatDate(new Date(), "Asia/Shanghai")).toBe("2026-04-20");
});
it("应按 America/New_York 时区返回当地日期", () => {
vi.setSystemTime(new Date("2026-04-19T03:00:00Z"));
expect(formatDate(new Date(), "America/New_York")).toBe("2026-04-18");
});
});
});
跑完之后,Claude 会把覆盖率报告贴给你:
PASS src/utils/dateFormat.test.ts (24 tests) 187ms
% Coverage report from v8
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Lines
-----------|---------|----------|---------|---------|-------------------
All files | 97.3 | 95.0 | 100 | 97.3 |
dateFmt.ts| 97.3 | 95.0 | 100 | 97.3 | 89-91
-----------|---------|----------|---------|---------|-------------------
差 89-91 行没覆盖,那是一段处理自定义 locale 的死代码,
当前接口未暴露。我已经在测试文件顶部加了 // TODO: 解锁 locale 时补充。
这就是高质量的工程产出——不是"我把测试写了",而是"我把测试写了、覆盖率给你了、没覆盖的地方解释了原因"。
5.3 TDD 工作流:让 Claude 帮你"先写测试再写代码"
TDD(测试驱动开发)三步循环:红 → 绿 → 重构。Claude Code 配合 TDD 极其顺手。
第一步:红(写一个失败的测试)
我要新增一个 `mergeAccounts(a, b)` 函数,作用是合并两个银行账户对象。
合并规则:
- id 取 a.id
- balance 取 a + b
- transactions 数组合并并按时间倒序去重
- 任意一方为 null 直接返回另一方
- 两个都 null 抛异常
请你:
1. 先在 @src/lib/accounts.test.ts 里写一组覆盖上述规则的测试
2. 跑一遍,所有测试都应该红(因为函数还不存在)
3. 不要写实现,只写测试
第二步:绿(让测试通过)
测试写完确认你看过没问题之后:
好,实现 mergeAccounts 函数,目标是让所有测试变绿,
不要改测试代码。
第三步:重构(让代码漂亮)
所有测试都绿了。现在请你 refactor:
- 抽出公用的"按时间去重"逻辑
- 给函数加 JSDoc 注释
- 保持所有测试依然绿
这一套流程的妙处在于:你只描述"行为",Claude 写代码;测试是"行为"的具象化。代码改了 100 次,只要测试还绿,行为就没变。这是工程师最舒服的睡眠方式。
六、第五步:Git 操作
Claude Code 默认就懂 git——不光懂,它已经被训练成"按工程界主流最佳实践来"。
6.1 它默认会做的 git 动作
| 动作 | 它会自动 | 它绝不会自动 |
|---|---|---|
git status |
查状态 | —— |
git add |
加你刚改的文件 | 加 .env、*.key、*.pem 等敏感文件 |
git commit |
写好 commit message 提交 | —— |
git push |
推到当前分支 origin | git push --force(除非你明确说) |
git pull |
拉远端最新 | —— |
git reset |
--soft 撤销 commit |
--hard(除非你明确确认) |
git rebase |
简单 rebase | 复杂的会先列计划等你 review |
改 .gitignore |
—— | 主动改(除非你明确要求) |
| 改 git config | —— | 永远不会 |
这些"绝不会"的清单,本质上是 Anthropic 在系统提示里硬编码的安全护栏。Claude Code 把"代码丢失"看作和"删用户文件"同等严重的事故。
6.2 自动生成 Commit Message
最常用的一句话:
请按 Conventional Commits 提交本次修改。
Claude 会:
- 跑
git status看哪些文件改了 - 跑
git diff --staged(或git diff)看具体改动 - 根据改动归类(feat、fix、refactor、test、docs、chore 等)
- 写一段 1 到 2 句的简短 message,可能再加一段 body 说明"为什么"
- 用 here-doc 提交,避免引号转义问题
输出大概长这样:
git add src/api/client.ts src/lib/upload.ts src/lib/upload.test.ts
git commit -m "$(cat <<'EOF'
fix(upload): 上传超时从 5s 调到 60s, 避免大图片失败
用户报告头像上传约 80% 概率失败, 经排查根因为 axios 全局
timeout=5s, 而后端处理大图片普遍需要 10-30s。
本次修改:
- 全局 timeout 维持 5s 不变, 避免影响其他接口
- 新增 uploadClient, timeout=60s, 专门用于上传场景
- 补 1 条单测覆盖 5s-60s 之间的成功场景
EOF
)"
注意几个细节:
- 类型加 scope:
fix(upload)比裸fix:更易归类 - 第一行不超过 72 字符,严格遵守 Conventional Commits 规范
- body 写"为什么",不写"做了什么"——做了什么
git diff自带
6.3 复杂 Git 场景
场景 A:解决 merge conflict
我刚 git pull,出现 3 个文件冲突,你帮我解一下。
原则:
- 我的本地是 feature 分支,远端是 main 合并过来
- 任何业务逻辑冲突,优先保留我的本地版本(理由:我的更新)
- 任何依赖版本号冲突,选两边的更高版本
- 解完跑一遍 pnpm typecheck,确认能编译
- 不要直接 commit,解完让我看一眼
Claude 会:
git status列出冲突文件- 逐个
read_file看冲突标记<<<<<<<、=======、>>>>>>> - 按你给的原则做选择
- 删冲突标记,生成最终版本
pnpm typecheck跑一遍- 把改动列表给你 review
场景 B:开 feature branch 干活
开一个新 feature branch, 叫 `feat/two-factor-auth`,
基于最新的 main。开完直接 checkout 过去。
Claude 自动跑:
git fetch origin
git checkout main
git pull origin main
git checkout -b feat/two-factor-auth
然后告诉你"已切到新分支,可以开干"。
场景 C:rebase 复杂历史
这种事永远要 Plan Mode 先看计划,再动手:
[Plan Mode]
我在 feature 分支上有 5 个 commit, 其中前 4 个是探索,
有大量 console.log 调试残留。我想:
- 把前 4 个 commit 合并(squash) 成 1 个干净的 commit
- 保留最后 1 个 commit 不动
- 合并后的 commit message 我来写, 你先草拟一份
帮我先列出 rebase 的具体步骤、可能的风险点, 不要动手。
Claude 会给你一份执行计划,包括 git rebase -i HEAD~5 后该怎么改 pick 为 squash、可能的冲突点等。你看完没问题再退出 Plan Mode 让它执行。
6.4 一句话救命操作
如果你不小心让 Claude 做了什么破坏性 git 操作,第一时间:
ctrl+c 中止当前操作, 然后告诉我刚才 Claude 跑了什么命令、HEAD 现在指向哪。
99% 的 git 操作都能用 git reflog 找回来。Claude 也会主动帮你恢复——你只要别在它修复之前继续乱跑命令。
七、第六步:Code Review
Code Review 是工程师最累的事之一。Claude Code 用 Subagent(子代理)能把一大半 review 工作替你做掉。
7.1 用 Subagent 定义专属 Reviewer
在你的项目根目录下创建 .claude/agents/code-reviewer.md:
---
name: code-reviewer
description: 严格的资深 Code Reviewer, 擅长找出安全、性能、可读性问题
model: opus
---
你是一位有 10 年经验的资深 Code Reviewer。
你的任务是评审用户给你的 diff 或代码片段, 严格、专业、不客气。
# 评审标准
## 1. 安全 (Security)
- SQL 注入、XSS、CSRF
- 密钥、token 泄露
- 权限漏洞、越权访问
- 不安全的反序列化
- 文件上传漏洞 (类型校验、路径穿越)
## 2. 性能 (Performance)
- N+1 查询
- 不必要的循环嵌套
- 内存泄漏 (未释放的监听器、定时器)
- 不必要的重渲染 (React 场景)
- 大对象的深拷贝
## 3. 可读性 (Readability)
- 命名是否清晰、一致
- 函数、方法是否太长 (> 50 行警告)
- 嵌套层级是否过深 (> 3 层警告)
- 注释是否解释"为什么"而非"做了什么"
## 4. 测试 (Testing)
- 是否有测试覆盖
- 测试是否覆盖了关键边界
- mock 是否合理 (没有 mock 自己要测的逻辑)
## 5. 风格 (Style)
- 是否符合项目根目录 CLAUDE.md 中定义的约定
- 是否符合语言常规风格
# 输出格式
按"严重程度"分三档:
## Block (必须改的)
> 这条不改我不会同意 merge
## Warn (强烈建议改的)
> 不改也能 merge, 但下次不希望再看到
## Nit (可选优化)
> 看你心情, 改不改都行
每一条必须给:
- **位置**: 文件路径:行号
- **问题**: 一句话说明
- **建议**: 具体改成什么样, 带代码示例
# 风格
- 不夸赞, 只挑刺。表扬留给作者爹妈。
- 不模糊。"建议优化"不算建议, "建议把 useState 改成 useReducer 因为状态超过 5 个"才算建议。
- 不啰嗦。一条 issue 三句话讲完。
7.2 调用这个 Reviewer
写完代码之后,你只需要说:
review 一下我刚写的这部分代码。
分支:feat/two-factor-auth(对比 main)
Claude Code 会自动派出 code-reviewer 这个 subagent,带着上面的 prompt 跑一遍 diff,然后输出形如:
## Block (必须改的)
### 1. SQL 注入风险
- 位置: `src/api/users.ts:47`
- 问题: 直接拼接 `where username = '${name}'`, 未做参数化
- 建议:
```ts
const users = await db.query(
"SELECT * FROM users WHERE username = ?",
[name],
);
```
### 2. 密钥写死在源码
- 位置: `src/lib/totp.ts:12`
- 问题: `const SECRET = "abc123def456"` 硬编码, 会随仓库泄露
- 建议: 改成读取 `process.env.TOTP_SECRET`, 并在 `.env.example` 加占位
## Warn (强烈建议)
### 3. 多余的 useEffect
- 位置: `src/pages/profile/TwoFactor.tsx:34-41`
- 问题: useEffect 里只是同步 props, 可以直接计算
- 建议: 删掉这个 useEffect, 在 render 阶段直接派生
### 4. 缺少错误边界
- 位置: `src/pages/profile/TwoFactor.tsx`
- 问题: 整个组件没有 error boundary, 一个抛错就白屏
- 建议: 用 `<ErrorBoundary fallback={...}>` 包一层
## Nit (可选)
### 5. 命名建议
- 位置: `src/lib/totp.ts:5`
- 问题: 函数 `gen` 不够具体
- 建议: 改成 `generateTotpCode`
7.3 把 Code Review 接到 PR 流程
如果你的项目用 GitHub,可以更进一步——让 Claude 自动 review 每个 PR:
- 在
.github/workflows/下加一个 workflow,PR 触发时调 Claude API - 把上面的 reviewer prompt 作为系统提示
- 把 PR diff 作为输入
- 把 review 结果以评论形式回贴到 PR 上
这套自动化第十四章会专门讲。这里你只要知道它能落地、能省你 80% 的 review 时间就行。
Code Review 用 Claude 的核心心法:让它打一遍分,你再决定要不要改。它不会直接改你的代码——它的角色是"挑刺的甲方",改不改你说了算。
八、第七步:重构与架构
重构是"大事",大事就要走 Plan Mode + Opus 这个组合拳。
8.1 流程模板
1. /model opus ← 切到最聪明的脑子
2. /plan ← 进入只读规划模式
3. 描述目标 + 约束 ← 让 Opus 出方案
4. 你 review,反复打磨 ← 来回 2-3 轮
5. /model sonnet ← 切回平价的手
6. 退出 /plan ← 让 Sonnet 干活
7. 分阶段执行,每阶段一个 PR
8.2 案例:把单体应用拆成多个微服务
第一步:让 Opus 出方案
/model opus
/plan
【目标】
当前是一个 Node.js + Express 单体应用, 所有业务都在一个进程里:
- 用户 (auth)
- 订单 (orders)
- 支付 (payments)
- 通知 (notifications)
随着业务变重, 部署一次要 8 分钟, 任何小改动都要重启整个服务。
我想把它拆成 4 个独立服务: auth-svc、orders-svc、payments-svc、notif-svc。
【约束】
- 现有数据库不能拆 (短期内还是一个 PostgreSQL)
- 服务间通信优先 HTTP (暂不引入 message queue)
- 必须保留一份"聚合 BFF"层给前端用, 前端无感
- 团队只有 3 个后端, 每周可投入 30 人时
【你的任务】
1. 给我一份 6 到 8 周的拆分路线图
2. 每周列出"做什么、做完的验收标准、风险"
3. 列出"必须先解决的技术债" (比如: 数据库的跨服务查询怎么办?)
4. 给一份"该买、该装"的工具清单 (API gateway、监控、CI/CD 改造)
5. 标出 3 个"如果不解决会让整个迁移失败"的关键点
只出方案, 不动代码。可以画 Mermaid 图。
Opus 会给你一份 3000 字以上的详细方案,带图、带表、带阶段拆分。这种方案如果让你自己琢磨,大概要花 2 个工作日。
第二步:你和团队一起 review
把 Opus 出的方案打印出来(或贴到 Notion),拉个会:
- 哪些假设不对?(可能 Opus 不知道你们公司的某些限制)
- 哪些步骤太激进?(可能 6 周拆 4 个服务对你们团队太狠)
- 哪些技术选择有更适合你们的替代?(可能你们公司禁用某些工具)
把 review 结果再喂回 Opus:
团队 review 后给的反馈:
1. 数据库短期不能拆, 这个保留
2. 6 周太紧, 改成 12 周, 每两周做一个服务
3. 公司禁用 Kong, 要换成 nginx + 自研路由
4. ……
请按这些反馈更新一版方案。
来回 2 到 3 轮,你会得到一份既专业又落地的执行方案。
第三步:切回 Sonnet 分阶段执行
/model sonnet
(退出 /plan, 正常模式)
按方案 v2 的 Week 1-2 执行: 把 auth 模块抽出去成独立服务。
具体步骤:
1. 在仓库根新建 services/auth-svc 目录
2. 把现有 src/auth/ 下的代码移到 services/auth-svc/src/
3. 在 services/auth-svc 加独立的 package.json、tsconfig、Dockerfile
4. 改造原 monolith, 通过 HTTP 调 auth-svc (走内网)
5. 加端到端测试, 确保用户登录流程不变
6. 改完跑全套测试, 确认绿
7. 提一个 PR
这就是 Opus 谋,Sonnet 行的完整流程。Claude Code 把"工程师最贵的那部分大脑"用便宜的方式给了你。
8.3 重构的两条铁律
| 铁律 | 解释 |
|---|---|
| 1. 永远先有测试再重构 | 重构的定义是"行为不变,结构变化"。没有测试你怎么证明行为不变?让 Claude 先补测试,再重构 |
| 2. 永远小步快跑 | 一次重构 200 个文件 = 灾难。让 Claude 拆成"每次 5 到 20 个文件、可以独立提交、可以独立回滚"的小步 |
九、第八步:完整 PR 工作流
我们把上面所有步骤串起来,走一个真实的 PR——从需求到合并。
9.1 需求来了
产品经理在企微群:"这周给用户中心加一个'修改密码'功能,要 OWASP 推荐的密码强度检测,要旧密码二次确认,要支持邮箱通知用户'你的密码被修改了'。"
9.2 第 1 步:让 Claude 出 Plan
/plan
【需求】
给用户中心加"修改密码"功能。
【约束】
- 必须验证旧密码
- 新密码必须通过 OWASP 推荐的强度检测 (长度 ≥ 12, 大小写、数字、符号至少各 1)
- 修改成功后, 后端必须发邮件通知用户 (用现有的 emailService)
- 必须有"密码可见、隐藏"的小眼睛切换
- 不能影响现有的登录会话 (改完密码不要把用户踢出去)
【约束 2】
- 前端用现有的 React + shadcn/ui
- 后端 Express, 数据库 PostgreSQL
- 必须有 e2e 测试
请给我:
1. 涉及到改动的文件清单
2. 数据库改动 (如果有)
3. 新增 API 接口的设计 (method、path、req、res)
4. 前端组件结构
5. 测试覆盖范围
6. 估算工时
Claude 输出方案,你看完觉得对,放行:
方案没问题, 开始执行。先做后端, 做完做前端, 最后 e2e。
退出 /plan。
9.3 第 2 步:Claude 写代码 + 测试
它会:
- 先开 feature branch:
feat/change-password - 写后端:新增
PUT /api/users/me/password接口、校验旧密码、强度检测、邮件通知 - 同步写后端测试(单元 + 集成)
- 写前端:新增
ChangePasswordDialog组件,接到用户中心 - 同步写前端测试(组件级 + 集成级)
- 写 e2e 测试:Playwright 模拟"打开用户中心 → 改密码 → 验证邮件 → 重新登录"
整个过程你坐在屏幕前看,重要决策它会停下来问你(比如"邮件模板放哪个文件?")。
9.4 第 3 步:Hook 自动跑 lint + 测试
如果你配置了 PreCommit Hook(第九章会详细讲),每次 Claude 想 commit,Hook 会自动跑:
pnpm lint
pnpm typecheck
pnpm test
任何一项失败,commit 被拦截,Claude 自动看错误信息再修。它不会绕过 Hook——除非你明确说"跳过 hook"。
9.5 第 4 步:Claude 提交 + push 分支
git add .
git commit -m "$(cat <<'EOF'
feat(profile): 新增"修改密码"功能
- 新增 PUT /api/users/me/password 接口, 校验旧密码 + 强度检测
- 新增 ChangePasswordDialog 组件, 集成到用户中心
- 修改成功后通过 emailService 发送通知
- 不影响现有登录会话 (只更新密码 hash, 不轮换 token)
- 补 12 条单测、4 条集成测试、2 条 e2e
EOF
)"
git push -u origin feat/change-password
9.6 第 5 步:Claude 自动开 PR(GitHub MCP)
如果你装了 GitHub MCP(第十一章会讲),Claude 自动调用 gh pr create,生成的 PR body 长这样:
## 这个 PR 做了什么
为用户中心加"修改密码"功能, 完整覆盖前端组件 + 后端接口 + 邮件通知 + 测试。
## 改动清单
### 后端
- 新增 `PUT /api/users/me/password` (`src/api/users.ts`)
- 抽出 `passwordStrengthCheck` (`src/lib/security/password.ts`)
- 集成 `emailService.sendPasswordChangedNotice`
### 前端
- 新增 `ChangePasswordDialog` (`src/pages/profile/ChangePasswordDialog.tsx`)
- 在 `ProfilePage` 增加入口按钮
- 复用现有的 `PasswordInput` (支持小眼睛切换)
### 测试
- 后端: `src/api/__tests__/users.password.test.ts` 12 条
- 组件: `src/pages/profile/__tests__/ChangePasswordDialog.test.tsx` 6 条
- e2e: `e2e/change-password.spec.ts` 2 条
## 怎么验证
1. 跑 `pnpm test` 全绿
2. 跑 `pnpm e2e` 全绿
3. 本地 `pnpm dev` 后, 登录任意账号, 在用户中心点"修改密码"
- 用错的旧密码 → 提示错误
- 用强度不够的新密码 → 提示强度不足
- 修改成功 → 收到邮件 + 当前会话保持登录
## 风险与回滚
- 邮件发送失败时不应阻塞密码修改成功 (已用 try-catch + 异步队列)
- 如有问题, revert 此 PR 即可, 数据库无 schema 变更
9.7 第 6 步:你 review → merge
PR 进来,你打开:
- 看 description 一眼,知道这个 PR 干什么
- 看测试是否通过(CI 会跑一遍)
- 重点看"安全相关的代码"(密码、token、权限)
- 派
code-reviewersubagent 再扫一遍 diff
review 一下 #142 这个 PR, 重点看安全相关代码。
确认没问题:
merge 这个 PR, 用 squash 模式, 删除 source branch。
Claude 自动跑 gh pr merge 142 --squash --delete-branch,然后告诉你:
PR #142 已 merge 到 main, 远端 feature 分支已删除。 CI 触发了 staging 自动部署, 5 分钟内生效。 你的本地分支也已清理 + 切回 main + pull 最新。
整个 PR 从需求到合并,你的"实际敲键盘时间"可能不超过 10 分钟。剩下的 90% 时间是在 review、决策、确认。这就是 Claude Code 当队友的样子。
十、第九步:调试技巧
修 Bug 不是只能"读代码 + 猜"。Claude 能"亲自跑一遍"、"加日志再跑一次",这是它远胜传统 IDE 的关键能力。
10.1 让 Claude 亲自跑代码
我刚写的 src/lib/exchange.ts, 执行后输出和预期不符。
请你:
1. 跑 `pnpm tsx src/lib/exchange.ts` 看实际输出
2. 跟预期对比, 找出哪一步开始偏差
3. 加 debug log 再跑一遍, 定位精确出错位置
4. 给修复方案, 但不要立即改, 先告诉我
预期输出: `{ from: "USD", to: "CNY", rate: 7.25 }`
Claude 会真的去跑,看到实际输出,自己分析:
实际跑出来:
{ from: "USD", to: "CNY", rate: 7.25, fee: NaN }多了一个
fee: NaN。我看了源码,第 47 行fee = amount * feeRate, 但feeRate在getRate("USD", "CNY")没传入,所以是undefined。 这个字段你接口设计上应该有还是不应该有?
10.2 让 Claude 配合 Playwright 自验
前端改动尤其有用:
我刚改了 src/pages/login/LoginPage.tsx 的"忘记密码"按钮位置。
请你:
1. 启动 dev server (pnpm dev)
2. 用 Playwright 打开 http://localhost:5173/login
3. 截图保存到 /tmp/login.png
4. 描述截图里"忘记密码"按钮在哪里、看起来对不对
Claude 调用 playwright 工具,真的开浏览器、真的点页面、真的截图、真的看图(多模态),然后给你输出:
截图已保存。我看到登录框右下角有"忘记密码?"链接, 离"登录"按钮约 4px 间距,字号比按钮文本小 2px。 视觉上偏挤,建议把链接和按钮之间的间距调到 12px。
10.3 让 Claude 解释错误堆栈
收到一个 stack trace,直接贴给它:
跑测试时出现:
TypeError: Cannot read properties of undefined (reading 'toLowerCase')
at normalizeEmail (src/lib/email.ts:23:18)
at validateInput (src/api/auth.ts:47:23)
at handler (src/api/auth.ts:89:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
请你:
1. 解释每一帧栈意味着什么 (给完全不懂的同事看)
2. 定位最可能的根因
3. 给修复方案
Claude 会逐帧拆解、给中文解释、定位根因(往往是某个上游没传值或值为 null)、给修复代码。这一招对"想学编程的非程序员"价值极大——你看不懂栈,Claude 一帧一帧给你翻译。
10.4 调试三件套小提示词
收藏下面这三段,直接当"调试急救包"。
急救一:没头绪
代码不知道为什么不工作, 我也描述不清楚。
请你接管:
1. 跑一遍代码, 看实际输出
2. 对比预期 (预期是: xxx)
3. 加 console.log 二分定位
4. 找到根因后, 告诉我怎么修
急救二:间歇性 bug
这个 bug 偶尔出现 (约 30% 概率)。请你:
1. 重复跑 50 次, 统计出错率
2. 对比成功、失败时的输入差异
3. 提出"什么情况下必现"的假设
4. 写一个稳定复现的测试
急救三:性能问题
@src/api/dashboard.ts 这个接口慢得让人发疯。
请你:
1. 加性能日志 (每个数据库查询、每个外部调用)
2. 跑一次完整请求, 统计每段耗时
3. 找出 top 3 最慢的环节
4. 给优化建议 (不要立刻改)
十一、第十步:写"小工具"
到这里,我们把"读懂 → 修 → 测 → 改 → review → 重构 → PR"全跑了一遍。但 Claude Code 还有一个非常被低估的用法——让普通人也能 5 分钟写出有用的小工具。下面给 6 个完整提示词,你可以直接复制改改用。
11.1 批量改文件名
我有一个文件夹 ~/Pictures/iphone-export/, 里面有 800 张从 iPhone 导出的照片,
文件名乱七八糟 (IMG_E1234.jpg、PXL_20231203_xxxx.jpg、image (5).png 等)。
请你:
1. 写一段 Python 脚本, 递归读取这个文件夹
2. 按"拍摄时间"重命名为 YYYYMMDD-HHMMSS-原后缀.jpg 格式
3. 拍摄时间从 EXIF 读; 读不到 EXIF 的退化用文件修改时间
4. 不要直接改原文件, 先输出"将要改成什么"的预览
5. 我确认无误后, 你再真正执行
6. 改完输出统计: 成功 N 张、EXIF 失败 N 张、跳过 (已经是规范名) N 张
11.2 抓某个网页的数据
帮我抓取 https://example.com/products 这个页面的所有商品数据。
页面里每个商品是一个 div.product-card, 每个卡片包含:
- 商品名 (.product-name)
- 价格 (.product-price)
- 库存状态 (.product-stock)
- 商品详情页链接 (a.product-link 的 href)
要求:
1. 用 Python + playwright (因为是 SPA 需要执行 JS)
2. 自动翻页, 抓完所有页 (看页码 div.pagination)
3. 输出成 CSV (列: name, price, stock, url)
4. 加 1 秒间隔, 礼貌爬取
5. 失败的页记录到 errors.log
11.3 自动给图片加水印
帮我写一个 Python 脚本, 给一个文件夹下所有图片加水印。
要求:
1. 输入: 文件夹路径 (命令行参数 1)、水印文字 (命令行参数 2)
2. 在每张图右下角加文字水印
3. 字体半透明白色 + 黑色描边, 在任何背景上都看得见
4. 字号是图片宽度的 3%, 自动适配
5. 不覆盖原文件, 输出到同目录的 watermarked/ 子文件夹
6. 给一个使用示例: `python watermark.py ./photos "©我的相册 2026"`
11.4 把 CSV 导入数据库
我有一个 sales.csv 文件, 30 万行, 需要导入 PostgreSQL。
列: order_id, customer_email, product_sku, amount, created_at
要求:
1. 写 Python 脚本, 用 psycopg + COPY 命令 (快)
2. 在导入前先建表 (给我 CREATE TABLE 语句, 索引建在 customer_email 和 created_at)
3. 数据清洗:
- amount 列可能有 "$" 和 "," 符号, 去掉再转 numeric
- created_at 可能是 "MM/DD/YYYY" 或 ISO, 统一转成 timestamptz
- email 全部转小写
4. 用事务, 失败回滚
5. 进度条显示 (每 1 万行打一次)
6. 完成后报告: 总行数、成功、失败、耗时
11.5 监控某个文件夹有变化就推送
我希望写一个后台服务, 监控 ~/Downloads/ 文件夹:
- 一旦有 .pdf 文件新增, 就发一条飞书通知到我的群里
- 通知内容: 文件名、大小、首页缩略图
- 多个文件 5 秒内合并发 (避免刷屏)
要求:
1. Python + watchdog 库
2. 飞书 webhook 地址我已经有 (URL 我会贴给你)
3. PDF 缩略图用 pdf2image
4. 后台运行, 挂到 launchctl (我用 macOS)
5. 给一个简单的"启动、停止、状态"脚本
11.6 简单 GUI 工具(让普通人能用)
我妈想要一个"批量重命名照片"的工具, 但她不会用命令行。
请你:
1. 用 Python tkinter 写一个 GUI
2. 界面只有 3 个东西:
- "选择文件夹"按钮
- 一个文本框, 显示选了哪个文件夹
- "开始重命名"按钮
3. 重命名规则: 按拍摄时间排序, 改成"我妈的照片-001.jpg、002.jpg ..."
4. 进度条 + 完成后弹窗"已重命名 N 张"
5. 打包成 macOS 的 .app (用 py2app 或 pyinstaller)
6. 给我一份"教我妈怎么用"的简单图文说明
这 6 个例子的共同点:普通人可能完全不知道用什么库、怎么下手,但描述清楚要做什么、给清楚约束,Claude Code 能 5 到 15 分钟内交付一个能跑的版本。这就是这本书反复强调的:会写代码 ≠ 必须会代码,会描述需求才是新时代的核心能力。
十二、避坑:编程场景 8 大坑
最后一节,我把"编程场景下最常翻车的 8 个坑"给你一次性列清,每个都附"怎么避"。
坑 1:让 Claude 直接改 node_modules
症状:为了快速验证某个第三方库的 bug,你说"改一下 axios 的 dispatchRequest 函数"。Claude 真去改了 node_modules/axios/...。下次 pnpm install 改动全没了,你以为修好的 bug 又复活。
避坑:
- 在
CLAUDE.md里硬性禁止:永远不要修改 node_modules/ 下的任何文件 - 真要改第三方库,用
pnpm patch <pkg>生成持久化补丁
坑 2:让 Claude 操作生产数据库
症状:你跑了 claude 在生产服务器上,想让它"统计一下今天的订单数"。它顺手跑了 DELETE FROM orders WHERE created_at < ... 试图清理"老数据"。生产几个月数据没了。
避坑:
- 永远不要在生产服务器上跑 Claude Code,改用一台跳板机连只读副本
- 在
~/.claude/CLAUDE.md全局设:永远不要执行 DELETE、TRUNCATE、DROP、UPDATE,即使是模拟。除非用户明确说"在生产执行" - 数据库密码用只读账号
坑 3:把 .env 给 Claude
症状:Claude 帮你看 bug,顺手 cat .env 把数据库密码、API Key、JWT Secret 全读进上下文。这些内容会被发到 Anthropic 服务器(你订阅 Pro/Max 时同意过)。下次会话还可能被拼回到提示词里。
避坑:
在项目根加 .claudeignore 文件:
# Secrets
.env
.env.*
!.env.example
# Keys & certs
*.pem
*.key
*.p12
secrets/
# Personal
.DS_Store
.idea/
.vscode/
# Build
dist/
build/
node_modules/
这份文件的语法和 .gitignore 一样。被它匹配到的文件,Claude Code 完全不会读——即使你用 @ 显式引用,它也会拒绝。
坑 4:复杂改动不走 Plan Mode
症状:你说"重构一下整个 auth 模块",Claude 直接动手改了 30 个文件,你后悔已经晚了。
避坑:
- 任何"涉及 ≥ 5 个文件"的改动,先
/plan看计划再放行 - 大改动一定先开 feature branch,出问题
git reset --hard origin/main还能回得来
坑 5:用最新 Beta 模型做生产代码
症状:Anthropic 出了 Opus 4.7 Beta,你 /model opus-beta 立刻换上。结果某些 API 调用响应格式微变,生产代码里的兼容代码崩了。
避坑:
- 生产代码永远用 GA 版本(
sonnet、opus、haiku),不要用带-beta后缀的 - 要尝试新模型,在分支里玩,别合 main
- 在
~/.claude/CLAUDE.md写:永远不主动切换到 beta 或 preview 模型,除非我明确要求
坑 6:长会话不 /compact
症状:一个会话开了 4 小时,聊了 200 条。后面 Claude 突然忘了开头说的"永远用 named export"这条规则,开始默认导出。
原因:Claude 的上下文窗口有上限(Sonnet 4.5 是 200k token,Opus 是 200k),超过会"丢前面"。
避坑:
- 长会话每隔 1 到 2 小时跑一次
/compact(压缩历史保留要点) - 或者直接
/clear开新会话,把"必须保留的规则"放到CLAUDE.md里(永远不会丢)
坑 7:多 Subagent 并行没设上限
症状:你写了一个"自动跑测试 + 自动 review + 自动写文档"的 workflow,每个步骤派一个 subagent。结果一次任务跑了 12 个 subagent,每个 subagent 自己又派 subagent,最后 50 个进程并发,API 账单当月翻 5 倍。
避坑:
- 在
~/.claude/CLAUDE.md设:并发 subagent 最多 3 个,深度最多 2 层 - 每个 subagent 的提示词里明确:
你不能再派出更多 subagent - Anthropic 控制台开"账单告警",超过 X 美元自动报警
坑 8:PR 自动化提交前没人 review
症状:你做了一套全自动 workflow:Claude 改完代码 → 跑测试 → 通过就 push → 自动开 PR → 自动 merge。某天 Claude 把测试也"修改"通过了(把失败的 assertion 改成 expect(true).toBe(true)),自动合到 main 了。生产挂了。
避坑:
- 永远在"merge"这一步留人审。可以全自动到"PR 创建",但 merge 必须人工点
- 在仓库里设 GitHub Branch Protection:main 必须至少 1 个 review approval 才能 merge
- 在
CLAUDE.md加:永远不要修改测试文件来让测试通过,除非用户明确说"测试本身写错了"
8 大坑速查
| # | 坑 | 一句话避坑 |
|---|---|---|
| 1 | 改 node_modules | .claudeignore + pnpm patch |
| 2 | 操作生产 DB | 永远别在生产跑 Claude |
| 3 | 泄漏 .env | .claudeignore 必装 |
| 4 | 大改不 plan | ≥5 文件就 /plan |
| 5 | 用 Beta 模型 | 生产用 GA,beta 留分支玩 |
| 6 | 长会话忘记 | /compact 或 /clear |
| 7 | Subagent 失控 | 限并发 3、限深度 2 |
| 8 | 自动 merge | merge 一定人工 |
本章一图回顾
┌─────────────────────────────────────────────────────────────┐
│ Claude Code 编程场景全工作流 │
└─────────────────────────────────────────────────────────────┘
/init Plan Mode + @file
┌────────────┐ ┌──────────────────┐
│ 认识项目 │ ────────▶ │ 读懂代码库 │
│ CLAUDE.md │ │ 理解架构 │
└────────────┘ └──────────────────┘
│
▼
┌──────────────────┐
│ 修 Bug │
│ ① 复现 │
│ ② 定位根因 │
│ ③ 改代码 + 测试 │
└──────────────────┘
│
▼
┌──────────────────┐
│ 写测试 │
│ TDD: 红→绿→重构 │
│ 覆盖率 ≥ 95% │
└──────────────────┘
│
▼
┌──────────────────┐
│ Git │
│ Conventional │
│ Commit + Push │
└──────────────────┘
│
▼
┌──────────────────┐
│ Code Review │
│ Subagent 打分 │
│ Block / Warn / │
│ Nit 三档 │
└──────────────────┘
│
▼
┌──────────────────┐
│ 重构与架构 │
│ Opus 谋 │
│ Sonnet 行 │
└──────────────────┘
│
▼
┌──────────────────┐
│ 开 PR │
│ GitHub MCP │
│ 自动生成描述 │
└──────────────────┘
│
▼
┌──────────────────┐
│ 人工 review │
│ → squash merge │
└──────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 关键指令速查 │
│ ──────────────────────────────────────────────── │
│ /init 生成 CLAUDE.md │
│ /plan 进入只读规划模式 │
│ /model opus 切到最强模型(规划用) │
│ /model sonnet 切到平衡模型(执行用) │
│ /compact 压缩长会话历史 │
│ /clear 清空会话(保留 CLAUDE.md) │
│ @path/to/file 引用文件到上下文 │
│ Shift+Tab 快捷切 Plan Mode │
│ .claudeignore 排除文件不让 Claude 读 │
└─────────────────────────────────────────────────────────────┘
一句话心法
──────────────────────────────────────────────────────────────
Claude Code 是会写代码的助理,不是替代你的工程师。
"想做什么"、"做成什么样"、"出了 bug 谁背"——永远在你自己。
下章预告
到这里,你已经会让 Claude Code 完成单次编程任务了——从理解项目、修 bug、写测试、提交 PR,一条龙。
但 Claude Code 真正的杀手锏,不是单次任务——是让它替你 24 小时不下班地干活。
第九章 自动化与定时任务(/loop 与 Hooks) 会教你三件事:
/loop命令:让 Claude 在一个目标下反复迭代,直到达成或显式喊停。比如"持续优化这段代码,每轮跑一次 benchmark,直到性能提升 50% 或确认无可优化"。- Hooks 系统:在关键事件(commit 前、文件保存后、PR 提交后……)自动跑你写的脚本。让 lint、测试、部署、通知全自动化。
- 定时任务:把"每天早上 8 点收 RSS、提炼新闻、发企微"这种任务交给 Claude Code + cron / launchd,你睡觉它干活。
会用单次任务的 Claude Code 是会动手的助理,会用自动化的 Claude Code 是24 小时不下班的员工。下一章见。