一直在用 Claude Code 做开发——这个博客就是用它搭的,从主题配置、CSS 定制到内容生成、构建部署,全程对话式完成。甚至这篇文章里的朋友圈数据,都是它帮我从微信加密数据库里解密提取出来的。
用久了逐渐摸清了它的脾气,这篇算是一个实战总结。
它不是聊天机器人
先说最重要的认知:Claude Code 是一个 Agent 系统,不是问答工具。
它的工作方式是反复循环的代理过程:
读取上下文 → 选择工具 → 执行操作 → 观察结果 → 决定下一步
这个循环会一直跑,直到它认为任务完成或者需要你的输入。每一步都可能出错——选错工具、读错文件、基于过时的上下文做判断。
卡住的时候,往往不是模型不够聪明,而是你给了错误的上下文或者它没法验证自己做对了没。
真实踩坑
我让它推送博客到 GitHub,第一次把源码也推上去了——hugo.yaml、content/、themes/ 全暴露了。问题不在模型能力,而是我没告诉它"main 分支只放构建产物"。
加了 CLAUDE.md 规则后,它每次推送前都会自动跑检查:
| |
从此没再出过事。 不是它变聪明了,是规则在起作用。
需要关注的五个层面
当结果不对的时候,按这个顺序排查:
- 上下文加载顺序 — 结果不稳定?CLAUDE.md 是不是没被加载,或者被后面的内容覆盖了
- 工具选择 — 给了太多 MCP 工具?它可能选了一个不该用的
- 中间产物污染 — 长会话质量下降?上下文里堆满了之前任务的残留信息
- 验证闭环 — 它说"完成了"但没跑测试?“完成"不算数,得有证据
- 控制层缺失 — 自动化失控了?Hook 和 CLAUDE.md 里没有设约束
上下文工程:最重要的一件事
Claude Code 现在是 1M 上下文窗口。听起来很大,但实际使用中问题从来不是"不够长”——而是太吵了。
噪声从哪来
上下文空间是有"有效容量"的,以下这些东西会悄悄吃掉大量空间:
| 来源 | 大约消耗 | 说明 |
|---|---|---|
| 5 个 MCP Server 工具定义 | ~25,000 tokens | 每个工具的 schema 都会常驻 |
一次 git status -uall | 可达数万行 | 大仓库会刷屏 |
| 完整编译错误输出 | 几千到上万行 | 其实只需要报错那几行 |
| 之前任务的残留上下文 | 不定 | 最隐蔽的污染源 |
窗口大了不代表噪声可以放任。1M 上下文里塞满垃圾,模型找到关键信息的难度反而更高。
实践方法
截断输出——Claude 只需要知道"过了还是挂了、挂在哪":
| |
会话管理——这三个命令要形成肌肉记忆:
| |
实际体验:一个会话超过 20 轮之后,Claude 开始"忘记"前面说过的事,或者把两个不同任务的信息混在一起。这时候 /compact 比重新说一遍有效得多——它会保留关键决策,丢掉中间的探索过程。
Compact Instructions
可以在 CLAUDE.md 里写 Compact Instructions,告诉 Claude 压缩时必须保留什么:
| |
会话交接
长任务跨会话时,开新会话前让 Claude 写一份 HANDOFF.md:
| |
比依赖压缩算法靠谱——新会话读一遍就能无缝接上。
CLAUDE.md:和 Agent 的协作契约
这是 Claude Code 最核心的配置文件。写好了省心,写烂了每次都要重新纠正同样的事。
三级配置体系
~/.claude/CLAUDE.md → 全局规则,所有项目生效
项目根目录/CLAUDE.md → 项目级规则
项目子目录/CLAUDE.md → 模块级规则(可选)
Claude Code 启动时按顺序加载这三级,后者可以覆盖前者。
我的全局规则
| |
每条都是被坑出来的:
- 第 1 条:Claude 默认会用
pip install,在 uv 管理的项目里搞乱依赖 - 第 3 条:它特别喜欢"为了兼容性"多写一层抽象,导致代码膨胀
- 第 4 条:遇到 bug 它倾向于在旁边加个
if判断绕过去,改完代码更乱。加了这条后它会重构整个相关函数 - 第 5 条:有时候用户拒绝了某个权限,Claude 就直接放弃了。现在它会先试别的路,不行再告诉我
项目级规则(以这个博客为例)
| |
写清楚推送流程后,Claude 每次部署都严格按这个走。它会在推送前跑检查,发现有 .md 文件就停下来提醒我。
写 CLAUDE.md 的原则
该放的:
- 构建、测试、运行命令(
hugo server -D -p 4004) - 目录结构约定和命名规范
- NEVER 列表——绝对不能做的事(如"严禁推送源码")
- 代码风格(缩进、命名、注释语言)
- Compact Instructions
别放的:
- 大段项目背景介绍——Claude 读代码就知道了
- 完整 API 文档——太长,直接污染上下文
- 空泛原则(“写高质量代码”)——没有可执行性
- Claude 读仓库就能推断出来的东西
黄金法则:每次 Claude 做错被你纠正后,让它自己更新 CLAUDE.md。这样规则会越来越精准,越来越贴合你的习惯。
Skills:按需加载的工作流
Skills 不是模板库,是可以被模型按需触发的专家模式。
什么时候该做成 Skill
- 有固定流程、但不需要每次都加载的任务
- 需要 supporting files(参考文档、代码模板)辅助的工作
- 希望用
/skill-name一键触发的常用操作
描述怎么写
描述是写给模型看的,告诉它"什么场景下该触发我",而不是写一段人类看的说明文档。
| |
前者告诉模型触发条件,后者只是自我介绍。
分级管理
| 频率 | 策略 | 例子 |
|---|---|---|
| 每次都用 | auto-invoke 自动触发 | 代码审查、提交规范 |
| 偶尔用 | 手动 /skill-name 触发 | 部署、数据库迁移 |
| 很少用 | 别做成 Skill,写成文档 | 一次性的环境搭建指南 |
注意:每个 Skill 的描述都会常驻上下文占用 token,所以数量要克制。能用 CLAUDE.md 一句话说清的,就别单独做 Skill。
Hooks:确定性的硬约束
Hooks 解决一个根本问题:有些事不能靠 Claude 临场发挥,必须用确定性流程保证。
Hook 的执行时机
PreToolUse → 工具调用前触发(可以阻断)
PostToolUse → 工具调用后触发(可以检查结果)
Notification → 任务完成/出错时触发
适合做 Hook 的
- Edit 后自动 lint — 每次编辑文件后跑格式化,不靠 Claude 记得
- 保护关键文件 — 阻断对
.env、credentials.json的修改 - 完成后通知 — 长任务跑完了发个推送,不用一直盯着
不适合做 Hook 的
- 需要语义判断的(“这段代码质量好不好”)→ 放 CLAUDE.md 当规则
- 长流程的(“先构建再测试再部署”)→ 做成 Skill
- 要读大量上下文才能决定的 → Hook 拿不到完整会话
三层叠加
单独用任何一层都不够稳:
CLAUDE.md → 声明规则:"严禁推送源码"
Skill → 定义流程:"推送时按这个步骤走"
Hook → 硬性校验:"推送前检测到 .md 文件就阻断"
规则告诉它"该怎么做",流程告诉它"按什么顺序做",Hook 保证"做错了会被拦住"。
Subagents:隔离才是核心价值
Subagent 的核心不是"并行加速"——而是隔离。
大量输出的任务交给 Subagent 跑,它的上下文不会污染主线程。主线程只拿最终摘要。
实际使用场景
搭建这个博客的时候,我在主线程写文章,同时让 Subagent 去做调研:
主线程:写博客文章内容 → 配置 CSS → 调整排版
↕
Subagent 1(后台):搜索微信数据导出工具,返回推荐方案
Subagent 2(后台):搜索 QQ 空间爬虫工具,返回可用方案
Subagent 返回的结果是精炼过的摘要,不会把搜索过程中几十个网页的内容塞进我的主线程。
内置 Subagent 类型
| 类型 | 用途 | 工具权限 |
|---|---|---|
| Explore | 只读扫描代码库 | Read, Glob, Grep(不能写文件) |
| Plan | 规划实现方案 | Read, Glob, Grep(不能写文件) |
| General-purpose | 通用任务 | 全部工具 |
使用要点
- 限定工具权限:探索性任务不需要写文件的能力
- 按任务选模型:重型推理用 Opus,简单搜索用 Haiku,省钱
- 设
maxTurns:防止 Subagent 陷入死循环 - 改文件用
isolation: worktree:在独立的 git worktree 里操作,不会和主线程冲突 - 后台运行:
run_in_background: true,不阻塞主线程,完成后自动通知
Prompt Caching:省钱的关键
Claude Code 的架构围绕缓存构建。理解缓存机制能帮你省钱并减少速率限制。
缓存匹配规则
缓存按前缀匹配,从前往后对比:
System Prompt → 工具定义 → 对话历史 → 用户输入
前面的部分只要没变,就能命中缓存。改了前面的,后面全部失效。
避坑指南
| 操作 | 后果 | 建议 |
|---|---|---|
| System Prompt 里放时间戳 | 每秒都变,缓存永远不命中 | 时间放在用户消息里 |
| 中途加/删 MCP 工具 | 工具定义变了,后续全失效 | 会话开始前确定好工具集 |
| 打乱工具声明顺序 | 前缀不匹配 | 保持工具注册顺序固定 |
| 频繁切换模型 | 不同模型的缓存不共享 | 一个会话用一个模型 |
高命中率 = 更便宜 + 更少触发速率限制 + 响应更快。
常用命令速查
| |
Memory 系统
Claude Code 有一套文件级的持久化记忆系统,跨会话生效。
四种记忆类型
| 类型 | 用途 | 例子 |
|---|---|---|
| user | 用户画像 | “深度 Go 经验,React 新手” |
| feedback | 行为纠正 | “不要 mock 数据库,用真实连接” |
| project | 项目状态 | “3 月 5 日起代码冻结” |
| reference | 外部资源指针 | “bug 追踪在 Linear INGEST 项目” |
什么不该存
- 代码结构(读代码就知道了)
- Git 历史(
git log是权威来源) - 调试方案(修复在代码里,上下文在 commit message 里)
- CLAUDE.md 里已经有的东西
记忆的价值在于存非显而易见的信息——那些"你不说我不知道"的事。
实际工作流示例
以搭建这个博客为例,完整流程是这样的:
1. 初始化项目 → Claude 搭建 Hugo 目录结构
2. 配置主题 → 修改 hugo.yaml,定制 CSS
3. 写 CLAUDE.md → 定义推送规则和安全检查
4. 写内容 → 对话式生成文章
5. 数据整合 → Subagent 解密微信数据库、爬取 QQ 空间
6. 迭代修改 → 反复调整排版、图文混排
7. 部署 → Claude 构建 + 安全检查 + 推送
中间出过的问题:
- 推送了源码 → 加 CLAUDE.md 规则解决
- 图片路径不对 → page bundle 的图片需要放 static 目录
- 构建产物里混进了
.tmp文件 → 推送前加清理步骤 - 会话太长质量下降 →
/compact或/clear开新会话
每次踩坑都变成了 CLAUDE.md 里的一条新规则。系统在使用中自我进化,这才是 Agent 系统的正确用法。
最后
Claude Code 越好用,越容易忘记它是个需要治理的系统。
不设规则就是在赌每次运气都好。写好 CLAUDE.md、配好 Skills 和 Hooks、管好上下文——这些"无聊"的工程化工作,才是让 Agent 稳定输出的基础。
把它当团队成员来管理,而不是当工具来使用。

说些什么吧!