Claude Code 折腾了一阵子,我一直觉得这工具好用是好用,但每次输入命令都得憋英文,还要在脑子里过一遍 Prompt 模板,有点累。后来干脆花了两个周末,把日常最常用的操作全部封装成了带中文提示的 Slash Command,一共 10 个,做成了一个可以直接拷到项目里用的工作流包。这文章不是讲概念,就是把这 10 个命令的设计思路、配置文件写法、踩过的坑完整摊开,给同样在用 Claude Code 写代码、做 Code Review、理项目的人一个能直接抄作业的参考。
先说清楚这套东西解决什么问题:很多人把 Claude Code 当成一个高级聊天框来用,问一句答一句,完全没有发挥出它真正的优势。它其实支持自定义命令,可以把复杂的 Prompt、固定的处理流程、甚至本地脚本全部打包成一个短命令,输入/修复就能触发一整套 Bug 分析流程,而不是每次手动敲一大段话。10 个中文命令做完后,我的日常协作流程变成了三步:写完代码敲/审查,开会前敲/周报,接手老项目敲/导读。效率提升是实打实的,更关键的是这套做法让没有提示词经验的同事也能轻松上手。
1. 整体设计:为什么要把命令做成中文 Slash 命令
1.1 Claude Code 的原生命令机制
这一节先介绍背景知识,用过的朋友可以跳过。Claude Code 支持自定义 Slash Command,命令文件放在项目根目录的.claude/commands/下,每个命令由markdown提示词文件和可选的TypeScript脚本文件组成。你在对话框输入/某某时,Claude Code 会自动读取对应的 Markdown 内容,把其中的参数替换成你实际输入的值,然后作为系统提示词的一部分发给大模型。
这套机制比我一开始以为的“预置 Prompt 模板”要强得多。Markdown 文件只是静态文本,真正让它活起来的是旁边的.ts脚本文件。脚本可以读取当前项目的文件状态、Git 暂存区内容、甚至执行终端命令,把结果拼接到提示词里再发给模型。这意味着我可以在命令里写“请分析以下 Git Diff”,然后脚本自动把git diff --cached的输出塞进去。
原生机制里还有几个细节值得注意。命令文件区分全局和项目级:全局命令放在~/.claude/commands/,所有项目可用;项目级放在项目根目录,适合和团队共享。命令参数通过$ARGUMENTS传递,文件名中的数字会作为参数编号。这些细节在后面配置时会反复用到。
1.2 选择中文命名的三个决定性理由
第一个理由是团队协作门槛。我们小组六个人,真正写过 Prompt 的不到一半,大部分同事对 AI 工具的态度是“能用但不想折腾”。如果我给他们分享的是一堆英文 Prompt 模板,基本等于没分享。但如果是/审查、/周报这样的中文命令,只要看一眼列表就能猜到功能,用一次就能记住。这个差别在团队落地时是决定性的。
第二个理由是记忆成本。我知道很多人觉得英文命令更“正统”,但作为一天要敲几十次命令的人来说,记忆负荷是真实存在的。尤其在上下文切换频繁的时候,脑子里要同时装业务逻辑和命令语法,很容易卡壳。中文命令天然符合我的思维习惯。更重要的是,Claude Code 的模型本身对中文理解力很强,命令名用什么语言对它来说没有区别,但这降低了我的工作记忆负担。
第三个理由是语义完整性。英文 Slash Command 往往受限于单词长度,比如/review、/fix、/log,这些缩写能表达功能但不表达场景。中文命令可以用“审查代码”“梳理日志”“生成周报”这样的动宾结构,信息密度更高。当一个命令包含多个操作步骤时,中文命名能把整个流程的目的直接表达出来,这比一个含糊的英文单词要清楚得多。
1.3 十个命令的全景地图
我最终保留了 10 个命令,按照使用频率和场景分成四类。先给你一张全景表,后面每一类再展开讲。
| 命令名称 | 触发方式 | 核心功能 | 适用场景 |
|---|---|---|---|
| 代码审查 | /审查 [范围] | 检查本地修改或指定文件,输出代码问题清单 | 提交前自检、MR 前预审 |
| 缺陷定位 | /定位 [现象] | 根据错误信息或现象描述,定位代码中可能的问题点 | 线上 Bug 排查、报错处理 |
| 提交信息 | /提交 [描述] | 生成符合 Conventional Commits 规范的提交说明 | Git 提交前 |
| 提交记录 | /历史 [范围] | 分析 Git 提交历史,输出提交规律与问题总结 | 版本回顾、绩效总结 |
| 差异解读 | /变更 [文件] | 解释工作区与暂存区的代码改动意图 | Code Review 辅助 |
| 重构规划 | /重构 [目标] | 输出重构方案,包含步骤拆解、风险影响、验证方案 | 技术债清理 |
| 文档生成 | /文档 [模块] | 为目标代码模块生成 README 与接口说明 | 新模块交付、交接 |
| 项目导读 | /导读 | 通读项目结构,输出架构说明与新手指南 | 新人接手、快速上手 |
| 周报助手 | /周报 | 分析本周提交记录,生成工作总结 | 周报撰写 |
| 学习助手 | /教学 [主题] | 解释项目中的特定技术概念,附带项目内实例 | 技术学习、新人培训 |
这张表里,前四个是高频使用的“主力命令”,几乎每天都会碰;中间三个是“低频高价值命令”,虽然用得少但每次都能省半小时以上;最后三个是“团队协作命令”,主要给非核心开发人员用。
2. 核心实现:三个高频命令的逐行拆解
2.1 代码审查命令的完整实现
代码审查命令是我最早实现的一个,也是迭代次数最多的。它的核心思路是:让 Claude Code 扮演资深 Reviewer 的角色,对指定范围的代码进行审查,输出问题清单而非泛泛而谈。
先看目录结构,这是标准做法:
.claude/commands/ ├── 审查.md ├── 审查.ts ├── 定位.md ├── 定位.ts └── ...审查.md的内容如下:
你是一名拥有 15 年经验的资深代码审查专家,擅长发现潜在 Bug、安全隐患和性能瓶颈。 请审查以下范围内的代码变更,重点关注: 1. 逻辑错误与边界条件(空值、并发、溢出等) 2. 安全隐患(注入、敏感信息泄露、越权访问) 3. 性能问题(不必要的大对象创建、循环内查询、N+1 问题) 4. 代码风格与可维护性(命名、重复代码、魔法数字) 5. API 设计的合理性(参数校验、返回值定义) 输出格式: - 按严重程度分为【阻断级】【建议级】【优化级】 - 每个问题需要给出:文件路径、行号(如可定位)、问题描述、修改建议 - 如果审查范围内没有问题,请明确说明,不要为了凑数而输出无意义建议 审查范围:$ARGUMENTS这里的核心是$ARGUMENTS变量。用户在输入/审查 全部时,这个变量会被替换成“全部”;输入/审查 src/utils.ts时,会被替换成文件路径。但标记文件里不能执行任何代码,真正去拉取 Git Diff 的工作要由 TypeScript 脚本来做。
审查.ts的核心逻辑如下:
import * as cp from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; function getGitDiff(scope: string): string { // git diff 是核心数据源,只审查未提交的改动 const args = scope === '全部' ? ['diff', '--cached'] : ['diff', '--cached', '--', scope]; const output = cp.execSync(`git ${args.join(' ')}`, { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 // 大项目 diff 很容易超默认 buffer }); return output; } function truncate(text: string, maxLen: number = 12000): string { // 超过上下文窗口的直接舍弃中间部分,保留开头和结尾 if (text.length <= maxLen) return text; const half = Math.floor(maxLen / 2); return text.slice(0, half) + '\n\n...[中间内容已省略]...\n\n' + text.slice(-half); } export async function main(args: string[]): Promise<string> { const scope = args.join(' ') || '全部'; // 也要包含暂存区状态以外的上下文信息 const branch = cp.execSync('git branch --show-current', { encoding: 'utf-8' }).trim(); const lastCommit = cp.execSync('git log -1 --oneline', { encoding: 'utf-8' }).trim(); const diff = getGitDiff(scope); return `当前分支:${branch} 最近提交:${lastCommit} 审查范围:${scope} ${truncate(diff)}`; }这个脚本做的事情非常简单:把 Git Diff 抓取出来,加上当前分支名和最近提交信息,一并交给 Claude。关键点在于truncate函数,这是我在实践中发现的硬性需求。没有它时,遇到大型项目的一次提交动辄几万字符的 Diff,Claude 的上下文窗口会被大量无关代码刷屏,导致真正重要的逻辑反而不被关注。截断后虽然丢失了中间细节,但模型能集中精力处理改动上下文的关键部分,效果反而更稳定。
还有个细节我要特别提示:git diff --cached只审查暂存区的改动,不审查工作区未暂存的部分。这种设计是有意的,因为暂存区内容往往是提交意图较明确的代码。但我后来发现很多人用命令时不习惯先git add,所以我在审查.ts里做了逻辑调整:如果暂存区为空,就自动改为对比工作区和 HEAD。这个适应性逻辑极大减少了误操作率。
2.2 缺陷定位命令:把问题描述转换为代码路径
缺陷定位命令解决的是最让人头疼的排查环节:线上报了一个错,错误信息很抽象,只知道大概发生在哪个模块,但要找到具体代码位置往往要翻半天日志。这条命令的设计思路是“现象输入,路径输出”。
定位.md的内容:
你是一个资深 Debug 专家。根据用户描述的错误现象,结合项目代码结构,进行以下分析: 1. 根据异常信息的关键词,推测可能出错的函数调用链路 2. 在项目代码中搜索与错误相关的函数、变量、异常类 3. 根据调用关系判断最可能的出错位置 4. 给出 2-3 个可疑点,每个可疑点包含:文件路径、函数名、行号(如可定位)、出错概率、排查建议 注意: - 如果错误信息中包含堆栈片段,优先从堆栈线索入手 - 不要给无关的全局建议,一定要定位到具体文件和函数 - 如果无法定位,列出你搜索过哪些关键词和文件,帮助用户进一步提供信息 错误现象:$ARGUMENTS定位.ts的实现逻辑就更复杂一些,因为要主动搜索代码内容:
import * as cp from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; const IGNORE_DIRS = ['node_modules', 'dist', 'build', '.git', 'vendor', '__pycache__']; function searchInFiles(needle: string): string[] { // 这里有两个搜索策略:文件名匹配 和 内容匹配 const results: string[] = []; const needleLower = needle.toLowerCase(); // 策略一:在文件内容里搜关键词,用 ripgrep 效率高很多 try { const rgOutput = cp.execSync(`rg -l -i "${needle}" --type-add 'web:*.{ts,tsx,js,jsx,vue,py,java,go}' -t web . 2>/dev/null | head -30`, { encoding: 'utf-8', maxBuffer: 5 * 1024 * 1024 }); results.push(...rgOutput.trim().split('\n').filter(Boolean)); } catch { // ripgrep 没装或没有匹配都会走到这里 } // 策略二:按文件名匹配 const files = walkSync('./src', 4); // 限制深度,避免遍历整个 node_modules for (const file of files) { const base = path.basename(file); if (base.includes(needle) || needleLower.includes(base.replace(/\.[^.]+$/, '').toLowerCase())) { results.push(file); } } return [...new Set(results)]; } function walkSync(dir: string, maxDepth: number): string[] { // 一个简单的递归遍历函数,再加个深度限制防止爆掉 if (maxDepth <= 0) return []; const files: string[] = []; if (!fs.existsSync(dir)) return files; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (IGNORE_DIRS.includes(entry.name)) continue; if (entry.isDirectory()) { files.push(...walkSync(full, maxDepth - 1)); } else if (entry.isFile()) { files.push(full); } } return files; } export async function main(args: string[]): Promise<string> { const description = args.join(' ') || '未提供错误现象'; const searchTerms = description .split(/\s+/) .filter(term => term.length > 1) .slice(0, 5); // 最多取5个关键词,不然搜索范围太大 const foundedFiles: string[] = []; for (const term of searchTerms) { foundedFiles.push(...searchInFiles(term)); } const uniqueFiles = [...new Set(foundedFiles)].slice(0, 30); // 读几个候选文件的头部,给模型一些结构线索 const fileSnapshots = uniqueFiles.slice(0, 5).map(file => { try { const content = fs.readFileSync(file, 'utf-8').slice(0, 1500); return `### ${file}\n${content}`; } catch { return ''; } }).join('\n\n'); return `错误现象:${description} 在项目中找到以下可能相关的文件: ${uniqueFiles.length > 0 ? uniqueFiles.join('\n') : '未找到匹配文件,请检查关键词或扩大搜索范围。'} 其中部分文件的内容预览如下: ${fileSnapshots || '无可用预览'} `; }这里我用了一个组合搜索策略:先用ripgrep搜内容匹配,再用路径遍历做文件名匹配。为什么要两套方案?因为错误信息里的关键词经常不是文件名,而是异常类名、接口名、或者中文字段名。rg搜内容能覆盖这类情况,但不一定每个环境都装了 ripgrep,而且大目录全量搜索很慢。文件名的匹配虽然覆盖率低,但执行速度快,两者互补。
另外一个值得一提的取舍是walkSync的深度限制。如果项目采用平铺结构,深度 1-2 就能找到;如果项目嵌套深,4 层是合理上限。再深基本都是业务代码的分包目录,对定位帮助不大,还会因遍历过慢影响命令响应速度。这些细节看着琐碎,实际用起来区别很大。
2.3 提交信息命令:让 Git 提交从憋文案变成填空
这条命令做的是最基础但最烦人的事。很多人提交代码时提交信息随便写个"fix bug"或"update",团队看历史记录时一头雾水。这条命令用 Claude 理解 Diff 内容,自动生成规范提交信息。
提交.md:
根据代码变更内容,生成符合 Conventional Commits 规范的提交信息。 要求: 1. type 限用:feat / fix / refactor / docs / chore / perf / test 这七种 2. 简要描述中英文混合,中文为主体,动词开头,不超过 20 个汉字 3. 在提交信息中说明修改的核心文件和影响函数 4. 如果有破坏性变更,需要在正文中用 `BREAKING CHANGE:` 标记 5. 最终输出只保留提交信息原文,不要增加任何解释你的思路的内容 变更描述(如为空则自动分析): $ARGUMENTS提交.ts的主要逻辑:
import * as cp from 'child_process'; export async function main(args: string[]): Promise<string> { const userDescription = args.join(' '); // 这里做的是"增强版 diff 摘要",比把完整 diff 直接扔给模型效果更好 let diff = ''; try { diff = cp.execSync('git diff HEAD --stat', { encoding: 'utf-8' }).trim(); // 加上实际文件变更比率的参数据,让模型更好判断本次修改的规模 const diffSummary = cp.execSync('git diff HEAD --dirstat=files,0', { encoding: 'utf-8' }).trim(); diff += '\n\n目录变更统计:\n' + diffSummary; } catch { diff = '无 Git 信息'; } return `用户描述:${userDescription || '(未提供,请直接从 Diff 中分析)'} ## 本次变更统计 ${diff} ## 请基于以上信息生成提交信息。`; }这里没有把整个 Diff 交给模型,只给了--stat的统计即文件和行数变化。这么做省 token 而且效果不差。模型根据文件变更列表加上用户的一句话描述,已经足够产出合理的提交类型判断。把整个 Diff 塞进去反而会产生噪音,比如模型会盯着某些具体实现细节,反而忽视了整体变更意图。
产出提交信息后,用户可以直接复制使用,也可以跟我给的模板对比调整。这个命令看着简单,但它的实际效果非常稳定,因为提交信息生成是一个极度适合 LLM 的任务——不需要深度推理,只需要概括归纳。
3. 配置与安装:从零搭建完整的命令工作流包
3.1 配置文件目录结构与全局命令安装
这套工作流包的核心文件全部放在.claude/commands/下。如果只是想自己用,可以放到全局目录~/.claude/commands/,这样所有项目都能共用。如果是要给团队共享,建议提交到仓库里,放在项目根目录下,配合团队的.claude/settings.json配置文件一起使用。
团队的共享场景里还要注意一点:很多人会直接在项目里修改.claude下的文件,导致团队命令版本不一致。我建议命令文件尽量放在独立的私有目录维护,通过构建脚本部署到项目里,或者直接以文件方式共享,让每个人自己安装。这个选择虽然多了一步操作,但避免了“我在你机器上改了命令,你机器上是旧的,而且完全不知道差异在哪”的尴尬局面。
配置文件这块,一个常见需求是设置命令权限。Claude Code 默认在执行脚本类命令时会弹出确认框,有些团队希望静默执行。这时可以在.claude/settings.json中配置权限:
{ "permissions": { "allow": [ "Bash(git diff:*)", "Bash(git log:*)", "Bash(rg:*)", "Read(*)" ], "deny": [ "Bash(git push:*)", "Bash(git reset:*)", "Bash(rm:*)" ] } }这个配置的意思是:允许读取文件、查看 Git Diff 和日志、搜索代码;禁止推送、硬重置和删除操作。我强烈建议任何团队都做一层这样的限制,因为 Claude Code 为了完成“分析任务”可能需要读文件,但完全没有理由执行推送或删除命令。权限配置不花一分钟,但能挡住很多误操作。
3.2 命令的运行机制:Markdown 与 TypeScript 的分工边界
这是理解 Claude Code 的自定义命令最核心的一点:md文件与ts文件的职责边界。我从多次迭代中总结的经验是:
Markdown 文件的职责是定义模型的角色、任务和约束。它所有的文字都会传给 Claude,作为系统提示词的一部分。要注意的是这个文件里不能直接执行任何命令,它的作用是"告诉模型要做什么"。
TypeScript 文件的职责是提供数据、执行系统操作。它会在 Claude 开始处理之前执行,产生的返回值会作为一个特殊消息注入到上下文中。主函数通常接受args(string[])作为参数,这个参数就是用户在命令后输入的内容。
两者之间的配合逻辑是这样的:在/审查命令里,审查.md描述代码审查专家的行为和输出格式,而审查.ts抓取 Git Diff 的实际数据,把数据加进上下文中。模型拿到数据和任务指令后,输出最终的审查结果。没有.ts文件的命令也可以正常运行,$ARGUMENTS会被用户输入替换,但无法动态抓取项目状态。
关于 TypeScript 文件的几个实操要点:
ts文件的入口函数必须是main(args: string[]): Promise<string>,返回值会被拼接到上下文中。ts文件通过 Node.js 执行,所有 Node 内置模块都能直接用。- 文件内不要写 console.log,输出结果应通过返回值传递。
- 命令执行环境是项目根目录,所以相对路径不会出错。
- 脚本异常时命令会失败,但不会中断 Claude Code 主进程。
这些约定最初我花了不少时间摸索,因为官方文档并不会明确告诉你返回值如何连接提示词。实践中试错几轮后,我总结成上面这几条,基本涵盖了 90% 的场景。
3.3 与 Visual Studio Code 的联动配置
我在日常开发中用 Visual Studio Code 自带的终端来跑 Claude Code,这个组合体验不错。关键要在 VS Code 的集成终端里允许 Claude Code 使用快捷命令,以及配置好终端会话的保持。
具体的配置方式是在 VS Code 的settings.json里设置:
{ "terminal.integrated.env.windows": { "CLAUDE_CODE_OPTS": "--dangerously-skip-permissions" } }注意这里--dangerously-skip-permissions是跳过权限确认,适合个人开发环境使用。如果团队协作,建议不要开这个选项,而是在settings.json里精确配置允许列表,前面说的权限配置就是这个用途。
另外,我习惯把 Claude Code 单独放到一个终端标签页,并给它设置一个独立的配色,避免跟其他终端输出混在一起。VS Code 的终端界面支持多标签,在terminal.integrated.tabs里可以把 Claude Code 的会话固定住,这样随时敲命令都不用找。
3.4 一个完整的命令部署流程示例
假设你要把整套工作流包部署到一个新成员电脑上,最稳妥的手动流程是这样的:
- 先安装 Claude Code:
npm install -g @anthropic-ai/claude-code - 克隆项目到本地,执行
claude初始化 - 复制命令目录:把
.claude/commands/整个文件夹放到项目根目录,注意不要覆盖别人已经改过的配置 - 检查
settings.json权限配置,确保Bash(git diff:*)等允许规则在里面 - 在项目目录运行
claude,输入/查看命令列表是否出现中文命令 - 先跑一遍
/文档 当前目录做一个冒烟测试,确认 TypeScript 脚本能正常执行
这个流程我已经给组里新人走过三轮,基本上没有盲点。
4. 实操过程与核心环节实现
4.1 一次完整的代码审查实战记录
为了让你对这套工作流包有更直观的感受,我记录一次真实的/审查操作过程。那天的场景是:一个变更涉及用户登录模块,修改了验证码校验逻辑和 Token 刷新机制。
我在终端输入:
/审查命令执行后,终端会把审查.ts抓取到的 Git Diff 与审查.md的命令文本合并作为上下文,模型开始分析。大约 10 秒后输出了一份报告,其中有一条我印象很深:
【阻断级】
verifyCode.ts第 89 行:验证码校验失败时直接抛出异常导致整个登录请求回滚,但在验证码校验之前已经被查询的验证码记录、尝试次数等信息处于未清理状态,极端并发场景下可能导致验证码记录泄漏。
这条我确实没想到。原代码里验证码校验失败就立刻抛出业务异常,框架层会做事务回滚,但那张记录验证码的表因为事务隔离级别的问题,在特定数据库配置下并不会完全回滚。这种场景靠人肉一眼看出很难,但 LLM 结合了代码上下文之后真的能找到这种跨模块的隐蔽问题。
模型还正确识别了一个潜在安全风险——在重置 Token 之前没有校验旧 Token 是否已经过期,给重放攻击留了窗口。这两条建议都直接提进了 MR 里,同事看到后立刻调整了逻辑。自从团队开始用/审查,大家可以明显感受到提交前的隐患变少了。
4.2 缺陷定位命令的高效排查实例
有一次后台报了个杂音错误,日志里反复出现JSON parse error: Unexpected token,但是没有明确堆栈。我直接敲了/定位 JSON parse error 日志上传。
命令脚本把这三个关键词并行搜索了一遍。结果性能非常明显,因为我的日志上传模块里有一段手写的 JSON 序列化逻辑,它拼 SQL 的时候不小心在字符串数组里留下了尾逗号,PHP 那边解析到数组最后一个位置时直接挂了。如果没有这套命令,靠手动打开项目反复搜索关键词,至少要到 5-10 分钟甚至更久。一个命令下去,3 秒就列出 6 个可疑文件,我打开第一个就找到了问题。
这里有个使用场景要提示:命令的效果跟错误描述的信息量强相关。如果只知道"报错了",模型也只能瞎猜。我总结了一句口诀:报错信息要给出【异常类型 + 关键词 + 大概功能模块】,准确率翻倍。比如上面的JSON parse error 日志上传,就包含了这三类信息。
4.3 周报助手命令的团队落地效果
这个命令是我意料之外好评最多的一个。起因是我发现每个周五写周报都要打开 Git 记录整理提交信息,步骤繁杂。后来我写了/周报命令,脚本自动统计当前用户本周的提交记录,按日期分组,输出每个提交的标题、影响文件、关联的 MR 号。模型再将这些内容整理成周报格式。
周报.ts的核心逻辑:
import * as cp from 'child_process'; export async function main(args: string[]): Promise<string> { // 默认统计本周一到今天 const monday = new Date(); const day = monday.getDay(); const diff = day === 0 ? 6 : day - 1; monday.setDate(monday.getDate() - diff); monday.setHours(0, 0, 0, 0); const since = args[0] || monday.toISOString().slice(0, 10); // git log 按作者 + 时间过滤 const author = cp.execSync('git config user.name', { encoding: 'utf-8' }).trim(); const log = cp.execSync( `git log --author="${author}" --since="${since} 00:00:00" --until="now" --pretty=format:"%h %ad %s" --date=format:"%Y-%m-%d %H:%M"`, { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 } ).trim(); // 统计每个文件的变更行数, 给周报提供更具体的数据 const stat = cp.execSync( `git log --author="${author}" --since="${since} 00:00:00" --numstat --pretty=format:"%h" | awk '/^[0-9]/ {added+=$1; deleted+=$2} END {print added, deleted}'`, { encoding: 'utf-8', maxBuffer: 5 * 1024 * 1024 } ).trim(); return `本周起始日期:${since} 提交记录: ${log} 变更统计(新增行数 删除行数):${stat} 请把以上内容整理成周报,包含: 1. 本周重点工作方向归纳 2. 按功能模块整理的具体事项 3. 需要关注的风险或遗留问题 4. 下周计划建议 5. 不要包含代码细节,用面向管理者的语言`; }这个脚本用git config user.name自动识别当前用户,不用手动填名字。模型拿到的提交记录已经过滤到个人,这样生成的周报内容准确度很高。需要注意的是如果团队里大家共用 Git 账号,这个命令的准确性就会打折扣,需要改成按邮箱或 ID 过滤。
4.4 项目导读命令:让新人快速上手老项目
最后一个我重点讲讲/导读命令。接手过老项目的人应该深有体会:一个新仓库,除了 README 里那几句话,什么引导都没有。AI 编程工具的作用在这里尤为突出——它可以快速消化数百个文件。
导读.ts脚本会做以下事:
import * as cp from 'child_process'; export async function main(args: string[]): Promise<string> { const topDir = args[0] || './src'; // 默认看 src 目录 // 先拿目录树 const tree = cp.execSync(`find ${topDir} -maxdepth 3 -type f | head -100`, { encoding: 'utf-8' }); // 关键入口文件的读取策略: // 1. package.json 或 go.mod 看依赖 // 2. 入口文件常叫 main / index / app,优先看 // 3. 配置文件如 .env.example 提供环境变量线索 const entryFiles = ['package.json', 'go.mod', 'main.ts', 'main.go', 'index.ts', 'app.py', '.env.example'] .filter(f => { try { return require('fs').existsSync(f); } catch { return false; } }) .map(f => `### ${f}\n${require('fs').readFileSync(f, 'utf-8').slice(0, 1000)}`) .join('\n\n'); return `项目目录树(前三层): ${tree} 关键配置文件与入口文件内容: ${entryFiles} 请根据以上信息输出: 1. 项目的技术栈与架构模式 2. 核心领域模型(结合文件名推测) 3. 请求/事件的处理流程概述 4. 常见修改场景的切入点说明(比如新增接口、改数据库字段、加定时任务) 5. 针对新人的上手步骤建议`; }这个命令的核心价值在于,把"人肉通读项目"的过程压缩为一次对话。模型会依据目录结构和核心配置推断出项目的设计意图。比如看到src/controllers/、src/services/、src/models/这样的目录,就能判断这是一个典型 MVC 分层结构;看到go.mod里的依赖,就能判断项目是否用了特定的 Web 框架、ORM 和消息队列。对新人来说,这份“导读”比让资深同事讲半小时更具体。对有经验的开发者来说,它的价值是快速判断一个项目值不值得深入。
5. 常见问题与排查技巧实录
5.1 命令不生效或列表不显示
最常遇到的坑是:文件放进.claude/commands/了,但输入/看不到命令。这个问题的排查路径一般是:
- 看命令文件命名。Claude Code 要求命令文件名不能包含空格和中划线。中文文件名可以用,但中间不能有特殊字符。文件名的数字会作为参数编号。比如
审查_1.md这样的名字不合法,改成审查1.md就正常。 - 检查目录位置。命令文件必须在
.claude/commands/下,不能放在子目录里。子目录虽然能放,但不会出现在命令列表中。 - 重启 Claude Code 会话。老版本的 Claude Code 不会热加载新命令文件,必须重启会话才能识别。
提示:如果你用 VS Code 集成终端跑 Claude Code,重启会话不一定要重启 VS Code,只要退出
claude重新敲一遍即可。
5.2 TypeScript 脚本执行报错
脚本执行失败时,错误信息会直接显示在终端,通常是 Node.js 的堆栈。最常见的几类问题:
Cannot find module 'child_process':理论上内置模块都存在,但如果你在.ts文件顶部写了import ... from语法,必须确保环境支持 TypeScript 编译。Claude Code 内部会自动转译,但有时会因为项目里有自己的 tsconfig 产生冲突。稳妥做法是在ts文件里用require而非import。Standard output is empty:这是典型的返回值问题。如果你在 main 函数里没有返回字符串,或者返回 undefined,脚本就会报这个错。检查一下 main 函数的写法,确保所有路径都有返回值。Maximum buffer exceeded:抓取超大文件或超长 Diff 时常见。通过maxBuffer参数调大缓冲区即可,但不要无脑调大,建议根据项目规模在 5MB 到 20MB 之间设置。- 脚本有语法错误时,错误提示有时不明显,只会提示执行失败。这时可以把
.ts临时改成.js文件,用 Node 直接跑一遍看具体报错,定位后再改回来。
5.3 上下文窗口被无效内容塞满
命令脚本返回的内容会占用上下文空间,如果脚本太“贪婪”,把大量无关代码塞给模型,后面的对话质量会直线下降。这是我踩过最深的坑。
典型场景是/审查命令,当时我把完整 Diff 直接传给模型,结果有一次的 Diff 有 30000 多行,导致后续的对话里模型总是把旧代码遗忘,还出现幻觉。用截断策略后,效果稳定很多。经验数据可以参考:
| Diff 行数范围 | 截断策略 |
|---|---|
| 0-500 行 | 完整保留,不截断 |
| 500-2000 行 | 保留前后各 40%,中间摘要 |
| 2000 行以上 | 只保留统计和关键文件列表 |
5.4 命令执行的权限确认弹窗干扰
Claude Code 默认对脚本执行有权限确认机制,如果你调的命令涉及执行git或读文件,每个操作都会弹窗确认。这在实际使用中很烦人,尤其是命令脚本里有两三个execSync调用时,会连续弹窗好多次。
解决方式就是前面说的,在.claude/settings.json里配置allow列表。把命令所需的读类操作全部加进去。注意Bash(git diff:*)和Bash(git log:*)这类规则要精确,不要图省事写Bash(*),否则等于完全放弃权限控制。
5.5 不同系统和 Windows 环境的兼容性差异
我日常主要用 macOS 或 Linux,但热词列表里很多人关心 Windows 配置。Claude Code 在 Windows 下确实有兼容面问题,但也不是不能解决。关键差异点:
- Windows 下执行
git diff的路径分隔符不同,脚本里建议用path.join或path.resolve统一处理,而不是硬编码/分隔。 - 默认命令解释器不同,Windows 默认用
cmd.exe,有时sed、awk这类命令不可用。如果脚本里用到这些命令,先设置SHELL环境变量或者改用纯 node 实现。 - 中文路径文件名在 Windows 下有编码差异,搜索时注意用
utf-8编码规则。 - 建议在 Windows 上不要完全跳过权限确认,因为某些安全策略的差异会让跳过权限更容易出问题。
这一点对不同系统的兼容性,我特意让我一个 Windows 环境的同事跑过一遍全部命令,修改了脚本中涉及find、awk的管道逻辑,用相对简单的方式重写后,Windows 下也能稳定运行。
5.6 命令使用的频率控制与疲劳问题
这套工作流包有个隐藏问题:命令太方便了,会让人产生路径依赖。我有段时间甚至懒得自己看代码,遇到什么先敲一遍命令再说,结果越用越依赖,自己的代码理解能力反而退化了。
感受最深的是在排查一个线上问题时,Claude 给出了看似合理的定位,但验证时发现它推测的调用链是错的。那次之后我给自己定了一个规矩:/审查的结果只作为辅助参考,关键改动必须自己读一遍 Diff 和核心函数。AI 编程工具是放大器,不是方向盘。放大的是你的工作效率,但如果方向错了,工具只能让你更快地跑向错误的地方。
6. 扩展方向:把工作流包从“个人玩具”升级为“团队基建”
6.1 接入本地模型与私有化推理
如果对数据安全有要求,可以不使用 Claude 云端模型,而是调用本地模型。Claude Code 支持配置自定义推理端点,比如接入 LM Studio 这类本地模型服务。这个方向的好处是代码完全不出内网,适合涉及敏感数据的项目。坏处也很明显:本地模型的推理能力通常不如云端,复杂代码审查任务的效果会大幅缩水。
我的建议是分场景:对简单的提交信息生成、文档生成、周报等任务,本地模型的 response 时间足够且效果不差;但对代码审查、缺陷定位这类需要深度理解的任务,还是应该使用最强模型。可以这样按命令设置模型组:/提交和/周报走本地模型,/审查和/定位走云端模型。这样既控制了成本,又保证了关键任务的质量。
6.2 命令的自定义与团队模板沉淀
团队使用的过程中,命令会自然分化为“个人版”和“团队版”。我自己的实践是:每个团队项目管理的关键命令从 10 个精简到 5 个——审查、定位、提交、周报、导读——剩下的归类为个人扩展命令。团队版本由一个人维护,变更后通过 Git 合并到主干,其他人git pull自动更新。
另外可以考虑增加一个/模板命令,它不做任何分析,只是输出一组标准的 Markdown 模板,包含代码 review 清单、项目交接文档、故障报告等。这个命令的价值不在于“智能”,而在于统一团队的文档结构。时间长了,团队产出的文档风格会非常一致,后续检索和维护都省心很多。
6.3 未来扩展:定时任务与自动流程
目前这套工作流包全部是“对话时触发”,没有做到主动触发。后续可以考虑扩展的方向是把命令接入到 CI 流程中,比如每次 MR 创建后自动触发/审查,把审查结果写到 MR 评论里。也可以写一个定时任务,每周五下午自动跑/周报,把生成的内容推送到团队群。
这些扩展的实现路径会复杂一些,已经不是单纯的 Claude Code 范畴。但从实际收益看,越往这个方向走,效率提升越明显。代码质量检查从“人肉+主动”变成“自动+被动”,工作流本身的维护成本也大幅下降。
写在最后的实操体会
这套 10 个中文命令组成的 Claude Code 工作流包,用到现在大概三个月。我的体会是:AI 编程工具的潜力,很大程度上取决于你怎么包装它。同一套模型,一个什么都不配置的人可能觉得它只是高级一点点的搜索引擎;但一个把命令、权限、上下文管理都调好的人,能把它用成真正意义上的“团队高级工程师”——能审查、能定位、能写文档、能出周报。
如果你是刚接触 Claude Code,我的建议特别简单:今天先别写十个命令,就写一个。挑你最痛的那个环节,比如提交信息总是被吐槽,那就先做一个/提交命令。跑通一次,感受一下“输入两句话,输出一段规范文案”的体验,之后再逐步扩充。命令不是越多越好,顺手才是硬道理。