一、起点:Prompt 不是命令,是请求

刚用 Claude Code 时,我在 CLAUDE.md 里写了句:“永远不要修改 config/prod.env”。直到某个深夜,它在一次复杂重构中“顺手”改了那个文件。

原因很简单:模型没有“听话”的义务。上下文一长、噪声一多,任何书面约束都可能被选择性忽略。我需要三样东西:

  1. 管好上下文——让模型清晰地知道该做什么,别往雷区看;
  2. 硬性拦截——不管模型怎么想,危险操作物理上无法执行;
  3. 把复杂流程打包——让模型按可靠流程做事,而不是每次自由发挥。

二、上下文工程:管理模型的注意力

2.1 为什么“记住一切”是陷阱

上下文窗口是固定的注意力池。塞得越多,每条信息分到的注意力越少。关键指令淹没在冗余背景里,输出质量反而下降。上下文工程的本质不是“装更多”,而是维持高信噪比

2.2 三层架构

层级 组成 特点
系统提示词 工具定义、安全规则、行为底线 Anthropic 维护,不可见不可改,最高优先级
CLAUDE.md 项目级持久化指令 用户唯一可持久影响的入口,跨会话自动加载
对话历史 用户消息、助手回复、工具结果 动态增长,最先触及上限

核心认知:系统提示词 > CLAUDE.md > 对话历史。 不要在对话里反复重申已有的规则,那是在浪费上下文。

2.3 用 CLAUDE.md 和 Rules 建立持久共识

CLAUDE.md 是项目的“默认记忆”,放通用规范。当项目变大,引入 Rules(模块化规则),按需加载,与 CLAUDE.md 平级,同属软约束。

# CLAUDE.md 示例
## 核心约束
- 不要修改 config/prod.env
- 遵循 ESLint 和 Prettier 配置
- 数据库迁移规范见 @.claude/rules/database.md

注意:这一切都是“软约束”。 模型会尽力遵守,但不保证。真正的安全兜底在 Hooks。


三、Skills:把“可靠流程”打包

3.1 为什么需要 Skills

CLAUDE.md 告诉模型“什么能做、什么不能做”,但它不教“怎么做”。比如你写“请帮我部署到 staging”,模型可以自由选择步骤顺序、跳过检查、忽略回滚——每次都像开盲盒。

Skills 解决的就是这个问题:把已验证的、可靠的做事流程打包成可复用的单元。 它本质上是一个结构化的“工作流模板”,包含:

  • 该任务的目标描述
  • 一步步执行流程
  • 可以调用的工具和权限
  • 可以附带的专属 Hooks(限定作用域)

3.2 Skill 的结构

一个 Skill 定义在 .claude/skills/ 目录下,是一个带 YAML frontmatter 的 Markdown 文件:

---
name: deploy-staging
description: 安全部署到 staging 环境
allowed-tools: [Bash, Read, Write, Grep]
---

# 部署流程

## 步骤
1. 运行 `npm test`,测试不通过则停止
2. 确认当前分支为 main
3. 构建项目:`npm run build`
4. 执行迁移:`npm run migrate:staging`
5. 部署:`npm run deploy:staging`

## 回滚条件
- 任一步骤失败,立即停止并报告
- 禁止跳过测试步骤

3.3 Skills 与 CLAUDE.md、Hooks 的区别

机制 解决什么问题 类比
CLAUDE.md / Rules 告诉模型什么能做、什么不能做 员工手册:写明规范和禁忌
Skills 告诉模型怎么一步步做 标准作业流程(SOP):拧哪个螺丝、用多大扭矩
Hooks 管住模型绝对不许做的动作 机器急停开关:手伸进去就断电

三者的协同关系:

  • CLAUDE.md 说:“部署要小心。”
  • Skill 说:“部署按这 5 步走,少一步都不行。”
  • Hook 说:“不管谁让你改 prod.env,直接拦截。”

3.4 Skills 的独特能力

Skills 有两个 Claude.md 和 Hooks 不具备的优势:

1. 限定作用域的 Hooks
Skill 可以携带专属 Hooks,只在执行该 Skill 时生效,结束后自动清理,不污染全局。比如部署 Skill 可以在 PreToolUse 时检查是否在多步流程中跳过了测试步骤。

2. 工具白名单
通过 allowed-tools 字段,限制 Skill 执行期间模型可调用的工具。部署流程不需要浏览器工具,就不给它。


四、Hooks:强制执行的“代码闸门”

4.1 Hook 的本质

Hooks 是嵌在执行流程里的可编程检查点。它不是 Prompt,是跑你写的代码。在模型准备调用工具时,Hook 先站出来裁决:

  • 放行
  • 拦截(并给出理由)
  • 转交人工确认

