.claude 目录:一份藏在项目根目录里的 AI 协作协议

0 阅读14分钟

摘要:拆解 Claude Code 的核心配置目录 .claude——它由指令、工作流、专家、权限、记忆五个子系统构成,配合全局层、项目层、本地层三层配置叠加,形成一套完整的 AI 协作协议。本文逐一解析其目录结构、各子系统职责,以及背后的上下文成本设计思路。

用过 Claude Code 的人大概都注意过一件事:项目根目录下多了一个 .claude 文件夹,有时旁边还躺着一个 CLAUDE.md。

很多人的做法是:写几行 CLAUDE.md 告诉 AI "用 TypeScript、遵循 ESLint 规范",然后就再没碰过这个目录。但如果打开它仔细看,会发现里面远不止一份说明文档——rules、skills、agents、settings.json,各管各的事,拼在一起构成了一套完整的 AI 协作协议。

这篇文章会把 .claude 目录拆开,逐层讲清楚它的结构、每个子系统的职责,以及它背后的设计思路。

在这里插入图片描述

先看全貌:.claude 目录到底管什么

一句话概括:.claude 目录是 Claude Code 在项目级别的配置中心,它告诉 AI "你在这个项目里该怎么干活"。整个目录可以拆成 5 个子系统,各自负责不同的事情:

子系统核心职责关键文件
指令告诉 AI 怎么写代码、遵守什么规范CLAUDE.md + rules/
工作流定义可复用的自动化流程skills/ + commands/
专家派出独立上下文的子代理执行专项任务agents/
权限控制 AI 能用哪些工具、能运行什么命令settings.json
记忆跨会话持久化 AI 的学习笔记~/.claude/projects/

需要留意的是,.claude 目录并不是唯一的配置来源。Claude Code 实际上在三个层级读取配置:

  • 全局层(~/.claude/) — 跟着个人走,跨所有项目生效
  • 项目层(.claude/) — 跟着仓库走,团队共享
  • 本地覆盖层(settings.local.json 等) — 个人偏好,不提交到 git
  • 三层叠加,优先级从高到低是:本地覆盖 > 项目配置 > 全局配置。
# 项目层 .claude/
CLAUDE.local.md
.claude/
├── CLAUDE.md              # 项目级指令(团队共享)
├── settings.json          # 权限与运行时配置
├── settings.local.json    # 个人本地覆盖(不入 git)
├── rules/                 # 项目级规则文件
│   ├── api-design.md      # API 设计规则
│   ├── typescript.md      # TypeScript 规范
│   └── testing.md         # 测试相关规则
├── skills/                # 项目级工作流
│   ├── code-review/
│   │   └── SKILL.md
│   ├── deploy/
│   │   ├── SKILL.md
│   │   └── references/
│   └── fix-issue/
│       └── SKILL.md
├── agents/                # 项目级子代理定义
│   ├── security-audit.md  # 安全审计子代理
│   └── code-reviewer.md   # 代码评审子代理
└── commands/              # 旧版命令(已被 skills 取代)
    └── review.md

# 全局层 ~/.claude/
~/.claude/
├── CLAUDE.md               # 全局个人指令(跨所有项目生效)
├── settings.json           # 全局权限与运行时配置
├── projects/               # 各项目记忆存储
├── rules/                  # 全局规则(所有项目共享)
├── skills/                 # 全局工作流(所有项目可用)
└── agents/                 # 全局子代理定义

指令系统:CLAUDE.md 和 rules/ 的分工

CLAUDE.md 是整个目录里优先级最高的文件。每次启动会话时,Claude Code 首先读它,把内容注入系统提示词,整个对话期间持续生效。它的作用类似于给 AI 的一份"项目须知":用什么语言、怎么跑测试、关键目录在哪里、有什么注意事项。

# 项目概述
这是一个基于 Next.js + TypeScript 的全栈项目,使用 Prisma ORM。

# 技术栈
- 语言:TypeScript(严格模式)
- 框架:Next.js 14(App Router)
- 数据库:PostgreSQL + Prisma
- 测试:Vitest + Testing Library

# 开发命令
- npm run dev — 启动开发服务器(端口 3000)
- npm run test — 运行测试
- npm run lint — ESLint 检查
- npm run db:migrate — 数据库迁移

# 关键目录
- src/app/ — 页面路由
- src/lib/ — 共享工具函数
- prisma/ — 数据库 schema 和迁移文件

