配置实战——settings.json 权限 + CLAUDE.md + Rules 懒加载
前两篇文章聊了"怎么操作Claude Code"和"怎么编排工作流"。这篇我们聚焦于配置——让Claude Code一启动就懂你的项目、只做你允许的事、在monorepo里不乱加载无关规则。

下面讨论的素材,来自shanraisshan/claude-code-best-practice仓库的真实配置。你可以直接拿来用,或者根据自己项目微调。
Part 1: settings.json 权限——allow / deny / ask 三区模型
权限系统是settings.json的核心——它就像一道门禁。每次Claude Code调用工具(Bash、Write、WebFetch等),都得先过这一关:
{"permissions": {"allow": ["Bash(npm test:*)", "Bash(npm run lint:*)", "Read(*)"],"deny": ["Bash(curl:*)", "Bash(rm -rf:*)", "Bash(git push --force:*)"],"ask": ["WebFetch(*)", "Bash(npm install:*)"]}}
三个区域的设计意图很明确:
| 区域 | 行为 | 用途 |
|---|---|---|
| allow | 自动放行,不弹窗 | 你每次都同意的安全操作(跑测试、读文件) |
| deny | 直接拒绝,模型看不到这个选项 | 绝对不能做的操作(删库、强制推送) |
| ask | 弹窗问你 | 需要你判断的操作(装依赖、调外部API) |
说到优先级,一个不能忽略的设计细节是:deny > ask > allow。如果一个操作同时匹配了deny和allow,deny赢。这条规则很关键——你不会因为allow规则写得太宽而意外放行危险操作。
实战配置:一个生产可用的权限模板
{"permissions": {"allow": ["Read(*)","Edit(*)","Bash(npm test:*)","Bash(npm run lint:*)","Bash(npm run build:*)","Bash(npx tsc:*)","Bash(git status:*)","Bash(git diff:*)","Bash(git log:*)","Bash(git branch:*)","Bash(git add:*)","Bash(git commit:*)"],"deny": ["Bash(rm -rf:*)","Bash(git push --force:*)","Bash(git reset --hard:*)","Bash(curl:*)","Bash(wget:*)"],"ask": ["WebFetch(*)","Bash(npm install:*)","Bash(git push:*)","Bash(git pull:*)","Bash(npm publish:*)"]}}
这个配置背后有几个原则:
allow不是越宽越好。 那种直接写"Bash(*)"的行为,等于废了权限系统。每个allow规则应该精准锁定你确认安全的命令。少即是多。
deny放操作后果不可逆的命令。 rm -rf、push --force、reset --hard——这些操作哪怕你误点了allow,也来不及后悔。直接堵死最省心。
ask放需要你判断上下文的操作。 WebFetch调外部API可能泄露代码、npm install可能引入恶意包——每次触发时你都该看一眼。
连接第2篇:跨层权限收窄模式
第2篇展示的Command→Agent→Skill三层编排中,工具白名单是逐层收窄的:
Command层能看到Agent和Skill,但不能直接调用Bash和WebFetch;
Agent层能访问Read和Skill,但不能直接执行Bash;
Skill层权限才精确到WebFetch(*)或Write(*)这样的单个操作。
这个权限收窄原则,在settings.json里也能直接套用——你可以给不同agent配置不同的allowed-tools,确保它们只做设计范围内的事。而settings.json的deny列表,就是全局底线——无论哪一层都不能越过。
Part 2: CLAUDE.md——让Claude Code一启动就懂你的项目
它应该写什么
CLAUDE.md是Claude Code启动时加载的指令文件。它可以有多个(从祖先目录往下读取),但项目根目录那个是核心。一份好的CLAUDE.md,通常不超过200行,只写三样东西:
1. Claude不会知道但必须知道的。 技术栈、命令、项目约定——这些是你项目特有的,Claude的训练数据里大概率没有。
2. Claude知道但可能搞错的。 比如"用named export,不用default export"——Claude两种都会写,但你的项目只认一种。这是纠正默认行为,不是教它基础知识。
3. 绝对不能做的。 .env不能commit、database schema不能随便改、依赖不能随便加——这些是项目的"宪法",白纸黑字写清楚。
它不应该写什么
- 基础知识("React组件应该用hooks"——Claude本来就知道)
- 模糊建议("写出高质量的代码"——这句话没有任何约束力)
- 太长(超过200行Claude会开始忽略后面的内容)
实战模板:一个60行的CLAUDE.md
# 项目:[你的项目名]## 技术栈- Frontend: React 18, TypeScript 5, Vite- Backend: Node.js 22, Express, PostgreSQL, Prisma## 命令- Build: `npm run build`- Test: `npm test -- --coverage`(必须0 failure)- Lint: `npm run lint --fix`- Type check: `npx tsc --noEmit`## 代码约定- 函数组件 + hooks,不用class- named export,不用default export- 测试文件和源文件同级:Button.tsx → Button.test.tsx- commit message格式:`type(scope): description`## 边界- 永远不commit .env或secrets- 加依赖前先检查bundle size- 改database schema、CI配置前先问我- commit前必须跑测试和lint## 当前项目状态- 正在做的功能:用户认证重构(auth-v2分支)- 已知坑:auth.ts里有一段旧的JWT逻辑,本次重构不碰它
注意最后"当前项目状态"那段——这是CLAUDE.md里最容易被忽略但最有价值的部分。它告诉Claude"我们在做什么、有什么坑",避免它在你不在的时候自创方案。
Monorepo场景:祖先加载 + 后代加载
Claude Code会沿着目录树加载CLAUDE.md,有点像gitignore的继承策略:
你从 /monorepo/ 启动 Claude:自动加载:~/.claude/CLAUDE.md ← 全局规则/monorepo/CLAUDE.md ← 项目根(shared规则:git约定、CI流程)按需加载(碰到对应目录的文件时才加载):/monorepo/packages/frontend/CLAUDE.md ← 前端规则/monorepo/packages/backend/CLAUDE.md ← 后端规则
实战策略很简单:
根目录CLAUDE.md放跨项目的共享约定。
子目录CLAUDE.md放各模块特有的技术栈和patterns。
Claude处理前端代码时自动带上前端规则,处理后端时自动带上后端规则,互不污染。
Part 3: .claude/rules/——更细粒度的指令控制
CLAUDE.md够好用了,但有一个小问题——它没办法按文件类型做精细的控制。你在monorepo里可能希望"TypeScript文件有统一规范,但别影响其他文件"。
.claude/rules/目录 + paths: frontmatter就是专门解决这个问题的:
# .claude/rules/typescript.md---paths:- "src/**/*.ts"- "src/**/*.tsx"---## TypeScript规范- 优先使用interface而非type(除非需要union/intersection)- 函数参数超过3个时使用对象参数- 异步函数返回值始终用Promise<T>
这个文件只在Claude读取src/**/*.ts文件时才加载。处理Go、Python、配置文件时完全不占用context——这就是"懒加载"的用意。
什么时候用Rules而不是CLAUDE.md:当一条规则只对特定文件类型或目录生效时。全局规则放CLAUDE.md,文件级规则放Rules。
实战落地:你能直接拿走的东西
完整的settings.json模板
把下面内容保存到.claude/settings.json:
{"permissions": {"allow": ["Read(*)", "Edit(*)","Bash(npm test:*)", "Bash(npm run lint:*)", "Bash(npm run build:*)","Bash(git:status,diff,log,branch,add,commit:*)(!push !reset !rebase)"],"deny": ["Bash(rm -rf:*)", "Bash(git push --force:*)", "Bash(curl:*)"],"ask": ["WebFetch(*)", "Bash(npm install:*)", "Bash(npm publish:*)"]},"attribution": {"commit": ""}}
完整的CLAUDE.md模板
把上面那个60行模板保存到项目根目录CLAUDE.md就行。
Rules文件模板
mkdir -p .claude/rules
# .claude/rules/typescript.md---paths:- "src/**/*.ts"- "src/**/*.tsx"---## TypeScript规范[你的规范]
验证配置生效
# 1. 检查settings.json有无语法错误cat .claude/settings.json | python3 -m json.tool > /dev/null && echo "JSON valid"# 2. 重启Claude Codeclaude# 3. 验证CLAUDE.md被加载(Claude应该知道你的项目命令和约定)# 让它跑一下npm test——如果不需要你解释怎么跑,说明CLAUDE.md生效了
本文素材来源:shanraisshan/claude-code-best-practice
