像 Boris Cherny 那样使用 Claude Code 的 10 个 Slash Commands
像 Boris Cherny 那样使用 Claude Code 的 10 个 Slash Commands
像 Boris Cherny 那样使用 Claude Code 的 10 个 Slash Commands 像 Boris Cherny 那样使用 Claude Code 的 10 个 Slash Commands Modified April 12 Code block Markdown Copy Are there implicit type coercions that could cause subtle bugs? Concurrency: Could any state mutation cause race conditions if called concurrently? Are shared resources properly synchronized? What happens if this function is called twice before the first call completes? Dependencies: Are imports used? Flag any unused imports. Are there circular dependency risks? Is the module tightly coupled to implementation details it shouldn't know about? Naming and structure: Do function names accurately describe what they do (including side effects)? Are there functions doing more than one thing that should be split? Output format For each finding, give: Severity: 🔴 Critical (will cause bugs) / 🟡 Warning (could cause issues) / 🔵 Note (improvement) The specific code location What could go wrong A suggested fix (code, not just description) 下面是 /dissect src/routes/predict.py 审查 prediction endpoint 的效果: No access 1oPBcAo2A6Kuc06z 00:00 这次 review 把问题组织到了六个维度里,但最亮眼的是它抓到了一些普通 linter 根本抓不到的东西,比如: • 一个损坏的 API contract:model version 虽然出现在 request schema 中,但在两个 handlers 里都被悄悄忽略了 • 当模型没有加载时,接口返回的是 200 OK 加空数据;它本该返回 503 • 单条延迟被错误地记录成“总耗时的平均值”,而不是真正的单条测量值 它还交叉读了测试文件,并指出一个很关键的问题:现有测试居然把 “model not loaded 时返回 200” 这个错误行为本身写进了断言里。 最后的 “Top 3” 优先级列表也非常有价值,因为它直接给你一个适合单次 commit 的行动清单。 Command 5:/testmatch 上面的 review 已经指出了若干未覆盖的代码路径,这时候就轮到 /testmatch 了。 AI 生成测试的一大问题在于:它们几乎从来不会匹配你项目现有的测试风格。 断言库、命名风格、setup 模式,全都可能不一样。 这个命令会先读取你已有的测试,再生成“看起来像是你团队里某个人写出来”的新测试。 Code block Markdown Copy description: Generate tests that match existing project test patterns allowed tools: Read, Glob, Grep, Bash(npx ), Bash(npm test ) argument hint: <file to test Generate tests for: $ARGUMENTS Step 1: Learn the existing test patterns Before writing anything, find and read 2 3 existing test files in this project: ! From those files, identify: Test framework (jest, vitest, mocha, pytest, etc.) Assertion style (expect/assert/should/chai) Naming convention for describe/it blocks Setup and teardown patterns (beforeEach, fixtures, factories) Mocking approach (jest.mock, sinon, manual mocks, dependency injection) File naming convention ( .test.ts, .spec.ts, tests / ) Step 2: Read the target file Read $ARGUMENTS completely. Understand every function, every branch, every error path. Step 3: Generate tests Write tests that: Follow EXACTLY the patterns found in Step 1 Cover every exported function/method Include happy path, error cases, and edge cases Test boundary values and null/undefined inputs Use the same mocking approach as existing tests Use the same file naming convention Place the test file adjacent to the source file following the project's convention. Do NOT use any test patterns, assertion libraries, or conventions that don't already exist in this project. 下面是 /testmatch src/services/prediction logger.py 为 logging service 生成测试的结果: No access 7cbPLWRnLTJf75xp 00:00 它一共生成了 19 个测试,分布在三个 classes 中,每个公共函数一组,而且第一次运行就全部通过。 这些测试和现有项目约定完全一致:同样的 conftest.py fixtures、同样的 db session 依赖注入、同样按 Test class 分组、内部用扁平 methods 的结构。 最有意思的是它还主动解决了一个隐蔽问题。service functions 会调用 db.commit(),因此 conftest.py 里正常的 session.rollback() teardown 根本无法回滚已经提交的行。 它因此加了一个 clean predictions 的 autouse fixture,在每个测试前删除所有 rows,强制保证隔离。 这种测试基础设施和应用代码之间的微妙耦合,通常需要开发者在 CI 里失败几轮后才会意识到。 Command 6: /explain func 在 review 和 testing 的过程中,你迟早会碰到那些逻辑很密、但实现原因完全没写下来的函数。 这个命令会生成 inline documentation,而且有一条很重要的规则:它解释的是 “why”,不是 “what”。 因为代码自己已经说明了它在做什么;评论应该负责解释它为什么要这样做。 这些注释应该把那些非显而易见的决策和未来维护者必须守住的 invariants 记录下来。 Code block Markdown Copy description: Generate why focused documentation for complex functions allowed tools: Read, Grep argument hint: <function name or file:line Document the function or code block at: $ARGUMENTS Rules for documentation style Explain WHY, not WHAT. The code shows what it does. Comments explain why it does it that way. Document non obvious decisions: "We use a Map instead of an object here because keys can be symbols" Document invariants: "This must be called after auth middleware has run" Document constraints: "Rate limited to 100 calls/min by the upstream API" Document gotchas: "Returns stale data if cache TTL hasn't expired, even after a write" DO NOT add comments that restate the code: "// increment counter" above counter++ Output format Add a JSDoc/docstring header with: purpose (one line), parameters with types, return value, throws/errors, and a brief example if the usage isn't obvious Add inline comments only where the code makes non obvious decisions Keep every comment under 100 characters per line Output the function with documentation added. Do not modify the logic. 下面是 /explain func src/preprocessing/pipeline.py 为 feature engineering functions 生成文档的效果: No access v5vNrwgJp0JYJDzC 00:00 这个命令为两个函数补上了文档。 对每个函数,它都解释了若干具体实现选择背后的原因:为什么要先去掉 URL 再处理标点(顺序反了会制造垃圾 token)、为什么 IDF 公式要在 log 外面再加一个 +1(避免把在所有文档中都出现的特征压成零)、为什么最后要做 L2 normalization(与训练好的模型保持 cosine distance 兼容)。 它还指出了这个文件里最大的正确性风险:TF IDF vocabulary 是根据当前 batch 建的,而不是根据训练语料建的,所以单文档推理得到的 IDF 值其实没有意义。 这种上下文对一个新加入团队的人来说,往往需要几周才能自己摸清。 Command 7: /refactor safe 到这一步,你已经 review 了代码、补了测试、也加了文档。 如果 /dissect 报出了结构性问题,比如一个 45 行的 handler 同时做 validation、inference、logging 和 response formatting,这时候就该用这个命令修它了。 用 AI 做重构的风险在于 Claude 很容易“顺手优化”掉你根本没让它碰的东西。 这个命令最重要的约束就是:public API 绝不能变。 它只允许你改内部结构。 Code block Markdown Copy description: Refactor internals without changing public API allowed tools: Read, Grep, Glob argument hint: <file or function Refactor the internals of: $ARGUMENTS Hard constraints DO NOT change any exported function signatures DO NOT change any return types or shapes DO NOT rename any exported symbols DO NOT change the module's public interface in any way DO NOT add new dependencies Preserve all existing behavior, including edge cases and error messages What to improve (internal only) Extract repeated logic into private helper functions Simplify nested conditionals (early returns, guard clauses) Remove dead code paths that can never execute Replace magic numbers/strings with named constants 下面是 /dissect src/routes/predict.py 审查 prediction endpoint 的效果: No access 1oPBcAo2A6Kuc06z 00:00 No access 1oPBcAo2A6Kuc06z 00:00 这次 review 把问题组织到了六个维度里,但最亮眼的是它抓到了一些普通 linter 根本抓不到的东西,比如: • 一个损坏的 API contract:model version 虽然出现在 request schema 中,但在两个 handlers 里都被悄悄忽略了 • 当模型没有加载时,接口返回的是 200 OK 加空数据;它本该返回 503 • 单条延迟被错误地记录成“总耗时的平均值”,而不是真正的单条测量值 它还交叉读了测试文件,并指出一个很关键的问题:现有测试居然把 “model not loaded 时返回 200” 这个错误行为本身写进了断言里。 最后的 “Top 3” 优先级列表也非常有价值,因为它直接给你一个适合单次 commit 的行动清单。 Command 5:/testmatch 上面的 review 已经指出了若干未覆盖的代码路径,这时候就轮到 /testmatch 了。 AI 生成测试的一大问题在于:它们几乎从来不会匹配你项目现有的测试风格。 断言库、命名风格、setup 模式,全都可能不一样。 这个命令会先读取你已有的测试,再生成“看起来像是你团队里某个人写出来”的新测试。 下面是 /testmatch src/services/prediction logger.py 为 logging service 生成测试的结果: No access 7cbPLWRnLTJf75xp 00:00 No access 7cbPLWRnLTJf75xp 00:00 它一共生成了 19 个测试,分布在三个 classes 中,每个公共函数一组,而且第一次运行就全部通过。 这些测试和现有项目约定完全一致:同样的 conftest.py fixtures、同样的 db session 依赖注入、同样按 Test class 分组、内部用扁平 methods 的结构。 最有意思的是它还主动解决了一个隐蔽问题。service functions 会调用 db.commit(),因此 conftest.py 里正常的 session.rollback() teardown 根本无法回滚已经提交的行。 它因此加了一个 clean predictions 的 autouse fixture,在每个测试前删除所有 rows,强制保证隔离。 这种测试基础设施和应用代码之间的微妙耦合,通常需要开发者在 CI 里失败几轮后才会意识到。 Command 6: /explain func 在 review 和 testing 的过程中,你迟早会碰到那些逻辑很密、但实现原因完全没写下来的函数。 这个命令会生成 inline documentation,而且有一条很重要的规则:它解释的是 “why”,不是 “what”。 因为代码自己已经说明了它在做什么;评论应该负责解释它为什么要这样做。 这些注释应该把那些非显而易见的决策和未来维护者必须守住的 invariants 记录下来。 下面是 /explain func src/preprocessing/pipeline.py 为 feature engineering functions 生成文档的效果: No access v5vNrwgJp0JYJDzC 00:00 No access v5vNrwgJp0JYJDzC 00:00 这个命令为两个函数补上了文档。 对每个函数,它都解释了若干具体实现选择背后的原因:为什么要先去掉 URL 再处理标点(顺序反了会制造垃圾 token)、为什么 IDF 公式要在 log 外面再加一个 +1(避免把在所有文档中都出现的特征压成零)、为什么最后要做 L2 normalization(与训练好的模型保持 cosine distance 兼容)。 它还指出了这个文件里最大的正确性风险:TF IDF vocabulary 是根据当前 batch 建的,而不是根据训练语料建的,所以单文档推理得到的 IDF 值其实没有意义。 这种上下文对一个新加入团队的人来说,往往需要几周才能自己摸清。 Command 7: /refactor safe 到这一步,你已经 review 了代码、补了测试、也加了文档。 如果 /dissect 报出了结构性问题,比如一个 45 行的 handler 同时做 validation、inference、logging 和 response formatting,这时候就该用这个命令修它了。 用 AI 做重构的风险在于 Claude 很容易“顺手优化”掉你根本没让它碰的东西。 这个命令最重要的约束就是:public API 绝不能变。 它只允许你改内部结构。 下面是 /debt scan 生成完整项目健康报告的效果: No access Vlf4F7wsyISBBjTs 00:00 No access Vlf4F7wsyISBBjTs 00:00 它在整个 codebase 中找出了 20 个问题,每个都有 severity、文件位置、问题描述和预计修复时间。 高优先级发现包括一些 linter 根本抓不到的东西,比如: • 用 assert 做输入校验,而 Python 在 O 下会直接把它静默禁用 • metrics service 里存在一个无上限 list,本质上就是内存泄漏 • model loading 中已经有文档记录的 race condition,但没有任何测试覆盖 最后 “Recommended Fix Order” 还会按投入产出比排出前五项,从“两分钟删掉 debugger”一路排到“45 分钟补测试覆盖”。 你甚至可以直接把每一条都原样转成 Jira ticket。 [Bonus] Command 11: /changelog 功能做完了,migration 也起草好了。 现在你需要 release notes。 手写 changelog 很无聊,而直接从 commit messages 自动生成出来的 changelog 又通常完全没法看。 这个命令位于两者中间:它会读取最近的 commits,再逐个检查 diff 以理解“实际发生了什么改动”,然后产出一份人类可读、可编辑后发布的 changelog。 下面是 /changelog 从项目提交历史中生成 release notes 的效果: No access J8s73Q4ibuJpNQ7P 00:00 No access J8s73Q4ibuJpNQ7P 00:00 它读了 11 个 commits,并逐个检查 diff 以理解“实际改了什么”,而不是照抄 commit message,然后把结果分进了 Added、Fixed 和 Infrastructure 这些类别里。 每个条目都描述的是 用户能感知到的影响,而不是代码改动本身。比如它会写 “Single prediction endpoint with request logging”,而不是 “add predict route and logger service”。 它还把 commit hashes 一并带上了,因此你可以随时回溯到具体 diff。 最后 summary 会把这些 commits 串成一条叙事链,说明目前到底已经做成了什么、还有哪些在进行中。 开始你的第一个命令 配置你的第一个 command,只需要三步: 1. 在项目根目录创建目录:mkdir p .claude/commands 2. 创建一个带 prompt 的 markdown 文件:echo "Review the staged changes and suggest improvements.\n\n!\git diff cached\ 3. 在 Claude Code 中运行它:/review 对于那些你希望跨所有项目复用的 commands(比如 orient 或 preflight),把它们放到 /.claude/commands/ 里,然后用 /command name 调用。 另外,这篇文章中的 commands 是有意带着强烈主观偏好的。它们编码进去了特定的 code review priorities、test patterns、commit hygiene 和 documentation style。你完全可以 fork 它们,再根据自己的 use cases 做调整。 但真正的价值不在于这些 prompts 的字面内容,而在于这套模式本身:找出那些你反复重打的指令,把它们保存成文件,并不断迭代 prompt,直到输出稳定地接近你手工完成时的效果。 还有一点要注意:Anthropic 后来已经引入了 .claude/skills/ 作为新 command 的推荐目录。Skills 支持更多能力,比如打包附属文件、自动触发(Claude 识别到相关任务时会自动加载这个 skill),以及 subagent 执行。 这篇文章里使用的 .claude/commands/ 方式依然可用,而且作为起步方案会更简单。 👉 轮到你了:你现在在 Claude Code 里反复输入、但其实早该被做成 custom command 的 prompts,到底有哪些? That's a wrap! 如果你喜欢这篇教程: Find me →@ avichawla @ avichawla 我每天都会分享关于 DS、ML、LLMs 和 RAG 的教程与洞察。 原帖链接:https://x.com/ avichawla/status/2042929462908719352 原帖链接:https://x.com/ avichawla/status/2042929462908719352 在终端里设置 shell aliases 已经自然到几乎成了每个开发者的肌肉记忆。某个命令只要你用得足够频繁,你就会给它起个 alias。 但在 Claude Code prompts 这件事上,开发者通常会完全跳过这一步,然后一遍又一遍地凭记忆重打同样的 10 15 行指令,比如他们的代码审查清单、测试生成约束、pre commit 扫描……而且一个 session 接一个 session 地重复。 真正的成本不只是你作为开发者不断重复输入,更在于 prompt drift。 每次你凭记忆重打一段 prompt,措辞都会轻微变化。比如你可能漏掉某个约束,或者用不同方式描述预期输出格式。 对于 shell commands 来说这无所谓,因为它们是确定性的;但对于 LLM 来说,措辞稍有不同,就可能产出明显不同的结果。 Claude Code 的 custom commands 同时解决了这两个问题。 你只需要把一个 markdown 文件保存在 .claude/commands/ 里,它就会变成一个 slash command。之后每次调用,Claude 都会收到完全一致的指令。 这些 prompts 通过 Git 做版本控制,所以整个团队跑的是同样的 commands;一旦有人优化了 prompt,其他人下次 pull 后就都能获得更新。 这正是 Boris Cherny 在他关于 Claude Code workflows 的线程里描述的模式:凡是会重复发生的 workflow,他都会把它变成一个 command,检入 Git,并与团队共享: 我们先走一遍它们的配置方式,然后再看这 10 个在我工作流里最有用的 commands。我会在一个真实的 ML inference service(FastAPI、scikit learn、Alembic)上演示每一个命令,这样你能看到实际输出,而且我会把完整 prompt templates 一并给你,你可以直接放进自己的项目里。 自定义命令是什么 一个 custom command,本质上就是 .claude/commands/ 目录里的一个 markdown 文件。文件名就是命令名。 文件内容就是当你运行这个 command 时发给 Claude 的 prompt。你可以使用 $ARGUMENTS 作为占位符,承接命令名后面输入的任何内容。 例如,运行 "/dissect src/auth/session.ts" 时,$ARGUMENTS 会被替换成 "src/auth/session.ts"。 你还可以用 shell commands 动态注入上下文,方法是使用 !\command\`` 语法: Claude 会在处理 prompt 之前先执行这些 shell commands,因此上下文始终是最新的。 最后,你还可以在文件顶部加一个可选的 YAML frontmatter,用来预先批准工具权限(这样 Claude 就不会每次调用 git 都重新问你)、设置模型覆盖项,或者添加说明: 整个系统就这些:一个 markdown 文件、一个可选 YAML 头部,以及 $ARGUMENTS 用来接收动态输入。 下面我会分享 10 个我在实际工作中最有用的命令。 Command 1:/env check 当你 clone 一个项目,或者隔了几周重新回到一个项目,第一件事就是确认你的本地环境到底能不能跑起来。可能 runtime 版本不对、环境变量缺失、migrations 没有应用。 这个命令会一次性校验整个本地开发环境。 下面是 /env check 在这个 ML inference service 上运行出来的效果: No access OiVyoBEl52aFhk 2 00:00 No access OiVyoBEl52aFhk 2 00:00 这个命令一次就抓出了五类问题,包括 Python 3.12 与 3.11 的版本