# 注意事项
- 所有 API 路由必须有错误处理和输入校验
- 禁止直接操作 DOM,使用 React 状态管理
- 数据库 schema 变更必须通过 migration,禁止手动改库

CLAUDE.md 有 4 个可以放置的位置,适用范围不同:

  • 项目根目录的 CLAUDE.md — 团队共享指令,提交到 git
  • .claude/CLAUDE.md — 同上,另一个合法位置
  • 项目根目录的 CLAUDE.local.md — 个人项目偏好,默认被 gitignore
  • ~/.claude/CLAUDE.md — 全局个人指令,跨所有项目生效

实践中建议将 CLAUDE.md 控制在 200 行以内。原因很简单:它是每次会话都会加载的固定成本,写得越长,留给实际代码讨论的上下文空间就越少。而且 Claude Code 在压缩上下文(/compact 命令)后会重新从磁盘读取这个文件,过长的内容会反复挤占空间。

那如果团队规范确实很多怎么办?这就是 rules/ 目录存在的意义。

rules/ 下面放的是按关注点拆分的 Markdown 文件,每个文件负责一组特定规则。它支持两种模式:无路径限定(始终加载,和 CLAUDE.md 一起生效)和路径限定(只在 Claude 操作匹配路径的文件时才加载)。路径限定通过文件头部的 YAML frontmatter 实现:

---
paths:
  - "src/api/**/*.ts"
  - "**/*Controller*.ts"
---

# API 设计规则
- 所有接口使用 RESTful 风格
- 错误码统一用 HTTP 状态码 + 业务码组合
- 响应体必须包含 code、message、data 三个字段

这个设计的好处是按需加载:一个前端工程师在改 React 组件时,不需要被后端的 ORM 规范占用上下文窗口。一个有效的拆分时机是:当某段内容只适用于特定文件或场景,且篇幅较长时,就该提取到 rules/ 里。

CLAUDE.md vs rules/ CLAUDE.md 是"全局广播",rules/ 是"定向通知"。前者适合放构建命令、架构概述和通用规范,后者适合放特定语言、特定模块、特定框架的详细约束。

工作流系统:Skills 和 Commands

指令系统解决的是"遵守什么规范"的问题。但在实际开发中,还有大量的重复性工作流:代码审查按固定清单走、部署执行一串固定命令、修 Issue 有标准流程。这些单靠规范文档搞不定,需要把步骤编排成可执行的流程。

这就是 skills/ 目录的作用。每个 skill 是一个子目录,里面有一个 SKILL.md 入口文件,用 Markdown 写清楚这个工作流要做什么、按什么步骤执行。和 rules 最大的区别在于:rules 是被动的("始终遵守这些规范"),而 skills 是主动的("当我说执行这个流程时,按这些步骤来")。

skills 和 rules 还有一个关键差异:上下文成本不同。rules 在会话启动时就全量加载(路径限定的除外),持续占用上下文窗口;而 skills 只在被调用时才加载,用完就释放。对于那些偶尔才用到的复杂流程,做成 skill 比塞进 rules 更经济。

skill 的调用有两种方式:用户在对话中输入 /skill-name 手动触发,或者 Claude 根据 SKILL.md 里的 description 字段自动判断"当前对话适合用这个 skill"然后自己触发。这两种方式可以通过 frontmatter 里的 disable-model-invocationuser-invocable 字段分别开关。

SKILL.md 还支持两个特殊语法。一是 Shell 注入:用 ! 加反引号包裹一段 shell 命令,skill 加载时会先执行这段命令,把输出注入上下文。比如一个"修 Issue"的 skill 可以在加载时自动拉取最新的 Issue 详情。二是变量替换:$ARGUMENTS 代表调用时传入的参数,${CLAUDE_SKILL_DIR} 代表当前 skill 的目录路径,方便引用同目录下的参考文档。

---
description: 修复指定的 GitHub Issue,自动拉取详情并生成修复方案
user-invocable: true
---

# 修 Issue

## 当前 Issue

!`gh issue view $ARGUMENTS --json title,body,labels`

## 修复步骤

1. 分析 Issue 描述,定位相关代码
2.  src/ 目录下查找受影响的模块
3. 编写修复代码,确保通过现有测试
4. 运行 npm run test 验证修复
5. 提交 PR,关联 Issue 编号

## 参考文档

完整的代码规范见 ${CLAUDE_SKILL_DIR}/references/coding-standards.md