模型无法绕过。 这是从“请求”到“命令”的质变。

4.2 28 个事件

阻断式事件——Hook 不返回 Claude 就卡住:

事件 触发时机 典型用途
PreToolUse 调用工具前 拦截危险操作
PostToolUse 工具执行后 校验结果
PermissionRequest 请求授权时 自定义权限
Stop 会话结束时 提取摘要

非阻断式事件——旁路执行,Claude 不等:
Notification、SessionStart、UserPromptSubmit 等,适合记日志、同步状态。

事件之间是兄弟关系,独立触发。

4.3 注册 Hook:三层嵌套

{
  "hooks": {                    // 第一层:事件注册表
    "PreToolUse": [             // 事件名
      {
        "matcher": "Write",     // 第二层:匹配工具名
        "hooks": [              // 第三层:执行逻辑
          { "type": "command", "command": "./protect-prod.sh" }
        ]
      }
    ]
  }
}

4.4 裁决语法(踩坑点)

退出码 效果
exit 1 什么都不会发生!(最大坑)
exit 2 被视为系统错误,可能被绕过
exit 0 + JSON 正确的策略决策
# 拦截
{"decision":"deny","reason":"生产配置受保护"}
# 放行
{"decision":"allow"}
# 转人工
{"decision":"ask","reason":"需要审批"}

4.5 合并规则

多个 Hook 命中同一操作时:并行执行 → 自动去重 → 最严格结果胜出(deny > ask > allow)。只要有一个 deny,操作即被拦截。

4.6 作用域

注册位置 作用域 生命周期
~/.claude/settings.json 用户级 常驻
.claude/settings.json 项目级 常驻
.claude/settings.local.json 本地级 常驻
Skill / 子 Agent 各自作用域 临时

4.7 实战:保护生产配置

#!/usr/bin/env bash
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
if [[ "$file_path" == *"prod.env"* ]]; then
  echo '{"decision":"deny","reason":"生产环境配置文件受保护,禁止写入"}'
  exit 0
fi
echo '{"decision":"allow"}'
exit 0

五、完整控制层级

┌─────────────────────────────────┐
│        系统提示词 (L1)           │  ← Anthropic 维护,不可见
│      定义工具与安全底线           │
├─────────────────────────────────┤
│         Hooks (L2)              │  ← 硬约束,代码闸门
│    PreToolUse 拦截危险操作       │    不管模型怎么想,直接裁决
├─────────────────────────────────┤
│    CLAUDE.md / Rules (L3)       │  ← 软约束,记忆与引导
│    “什么能做,什么不能做”         │    降概率,不保证
├─────────────────────────────────┤
│        Skills (L3)              │  ← 软约束,流程打包
│    “怎么做,按什么步骤做”         │    限定工具,附带临时 Hooks
└─────────────────────────────────┘

优先级:系统提示词 > Hooks > CLAUDE.md = Rules = Skills

协同逻辑

  • CLAUDE.md + Rules:让模型知道边界,别往雷区想。
  • Skills:让模型按可靠流程做事,减少自由发挥。
  • Hooks:不管模型怎么理解、记不记得、按不按流程,危险动作物理拦截。

六、项目中的完整结构

my-project/
├── .claude/
│   ├── settings.json              ← Hooks 注册
│   ├── settings.local.json        ← 本地 Hooks(不提交)
│   ├── CLAUDE.md                  ← 项目持久规范
│   ├── rules/
│   │   ├── database.md            ← 数据库专项规则
│   │   └── frontend.md            ← 前端专项规则
│   ├── skills/
│   │   └── deploy-staging.md      ← 部署标准流程
│   └── hooks/
│       └── protect-prod.sh        ← 硬拦截脚本
├── src/
└── config/
    └── prod.env                   ← 被保护文件

七、行业视角

机制 行业采用情况
CLAUDE.md / Rules 已成事实标准。Cursor、GitHub Copilot、Windsurf 等均已采用类似机制
Skills Claude Code 独特优势。部分工具通过自定义指令实现类似功能,但不如 Skills 结构化
Hooks Claude Code 的核心壁垒。 其他工具尚无原生硬阻断能力,多靠插件或外部脚本

八、核心要义

  1. CLAUDE.md 定边界,Skills 定流程,Hooks 定底线。 三层缺一不可。
  2. Prompt 是请求,Hooks 是命令。 安全底线必须用代码实现。
  3. exit 0 + JSON 是唯一的策略控制方式;exit 1 是废的。
  4. Skill 的 Hooks 是临时的,不会污染全局;Skill 可以限定工具白名单。
  5. 多层 Hook 不冲突,deny 一票否决。软硬兼施才是完整的 AI 工程化治理。

更多推荐