给 Claude Code 写好指令——Prompt 工程实战指南
AI Coding 系列第 02 篇 · 上手必读
前言:为什么同样的工具,效果差这么多
同一个 Claude Code,有人用它十分钟写完一个功能,有人来回改了八次还是不对。
工具一样,差距在哪?
大多数情况下,不是模型的问题,是指令的问题。
Claude Code 本质上是一个语言模型,它对你说的话字面上非常认真。你说"帮我优化一下这个函数",它不知道你说的是性能优化、可读性优化还是内存优化——它会猜,猜对了是运气,猜错了你就要返工。
Prompt Engineering(指令工程)听起来像一个专业词汇,实际上就是一件事:怎么把你脑子里的需求,清晰地传递给 AI。
这篇文章不讲理论,只讲在 Claude Code 里真实有效的方法,每一个都附带对比案例,看完就能用。
一、最核心的原则:给结果,不给过程
新手写 Prompt 最常见的错误,是描述自己想做什么,而不是描述想要什么结果。
❌ 低效写法:
帮我优化这个函数
✅ 高效写法:
这个函数现在平均执行时间 200ms,目标是降到 50ms 以内。
主要瓶颈我怀疑在数据库查询那里,但不确定。
请先分析性能瓶颈,再给出优化方案,不要直接改代码。
区别在哪?
- 第一个:Claude 不知道你的优化目标,不知道从哪个方向切入,只能猜。
- 第二个:有具体目标(50ms)、有怀疑方向(数据库查询)、有明确的输出要求(先分析再方案,不要直接改代码)。
一个好的 Prompt 至少包含三个要素:
- 背景:当前是什么情况
- 目标:你想要达到什么结果
- 约束:有什么不能做、必须遵守的限制
这三个要素不需要每次都写得很长,但缺一个,Claude 就会去猜。
二、上下文:给够,但不要给废
Claude Code 的上下文窗口是有限的,放进去的内容越多,它能"看到"的东西越清晰,但也越容易被噪音干扰。
上下文给什么:
- 相关文件的路径(让它能直接读)
- 项目用了什么技术栈
- 已经尝试过什么方法、为什么不行
- 这个功能的业务背景(为什么要做这件事)
上下文不给什么:
- 不相关的代码文件(只会占用上下文,让 Claude 分心)
- 你自己都没整理清楚的想法(先想清楚再说)
- 重复说明同一件事
实际案例对比:
❌ 低效写法(信息太少):
帮我在用户系统里加一个角色权限功能
✅ 高效写法(上下文清晰):
项目:Node.js + Express + PostgreSQL,ORM 用 Prisma
现有用户系统在 /src/modules/user/ 目录下
需要加角色权限功能,角色分三种:admin、editor、viewer
权限控制在路由层做,不要改 controller 层逻辑
已有 JWT 认证中间件在 /src/middleware/auth.ts
请先看现有的用户模型(User model),再设计角色表结构,最后给实现方案
第二个给了:技术栈、代码位置、角色定义、技术约束(路由层、不改 controller)、已有相关代码位置、任务顺序。Claude 能直接开始干活,不需要额外猜测。
三、分解任务:大任务拆成小步骤
一个常见的失败模式:把一个复杂任务一次性扔给 Claude,期待它直接给出完美结果。
这在简单任务上可以,在复杂任务上几乎必然失败。原因是 Claude 在没有明确步骤的情况下,会做出很多隐含的决策——数据库表怎么设计、接口怎么命名、错误怎么处理——每一个决策都可能和你的预期不符。
正确做法:把大任务拆成有明确输出的步骤,一步步确认。
以"开发一个用户认证系统"为例:
❌ 一次性写法:
帮我开发一个完整的用户认证系统,包括注册、登录、JWT、刷新 token
✅ 分步写法:
第一步:先帮我设计数据库表结构,只给 SQL,不要写代码
要求:用户表、token 表,支持多设备登录
(确认表结构没问题后)
第二步:基于刚才的表结构,实现注册接口
只写 /src/modules/auth/register.ts,遵循项目现有的错误处理规范
(确认注册接口没问题后)
第三步:实现登录接口,返回 access_token 和 refresh_token
access_token 有效期 15 分钟,refresh_token 7 天
每一步都有明确的输出范围,你可以在每一步检查结果,发现问题马上纠正,不会等到全部做完才发现方向错了。
什么时候需要拆步骤:
- 任务涉及超过 3 个文件的改动
- 任务有多个相互依赖的子任务
- 你对最终方案不完全确定,需要边做边看
- 任务涉及数据库结构变更(一旦错了代价很大)
四、约束条件:把"不能做什么"说清楚
这是最容易被忽视的一点。
Claude 在没有约束的情况下,会按照它认为"最优"的方式实现。但"最优"往往和你的项目现状不符:
- 它可能会引入你们团队没用过的库
- 它可能会改动你明确不想动的文件
- 它可能会用一种和现有代码风格完全不同的写法
把约束条件明确写出来:
实现这个功能时:
- 不要引入新的 npm 包,用现有的工具
- 不要修改 /lib/auth.ts,那个文件是共享的
- 函数命名遵循现有代码的 camelCase 风格
- 错误处理用项目统一的 AppError 类,不要用原生 Error
约束条件可以提炼成 CLAUDE.md 里的全局规则(下一篇会详细讲),这样每次都自动生效,不用重复写。
五、输出格式:告诉 Claude 你要什么形式
Claude 的输出形式非常灵活,但如果你不指定,它会做默认决策——有时是你要的,有时不是。
常见的输出格式要求:
只给代码,不要解释
给代码之前先给方案,我确认了再写代码
给出修改前后的对比,用 diff 格式
分三个方案给我,各自说明优缺点,最后给你的推荐
用中文注释解释关键逻辑,其他不需要注释
在调试场景里尤其重要:
帮我找这个 bug,但不要直接改代码
先告诉我你的分析过程,你认为问题出在哪、为什么
这样你能看到 Claude 的推理过程,判断它的方向对不对,再决定是否让它动代码。
六、角色设定:让 Claude 切换思维模式
Claude Code 支持在 Prompt 里给它设定角色,这不是噱头,对输出质量有实际影响。
不同角色会触发不同的思维侧重:
你是一个有十年经验的后端工程师,对性能优化非常敏感
帮我 review 这段代码,重点关注可能的性能问题
你是一个安全工程师
帮我检查这个登录接口,列出所有可能的安全漏洞
你是一个刚加入项目的初级工程师,不了解任何背景
读一下这段代码,告诉我你看不懂的地方
最后这个用法特别有价值——用它来检验你的代码可读性。如果连"初级工程师 Claude"都能看懂,代码的可维护性基本过关。
七、迭代对话:把 Claude 当协作者,不是执行者
很多人用 Claude Code 的方式是:给指令 → 等结果 → 不满意 → 重新给指令。
这是低效的用法。
更好的方式是迭代对话:把 Claude 当成一个你在和它实时协作的同事。
迭代对话的节奏:
你:先帮我分析一下这个问题,不要急着给解决方案
Claude:[分析]
你:你说的第二点我觉得不对,因为我们的数据量其实很小,
性能不是主要瓶颈,可维护性更重要
Claude:[调整分析方向]
你:好,基于这个方向,给我一个实现方案
Claude:[方案]
你:方案整体可以,但第三步我不想用 Redis,
我们现在没有 Redis,用数据库实现
Claude:[调整方案]
你:OK,开始实现
这种对话模式下,你在持续校准 Claude 的方向,最终结果和你的预期会高度一致,而不是反复推倒重来。
八、处理不确定性:让 Claude 先问再做
当任务有歧义,或者你自己对需求还不确定时,一个非常有用的技巧:
我想实现 X 功能,但我对一些细节还不确定
在你开始之前,先问我三到五个你认为关键的问题
Claude 会提出它认为最关键的问题,这些问题本身就很有价值——它能帮你发现你自己没意识到的需求盲区。
实际例子:
我想给我们的 API 加一个限流功能,在你开始之前,
先问我你认为需要明确的关键问题
Claude 可能会问:
- 限流的维度是什么?按用户、按 IP、还是按接口?
- 超过限制是返回错误还是排队等待?
- 限流的计数是存在内存还是 Redis?
- 不同接口需要不同的限流策略吗?
这些问题如果在开始实现之前没有答案,最终代码很可能需要大改。让 Claude 先问,等于提前做了需求评审。
九、常见错误模式和修正
错误一:太模糊
❌ 帮我写一个好的错误处理
✅ 给这个 Express 路由加错误处理,捕获数据库连接失败和数据验证失败两种情况,分别返回 503 和 400 状态码,错误信息格式参考 /src/types/error.ts
错误二:期待 Claude 读心术
❌ 这个不对,重新写
✅ 这个实现的问题是:它在每次请求时都创建新的数据库连接,应该用连接池。请修改这一点,其他逻辑不变
错误三:一次改太多
❌ 一个 Prompt 里要求同时重构代码结构、加单测、改接口设计
✅ 每次只做一件事,做完确认再继续
错误四:不给失败案例
❌ 帮我写一个邮件验证函数
✅ 帮我写一个邮件验证函数,这些输入应该返回 true:user@example.com、user+tag@example.co.uk;这些应该返回 false:@example.com、user@、user@.com
给出具体的正反例,比描述规则更精确。
错误五:忘记说明已有约束
❌ 给这个 API 加缓存
✅ 给这个 API 加缓存,项目里已经有 node-cache,直接用它,不要引入 Redis 或其他缓存库
十、规则 vs 用例:描述行为,不是枚举结果
有一类错误值得单独说,因为很多人深陷其中却不自知。
某工程师让 Claude 写一个处理括号的函数,给了一张测试用例表:
ABC(DEF)GH → ABC(DEF)GH
(ABCDEFGH) → (ABCDEFGH)
(ABC(DEF)GH) → (ABC(DEF)GH)
ABC(DEF)GH) → ABC(DEF)GH
(ABC(DEF)GH → ABC(DEF)GH
Claude 看着这些用例会猜测一套规则——但猜出来的未必是你心里那套。结果是:Claude 给出的函数能通过这五个用例,但遇到第六个边界情况就出错了。
问题不是 Claude 不够聪明,是你给的是用例,不是规则。
- 用例:输入 X 应该得到 Y(枚举具体结果)
- 规则:遇到 A 情况时,做 B 操作(描述行为逻辑)
用例是规则的外在表现,不是规则本身。从少量用例反推规则的可能不止一种,Claude 会选它认为最合理的那个,但那个未必是你要的。
正确的方式是先把规则用自然语言说清楚,再附用例作为验证:
括号处理规则:
1. 括号配对完整(每个开括号都有对应闭括号)→ 不改动
2. 有多余的闭括号(无对应开括号)→ 删除该闭括号
3. 有多余的开括号(无对应闭括号)→ 删除该开括号
4. 嵌套括号从内到外判断配对
以下用例用于验证,实现正确时所有用例应全部通过:
[用例表]
这在业务逻辑里更为关键。"已下单未支付的订单,用户可以取消,但支付后不能取消"是规则;"以下这些测试场景要通过"是用例。拿用例当规则,Claude 能猜,但猜不全。
十一、场景化 Prompt 模板
把上面的原则整合成几个高频场景的模板,可以直接复用:
场景一:实现新功能
背景:[项目技术栈、相关文件位置]
需求:[具体要实现什么]
约束:[不能动哪些文件、不能引入哪些库、必须遵循什么规范]
输出:[先给方案/直接实现/先问关键问题]
场景二:排查 Bug
问题现象:[用户看到了什么、错误信息是什么]
复现步骤:[怎么触发这个问题]
已经排查过:[你已经看过哪里、排除了什么可能]
相关代码:[文件路径,让它自己读]
请先分析可能的原因,不要直接改代码
场景三:代码 Review
请 review 这段代码,重点关注:
1. 潜在的 bug 或边界情况
2. 性能问题
3. 安全漏洞
4. 可读性和可维护性
对于每个问题,说明严重程度(high/medium/low)和修改建议
场景四:重构
需要重构 [文件/模块]
重构目标:[可读性/性能/解耦/减少重复]
不能改变:[对外接口/函数签名/数据库结构]
请先给重构方案,列出要做哪些改动,我确认后再动代码
场景五:技术选型
我需要在项目里实现 [功能]
候选方案:[方案A、方案B](或者让 Claude 自己列)
项目约束:[团队技术栈、维护成本、性能要求]
请从这几个维度对比:[实现复杂度、维护成本、性能、生态成熟度]
最后给出推荐,说明理由
十二、本篇实践任务
学完要动手,这是这篇文章的配套练习:
任务一(基础): 找一个你最近写的需求描述或者 bug 报告,用"背景 + 目标 + 约束"三要素重写一遍,感受一下信息密度的变化。
任务二(中级): 选一个你项目里真实的小功能需求,用分步写法实现它:先让 Claude 只给方案,你确认后再让它写代码。注意观察"先分析再实现"和"直接实现"的结果质量差异。
任务三(进阶): 找一段你自己写的函数或模块,用这个 Prompt 让 Claude review:你是一个刚加入项目的初级工程师,不了解任何背景,读一下这段代码,告诉我你看不懂的地方。 看看 Claude 指出的问题,对照检查你代码的可读性。
总结
这篇的核心只有一件事:Claude Code 的输出质量,80% 取决于你给它的指令质量。
三个最重要的习惯:
一是给结果不给过程——说你要什么,不说你要怎么做。
二是约束要说清楚——你不想要什么,比你想要什么更重要。
三是复杂任务分步走——不要期待一步到位,边做边校准比推倒重来效率高得多。
这些习惯不需要一次全部养成,从下一个任务开始,把"背景 + 目标 + 约束"三要素写进你的 Prompt,就已经比大多数人用得好了。
下篇预告
第 03 篇:Commands 入门——你必须知道的 Claude Code 内置命令
/init、/clear、/compact、/review……这些命令是 Claude Code 日常使用频率最高的操作,很多人装了 Claude Code 但完全没用过它们,每天在手动做本可以一个命令完成的事情。下一篇全部说清楚。
AI Coding 系列持续更新,欢迎关注。