至于 commands/ 目录,它是 skills 的前身。每个 .md 文件的文件名即对应一个命令名。不过 skills 系统已经完全覆盖了 commands 的能力,如果两者同名,skill 优先。新项目建议直接用 skills。

专家系统:Agents 子代理

skills 和 rules 都在主对话的上下文里运行。但有些任务天然需要独立的视角——安全审计不应该被前面讨论的业务逻辑干扰,代码评审需要"假装自己没参与写代码"的旁观者心态。

agents/ 目录就是为这类场景设计的。每个 .md 文件定义一个子代理角色,包含名称、职责描述、可以使用的工具列表、模型选择等。和 skill 最本质的区别是:agent 被委托执行任务时,会拿到一个独立的上下文窗口,在里面完成工作,然后把结果压缩成摘要返回给主会话。

# 安全审计 Agent

你是一个专注于安全审计的代码审查专家。你的任务是检查代码中可能存在的安全风险,生成结构化的审计报告。

## 审计范围

- SQL 注入、XSS、CSRF 等常见漏洞
- 敏感信息泄露(硬编码密钥、token)
- 依赖包已知漏洞(CVE)
- 权限控制和认证逻辑

## 工具限制

只允许使用 Read 和 Grep,禁止执行任何写操作或运行代码。

## 输出格式

对每个发现的问题按严重程度分级:
- 🔴 严重:必须立即修复
- 🟡 警告:建议尽快处理
- 🔵 建议:可选优化项

## 模型

使用 claude-sonnet-4-20250514 以平衡审计质量与成本。

这意味着 agent 适合那些"需要专注、不想被主对话上下文污染"的任务。根据官方文档,agent 还支持一些 skill 不具备的能力:

  • 跨会话记忆 — agent 可以配置持久记忆范围,下次被调用时还记得之前的观察。
  • Git worktree 隔离 — 设置 isolation: worktree 后,agent 在独立的 git 工作树副本里运行,不影响当前分支。
  • 模型降级 — 可以给特定 agent 配一个更便宜的模型(比如用 Sonnet 跑日常任务),节省 API 开销。
  • 后台运行 — 设置 background: true 后,agent 始终作为后台任务执行,不阻塞主对话。

不过 agent 有一个限制:它不能再嵌套生成 agent。所以它更像是"最终执行者",而不是可以继续分发工作的中间层。

权限系统:settings.json 的三级控制

前面几个子系统都在定义"AI 该做什么",而 settings.json 解决的是"AI 能做什么"——它是权限的护栏。

Claude Code 的权限模型分三级:Allow(直接放行,不需要确认)、Ask(弹窗询问,这是未配置工具的默认行为)和 Deny(完全禁止,直接拦截)。评估顺序是 Deny 优先——即如果一个工具同时出现在 allow 和 deny 列表里,deny 胜出。

权限规则的语法支持通配符匹配,比如 Bash(npm test *) 可以放行所有以 npm test 开头的命令,Read(./.env) 可以单独控制对 .env 文件的读取权限。用过 Claude Code 的人可能有过这样的体验:跑一段完整的开发流程,需要频繁点击"允许"来授权各种操作。通过预先在 settings.json 里配置好 allow 列表,可以把这种打断降到最低。

{
  // 权限控制
  "permissions": {
    "allow": [
      "Bash(npm test *)",         // 放行所有 npm test 命令
      "Bash(npm run lint)",       // 放行 lint 检查
      "Bash(npm run dev)",        // 放行开发服务器
      "Read(src/**)",             // 放行读取 src 目录
      "Write(src/**)"             // 放行写入 src 目录
    ],
    "deny": [
      "Read(.env)",               // 禁止读取环境变量
      "Bash(rm -rf *)",           // 禁止危险删除命令
      "Bash(git push --force)"    // 禁止强制推送
    ]
  },
  // 其他配置
  "model": "claude-sonnet-4-20250514",
  "env": {
    "NODE_ENV": "development"
  }
}

settings.json 也有个人覆盖版本:settings.local.json。它不提交到 git,适合放个人 API 密钥、本地机器特有的路径配置等。整个优先级链条从高到低依次是:托管策略(IT 设定)> CLI 参数 > settings.local.json > settings.json > ~/.claude/settings.json。

除了权限,settings.json 还能配置默认模型、环境变量、是否开启自动记忆等。它实际上是整个 .claude 目录的"运行时参数"入口。

记忆系统:让 AI 跨会话记住项目经验

