背景
由于国内很难使用到国外的ai agent,所以日常工作中都是用trae开发,虽然他生成的代码可以运行,我也会审核,没问题就放上线上运行。不过由于现在离职后,发现求职过程中,大部分岗位都是要会用claude code,我不得不学习如何使用。
而使用各种ai协助开发也经常遇到一个问题,就是经常改代码会改把原有的代码改坏或ai新增的代码频繁改坏。这个导致我工作效率下降。所以通过学习claude code 官方文档补充claude code的使用技巧。 Claude Code官网
作为小白入门
使用过程中遇到的概念
-
它不是聊天框,是一个带工具的对话代理,要规范它的执行权限。
- 永远先让它只读验证:让它先 Read / Grep 把“要改哪里”指给你看
- 再让它改:改完立刻用 Read 或运行命令检查结果
- 不确定就先落盘到 tmp/报告文件:别让它直接 overwrite 关键源文件(除非你信任流程)
-
claude工作范围:当前项目根目录以及你明确给它的路径。
-
上下文:可见材料的总和(文件 + 对话 + 规则),而且会“满”。
-
CLAUDE.md:唯一的“长期记忆”与“行为规范”(优先级最高)
- 写规则(不许做的事、必须做的事)
- 写路径契约(哪些文件夹放什么)
- 写流程顺序(先 A 后 B,不要跳步)
- 写输出要求(写文件,不要只回复文本)
-
SKILL:把“流程 + 约束 + 工具权限”固化下来
- 编写目录:.claude/commands//SKILL.md(旧版目录)、.claude/skills//SKILL.md(新版)
- Skill 不是“函数库”,更像“任务工单 + SOP”
- description:决定什么时候被匹配/你怎么唤起
- allowed-tools:把权限收口(只读任务就不该给 Write/Bash)
- 正文指令:写清楚“输入在哪、输出写到哪、怎么才算完成”
- 多个 Skill 协作:靠“文件作为接口”,不靠魔法。
- ARGUMENTS去解析/your-skill后面跟着的参数。
-
MCP(Model Context Protocol):给 Claude 装"外接手臂,让 Claude 能碰它原生工具碰不到的东西(数据库、Notion、GitHub API、浏览器…)
-
上下文:在这一次对话的某个时刻,脑子里的全部已知材料。
- 你当下说的话 / 发的命令
- 对话历史
- CLAUDE.md
- 它用工具读到的内容(Read / Grep / Glob 的结果)
上下文
我因为国内使用国外模型不方便,于是就是用deepseek v4,他最新的支持1M token,这个是什么概念呢?大概几十万汉字,但 Claude Code 里一个文件读一次就几千~几万 token,加上命令输出、对话历史、CLAUDE.md,烧得比你想象的快。
回话时会消耗大量的token
┌─ 系统提示(Claude Code 自身的指令层)
├─ CLAUDE.md / 项目规则(每次都要参考)
├─ 对话历史(你之前所有轮次的消息 + Claude 的回复)
├─ 所有工具调用结果(Read 的文件内容、Bash 的输出、Grep 的命中…)
├─ 你这次的新输入
└─ 还要预留空间给自己生成回复
对话越长,每一轮要重传的"历史"就越长,上下文不是只涨一点点,是累加式增长——这是为什么长调试 session 会烧掉几万 token 很正常.
常用指令
如果当前对话token已满会发生什么
① 最常见:自动压缩(Auto-compaction)——软着陆
Claude Code 会在接近满时自动触发压缩:把早期对话变成一份摘要(summary),腾出空间继续跑。
你会看到类似提示:
"This session is being continued from a previous conversation that ran out of context…"
代价是什么?
-
早期细节会损失(为什么当初选方案 A 不选 B 的理由、被否掉的思路)
-
但关键信息(你让它保留的 intent、碰了哪些文件、当前待办)会通过一个"结构化摘要模板"带过来
-
Claude 还会尝试 rehydration——重新读你正在改的文件,尽量不掉链子.
② 你主动清:/compact——你控制的压缩
③ 你主动砍:/clear——最狠但最有效
清掉聊天历史,但 CLAUDE.md 和项目文件还在。适合:切换任务时(你刚修完 login bug,现在要做 migration——这两句话在同一个对话里硬续着跑是最费上下文的).
SKILL
存储位置
当skill的名称重名,读取优先级:企业>个人>项目。意味着优先级越高的,优先读取为该skill名称的功能。
插件这个独享命名空间,不跟其他冲突。
如果项目存在旧版本的目录commands,那么skills下的命令优先。
工作原理
它是通过“推断”工作
/run 和 /verify 的默认行为 =
识别项目类型(Node/Python/Go/Rust/Electron...)
+ 翻 README / package.json / Makefile 找启动线索
所以:
-
✅ create-react-app / vite / 标准 express / 标准 CLI 工具 → 大概率直接 /run就起飞
-
❌ 需要 db / env / migration / monorepo 多包 / 自研启动脚本 → 推断开始发抖,这时候就该 /run-skill-generator
启动项目的skill
/run—— 启动并驱动你的 app
-
目标:让应用进入运行状态,并把"变更是否肉眼/机器可观测"这个结果带回来。
-
无参数就能跑:/run
-
它会尝试推断项目类型:CLI / Server / TUI / 浏览器驱动类,并从 README、package.json、Makefile里猜启动命令。
/verify—— 构建 + 运行 + 裁定
-
目标:确认"代码变更在运行态下确实有效",而且它刻意不做下面这些替代品:
-
❌ 不代替跑单元测试(测试是给 CI/开发视角的)
-
❌ 不代替类型检查(类型过了≠功能对了)
-
❌ 不写你的单元测试
-
-
它会去找变更的"用户表面"(CLI 输出、API 端点、GUI 界面),实际驱动它执行,然后给出裁定:
但是verify不会做全套测试,是"运行时观察",测试归测试,它管的是 app 跑起来之后,变更是否可观测地生效。两者互补,不替代。
但以上两个skill显然不够大部分生产环境下所需的功能,因为项目可能还要启动其他,例如redis、读取.env、需要图形 session / 特殊环境等。那么run和verify可能就推断不准确,导致无法正确启动项目。为了解决这个问题,官方提供了一个skill——/run-skill-generator
/run-skill-generator—— 当"自动推断"不够用时
- 它做什么:从一个干净环境里,陪你把应用跑起来,然后把"什么安装命令、什么 env、什么启动脚本"记录成一个 项目级 skill 存到 .claude/skills/run-/。
- /run和 /verify不再靠猜,而是直接跟配方走。
- 每个项目跑一次;构建/启动流程变了就再跑一次。
它会:
- 和你一起(或以引导方式)把应用从零跑起来
- 捕获有效的:install 命令 / env 需求 / 启动脚本
- 写进 .claude/skills/run-/里
之后你再看目录,大概会多一块东西(这是它产出的项目级 skill,不是你手写的):
.claude/skills/run-<name>/
└── SKILL.md ← 记录了"怎么装、怎么启"
但要注意:它记录的是"构建 + 启动应用"的最小可行配方,不是 CI/CD、不是容器编排。目标是让 Claude 在开发机上可靠地把 app 跑起来。
实际工作中如何使用更好
前置思考:在开始之前你需要考虑的 N 个问题
1. 先定目标与边界
-
改动范围:明确哪些文件改,哪些文件绝对不能动。
-
验收标准:怎么算做完?是跑通测试,还是仅仅是看起来对了?
-
约束条件:有没有特殊的编码规范或业务逻辑不能破坏?
目的:不要让 AI "自由发挥",而是给它画一个牢笼。
2.设计验证方案
-
如何验证:是看 Diff(代码差异),还是跑单元测试?
-
观察指标:应用会不会崩溃?关键功能是否正常?
-
回滚机制:万一错了,如何一键还原?(强调 Git 的重要性)
目的:AI 的自检往往不可信,你需要预设"检查点"。
3. 授予最小必要权限
-
工具选择:是只需要读取(Read/Grep),还是需要修改(Edit/Write)?
-
命令限制:如果需要用 Bash,是否锁定了具体的命令前缀(如只允许 npm run而不允许 rm -rf)?
目的:给 AI 刚刚好的工具,不多不少。
如何让ai更准确实现任务
claude.md 如何编写能够更好的落地规则
公式:角色边界 + 输入契约 + 步骤化动作 + 输出契约 + 验收证据 + 禁区(负约束)
公式解读
1) 角色边界(Scope):把“你能碰哪、不能碰哪”钉死
## Scope(必须遵守)
- 只处理目录:`src/`、`lib/`、`scripts/`
- 禁止碰:`dist/`、`build/`、`*.env`、`*.lock`、CI 配置、migrations/
- 若任务不可避免需要动禁区文件 → 先停、说明理由、等我确认
2) 输入契约:说清“你从哪拿到数据、格式是什么”
## 输入
- 主文件:`src/config.ts`(必须存在)
- 额外读取:`src/types.ts`
- 用户输入:`$ARGUMENTS` 解析为 `--dry-run | --apply`
- 不依赖隐式环境变量;必须显式 Read 并检查存在性
3) 前置条件(Preconditions):不满足就停,不要硬来
## 前置检查(任一步失败就终止并报告)
1. 用 Glob 确认目标文件存在
2. Read 文件后校验关键导出/标识(例如 `export const CONFIG`)
3. 若缺失 → 输出 ❌ 并列出期望路径/标识,STOP
4) 步骤化动作:写“可复核的原子动作”,别写“目标宣言” ❌ 不准写法:
帮我把配置重构得更优雅
✅ 改成:
## 执行步骤(严格按序,每步完成后汇报一行状态)
1. Read `src/config.ts`,列出:当前字段、类型、调用点(用 Grep 找引用)
2. 向我展示一份「变更计划」(增/删/改名清单),等我回 OK
3. 仅在我回 OK 后:用 Edit 做精确替换(一次一小块,不要整体覆写)
4. 每处改动后:Read 被改区域 ±10 行,回显确认
5) 输出契约:不仅说“写哪”,还要说“写成什么样”(可核验)
## 输出
- 只写到:`src/config.ts`
- 不新增文件,除非我明确批准
- 每次变更后输出:
✅ 已改:[file]:Lstart-Lend
📌 变更摘要:-fieldX +fieldY
6) 验收证据(Evidence):把“我觉得好了”变成“你能证明它好了”
## 验收(必须做)
- TypeScript:`npx tsc --noEmit`(若失败 → 回滚描述)
- Lint:`npx eslint src/config.ts --max-warnings=0`
- 行为:若涉及运行时,给出最小调用用例(例如打印 config 快照),Read 输出并核对
7) 禁区与负约束(Negative constraints):越具体越准确
## 禁止
- 不改 `package.json`、`tsconfig.json`、`*.lock`
- 不做“顺便格式化整个文件/整个目录”
- 不引入新依赖
- 不把密钥/令牌写进源码或日志
模板
## 任务
<一句话说清:改什么、达到什么效果、不改什么>
## 输入
- 目标文件/目录:
- 参数解析:$ARGUMENTS → <字段>=<值> 或 <路径> <备注>
## 前置检查
- 存在性:
- 合法性(必须包含/不能包含):
## 步骤(每步都要可复核)
1) 定位:Glob/Grep → 给我「命中文件:L号:匹配行」
2) 计划:展示改动清单(改哪几行、为什么),等我 OK
3) 执行:Edit 精确替换(不要整体 Write)
4) 验证:Read 改动区;跑 typecheck/lint;给一行 ✅/❌
## 输出
- 改动记录写到:<固定路径>.log(可选)
- 终端输出:文件路径+行号+变更摘要
## 禁止
- 不动:<黑名单>
- 不新增:<不许新增的类型>
skill要严格限制其触发条件,及其功能
前置思考中,第一个问题的具体落地
description编写
description = 这个skill做什么(功能) + 什么时候该用它(触发条件) + 你可能会说的触发词
不要模糊描述,例如以下:
description: 处理文件的工具
description: 分析数据
description: 添加备注到文件
问题在哪:
-
"处理文件"——哪个文件?做什么操作? Claude 面对 20 个 skill 时,无法判断这个是不是最匹配的
-
没写触发词——Claude 只能靠猜,猜错就是你的代价 官方推荐的信息密度:
description: >
给文本文件末尾追加一行备注(// note: ...)。
当用户说"加个备注"、"标记一下"、"append note",
或直接调用 /add-note <文件名> "<内容>" 时使用。
只处理 .txt / .md / .ts / .js 等文本文件,不处理二进制。
有三个硬指标:
正文
不好的示例:
## Instructions
帮用户在文件上加个备注吧。
记得友好一点,展示结果。
推荐:
## Instructions
1. **解析参数**
- `$ARGUMENTS` 的格式预期为:`<文件名> "<备注内容>"`
- 从 `$ARGUMENTS` 提取:
- 文件名 = 第一个 token(不含引号的部分,或引号外第一段)
- 备注内容 = 引号内字符串,若无引号则剩余全部
2. **校验**
- 用 `Read` 工具确认文件存在且是文本(不是 .exe/.zip 等)
- 若文件不存在:输出 `❌ 找不到文件:<文件名>,请检查路径` 并停止
3. **执行**
- 用 `Edit` 工具在文件末尾追加一行:`// note: <备注内容>`
- 不要重写整个文件,只 append
4. **确认(强制步骤,不可省略)**
- 用 `Read` 重新读最后 3 行
- 输出:`✅ 已添加备注到 <文件名>:<备注内容>`,展示那 3 行
allowed-tools
前置思考中,第三个问题的落地
限制它能用的工具,防止"做得太多"。
坑点: 直接写 Bash= "允许跑任何 shell 命令"——对新手来说这通常太宽了。
官方支持的收窄方式是 Bash(前缀:*)语法,只放行"以特定前缀开头的命令":
allowed-tools:
- Read
- Edit
- Bash(git add:*)
- Bash(git commit:*)
- Bash(git status:*)
含义:只允许 git add ...、git commit ...、git status ...,其它 Bash 调用照样走默认权限/需要你确认。
自检
问自己三个问题,全答"是"就过关:
-
如果我同时对 Claude 说一句话,它有 5 个 skill 可选,它能通过这个 description 唯一锁定这个吗?
-
description 里有没有写"当用户说 ___ 时用"?(触发锚点)
-
有没有写"不做 ___"?(排除边界,防误触发)
反例自检:如果你的 description 删掉后 Claude 照样能猜对——说明它不够特异,多个 skill 会打架;如果删掉后 Claude 完全不知道什么时候用——说明你没给够语义锚点。
上下文管理
你想要它准,就得保证工作台上是相关、精简、可核查的材料。
一条经验:
如果你发现自己在对话里反复解释同一件事,说明你该把它固化到 CLAUDE.md 或 SKILL.md,让它从文件里读,而不是每次靠对话史"背着"。