前面 4 个子系统都是开发者主动配置的,记忆系统则不太一样——它是 Claude Code 自动生成的。

工作过程中,Claude Code 会自动保存一些观察笔记:发现的构建命令、代码模式、架构特征等。这些笔记存放在全局目录 ~/.claude/projects/<项目>/memory/ 下面。每次新会话启动时,Claude Code 会读取该项目的 MEMORY.md 索引文件(前 200 行或 25KB),把之前学到的东西重新带入上下文。

~/.claude/
└── projects/
    ├── my-nextjs-app/
    │   ├── MEMORY.md              # 记忆索引(会话启动时自动读取)
    │   └── memory/
    │       ├── 2026-04-10.md      # 当天工作笔记
    │       ├── 2026-04-11.md
    │       └── 2026-04-15.md
    └── python-api-service/
        ├── MEMORY.md
        └── memory/
            ├── 2026-04-08.md
            └── 2026-04-12.md

开发者也可以主动干预这个过程。在对话中说"记住这个:我们项目的端口固定是 3001",Claude Code 就会写入持久化记忆。用 /memory 命令可以查看和管理当前项目的记忆内容。

但有一点需要注意:记忆是机器本地的,不会跨设备同步,也不会共享给团队。它只解决"同一台电脑上连续工作时的上下文延续"问题。如果团队需要共享某些上下文,应该写进 CLAUDE.md 或 rules/,而不是依赖记忆系统。

背后的设计逻辑:为什么是这套结构

回头来看,.claude 目录的 5 个子系统并不是随意堆砌的。它们实际上在回答一个 AI 编程助手运转所需的五个基本问题:

  • 应该遵守什么规矩? → 指令系统(CLAUDE.md + rules/)
  • 遇到重复任务怎么办? → 工作流系统(skills/)
  • 需要专家视角时找谁? → 专家系统(agents/)
  • 哪些操作允许自主执行? → 权限系统(settings.json)
  • 之前学到的东西怎么保留? → 记忆系统(memory/)

而且这 5 层之间有一个清晰的上下文成本梯度:CLAUDE.md 和无路径限定的 rules 是常驻开销,每次会话都会占用上下文窗口;路径限定的 rules 是条件开销,只在操作特定文件时加载;skills 是按需开销,调用时才加载;agents 则完全在独立窗口运行,不占用主对话的空间。这意味着开发者可以根据"这条信息会被多频繁地使用"来决定把它放在哪一层——频繁用到的基础规范放 CLAUDE.md,偶尔用到的复杂流程做成 skill,需要独立判断的专项任务交给 agent。

团队协作:如何共享环境

在团队协作过程中,.claude 目录应该当成项目基础设施的一部分提交到 git。它本质上和 .eslintrc、.editorconfig 是同一性质的东西——团队对"AI 在这个项目里该怎么干活"达成的共识。新成员克隆仓库后,不需要任何额外配置就能获得和团队一致的 AI 协作体验。

此外,还需要注意团队配置和个人配置的分离。CLAUDE.md、settings.json、rules/、skills/、agents/ 都提交到 git,跟着仓库走,保证团队成员看到同一份规范。而 CLAUDE.local.md 和 settings.local.json 不入库,留给个人偏好。全局层 ~/.claude/ 则是跨项目的个人配置空间。这三层叠加的结构,本质上和软件工程里常见的"全局配置 → 项目配置 → 本地覆盖"模式一脉相承。

# Claude Code - 个人配置不入库
.claude/settings.local.json
CLAUDE.local.md

# 团队共享配置提交到 git(不需要 ignore)
# CLAUDE.md
# .claude/settings.json
# .claude/rules/
# .claude/skills/
# .claude/agents/

总结

.claude 目录的作用可以概括为:用 5 个子系统把"AI 在项目中该遵守什么规矩、能执行什么流程、可以动用什么工具、记住了哪些经验"这些问题结构化了。它的设计沿用了软件工程里常见的分层和按需加载的思路,只是这次被管理的对象从代码运行环境变成了 AI 的行为边界。

对于大多数项目来说,一个写得好的 CLAUDE.md 加一份合理的 settings.json 就能覆盖 80% 的需求。剩下的 rules、skills、agents,在真正需要时再逐步引入即可。一个建议是:在添加任何新配置之前,先问自己"不加它,我的卡点是什么"。能回答清楚这个问题,加进去的配置才不会变成无人维护的负担。

相关资源