1. 三个配置文件到底谁管什么:先把职责边界划清楚
很多人第一次接触 Claude Code 的配置体系时,最容易犯的错就是把settings.json、CLAUDE.md和 memory 当成"三个差不多的东西",随便往哪个里面塞内容。结果就是:明明写了规则,Claude 就是不遵守;明明配了权限,命令还是被拦;明明记了偏好,下次对话又忘了。问题的根源不在于配置写错了,而在于放错了地方。
我先把这三者的本质区别用一句话讲透:
settings.json管的是"工具和环境"——它决定 Claude Code 这个程序本身怎么运行,能碰哪些文件、能跑哪些命令、用哪个模型、走哪个 API 端点。它是给程序看的。CLAUDE.md管的是"项目规矩"——它告诉 Claude 在这个代码库里应该怎么写代码、遵循什么风格、避开哪些坑。它是给当前项目上下文看的。- memory 管的是"跨会话记忆"——它记录你个人的偏好、习惯、长期有效的事实,让 Claude 在不同会话、不同项目之间都能记得你。它是给你这个人看的。
这三者的作用域是层层放大的:settings.json是机器级/项目级,CLAUDE.md是项目级,memory 是用户级。理解了这个层级关系,后面所有的配置决策都会变得顺理成章。
1.1 为什么不能混着放:一个真实的翻车案例
我见过一个很典型的场景。有位朋友想让 Claude 在每次生成代码时都用 2 空格缩进,他把这条规则写进了settings.json的某个自定义字段里,然后发现完全不起作用。原因很简单——settings.json的 schema 是固定的,你塞进去的未知字段会被直接忽略,Claude 根本读不到。
正确的做法是:缩进风格属于"项目代码规范",应该写进CLAUDE.md。而如果你希望所有项目都用 2 空格缩进,那应该写进 memory,因为它是你的个人偏好,跨项目生效。
再举一个例子。有人想限制 Claude 不能执行rm -rf这类危险命令,他写进了CLAUDE.md说"请不要执行删除命令"。这其实是个软约束——Claude 大部分时候会遵守,但它本质上只是上下文里的一句话,不是硬性拦截。真正要硬性拦截,得在settings.json的permissions里配置deny规则。这就是"软规矩"和"硬权限"的区别。
记住一个判断口诀:能拦住程序的写 settings.json,能指导写代码的写 CLAUDE.md,能跨项目记住你的写 memory。
1.2 三者的加载顺序与优先级
Claude Code 启动时的加载逻辑大致是这样的:先读用户级的settings.json(通常在~/.claude/settings.json),再读项目级的settings.json(项目根目录下的.claude/settings.json),项目级会覆盖用户级的同名配置。然后加载 memory 文件,最后把当前项目的CLAUDE.md注入到系统提示里。
这个顺序很重要,因为它决定了冲突时谁说了算。比如你在用户级 settings 里设了默认模型是 A,项目级设了模型是 B,那在这个项目里就用 B。而CLAUDE.md和 memory 之间不存在"覆盖"关系,它们是叠加注入的,内容都会出现在上下文里。如果两者有矛盾,Claude 通常会倾向于更具体、更靠近当前任务的那一条,但这个行为并不绝对可靠,所以尽量不要让 memory 和 CLAUDE.md 出现直接冲突。
| 配置类型 | 典型路径 | 作用域 | 生效方式 | 适合放什么 |
|---|---|---|---|---|
| settings.json(用户级) | ~/.claude/settings.json | 所有项目 | 程序读取,硬性生效 | 默认模型、API 端点、全局权限 |
| settings.json(项目级) | <项目>/.claude/settings.json | 当前项目 | 覆盖用户级 | 项目专属权限、环境变量 |
| CLAUDE.md | <项目>/CLAUDE.md | 当前项目 | 注入上下文 | 代码规范、架构说明、禁忌事项 |
| memory | ~/.claude/下的记忆文件 | 所有项目 | 注入上下文 | 个人偏好、沟通习惯、长期事实 |
这张表建议你直接截图存下来,配置的时候对着看,能省掉大量试错时间。
2. settings.json 的字段拆解:哪些能改,哪些改了会出事
settings.json是三者里最"硬"的一个,因为它直接控制程序行为。但也正因为如此,它的 schema 最严格,写错字段名或者写错类型,轻则被忽略,重则导致 Claude Code 启动异常。我下面按功能模块拆开讲,每个字段都说明它解决什么问题、怎么配、有什么坑。
2.1 模型与端点配置:本地模型接入的关键
最常被改的就是模型相关配置。默认情况下 Claude Code 走官方端点,但很多人希望接入本地模型或者其他兼容端点,这时候就要动env字段。典型写法是这样:
{ "env": { "ANTHROPIC_BASE_URL": "http://localhost:1234", "ANTHROPIC_API_KEY": "your-key-here", "ANTHROPIC_MODEL": "your-model-name" } }这里有几个实操细节值得说。第一,ANTHROPIC_BASE_URL指向的端点必须兼容 Anthropic 的消息格式,不是随便一个 OpenAI 兼容端点就能直接用,很多本地推理框架需要额外的适配层。第二,ANTHROPIC_API_KEY如果本地服务不校验,随便填一个非空字符串即可,但不能留空,否则客户端可能直接报错。第三,模型名称要和你本地实际加载的模型标识完全一致,大小写都别错。
提示:改完
env之后一定要重启 Claude Code,环境变量是在进程启动时读取的,热改不生效。
我踩过的一个坑是:把ANTHROPIC_BASE_URL写成了带路径的形式(比如http://localhost:1234/v1),结果请求全部 404。后来才发现客户端会自己在后面拼/v1/messages,所以 base url 只需要写到域名和端口就够了。这个细节官方文档里没明说,但实测就是这样。
2.2 权限系统:allow / deny / ask 三档怎么用
权限配置是settings.json里最有价值的部分,也是最能体现"硬约束"的地方。它分三档:
allow:白名单,列出的操作直接放行,不再询问。deny:黑名单,列出的操作直接拒绝,Claude 连尝试的机会都没有。ask:灰名单,列出的操作每次都要你手动确认。
配置格式大致如下:
{ "permissions": { "allow": [ "Bash(npm run test:*)", "Bash(git status)", "Read(//src/**)" ], "deny": [ "Bash(rm -rf:*)", "Bash(curl:*)", "Read(./.env)" ], "ask": [ "Bash(git push:*)" ] } }这里的匹配语法是工具名(参数模式),支持通配符。几个经验点:
第一,deny的优先级最高,一个操作只要命中 deny,无论 allow 里怎么写都会被拒。所以别把同一个模式同时写进 allow 和 deny,那样只会以 deny 为准。
第二,Read(./.env)这类敏感文件一定要放进 deny,防止 Claude 在探索代码库时不小心把你的密钥读进上下文。这是安全底线。
第三,Bash(git push:*)放 ask 是个好习惯。push 是少数几个"一旦执行就难以撤销"的操作,让它每次确认一下,能避免很多手滑。
第四,通配符:*表示"这个命令后面跟任意参数"。如果你只写Bash(git),那只有裸的git命令会匹配,git status不会命中。这个细节很多人搞错。
2.3 环境变量与工具开关
除了模型和权限,settings.json还能控制一些行为开关。比如是否启用自动更新、是否收集遥测、默认的编辑器行为等。这些字段相对冷门,但有几个值得关注:
- 和终端执行相关的开关,决定 Claude 能否直接跑命令,还是必须先征求同意。
- 和文件监听相关的配置,影响它感知项目变化的速度。
- 和输出格式相关的设置,影响日志详细程度,排查问题时很有用。
我的建议是:不要一次性把所有字段都配上。先跑起来,遇到具体需求再针对性添加。配置越多,出问题的面越大,而且很多字段的默认值其实已经调得不错了。
2.4 项目级 settings 的覆盖陷阱
项目级.claude/settings.json会覆盖用户级,但覆盖是按字段而不是按整个文件。也就是说,如果项目级只写了permissions,那用户级的env依然生效。这个机制很合理,但有个坑:数组类型的字段(比如allow列表)通常是整体替换而不是合并。你在用户级 allow 里放了一堆常用命令,项目级又写了一个 allow,结果用户级那些全没了。
解决办法是要么在项目级把需要的都写全,要么干脆把通用规则都放用户级,项目级只写项目特有的。我个人的习惯是:用户级放通用白名单,项目级只放 deny 和项目专属的 allow,这样冲突最少。
3. CLAUDE.md 的写法:让 Claude 真正读懂你的项目
如果说settings.json是给程序看的说明书,那CLAUDE.md就是给 Claude 看的"项目入职手册"。它的质量直接决定了 Claude 在你项目里的表现——写得好的CLAUDE.md能让 Claude 像一个熟悉项目的老员工,写得差的就只是个会写代码的陌生人。
3.1 该写什么:从"项目地图"到"行为准则"
CLAUDE.md的内容可以分成几个层次,我按重要性排序:
第一层是项目地图。用几句话讲清楚这个项目是干什么的、目录结构怎么组织、核心模块在哪。这能帮 Claude 快速定位代码,而不是盲目地全库搜索。比如:
## 项目结构 - `src/api/` 所有 HTTP 接口,使用 Fastify 框架 - `src/core/` 业务逻辑,不依赖任何框架 - `src/db/` 数据库访问层,使用 Prisma - `tests/` 测试文件,与 src 目录结构镜像对应第二层是技术栈和约定。用了什么语言、什么框架、什么版本、什么包管理器。这些信息能避免 Claude 给出过时的写法。比如你用的是 React 18 的函数组件,就明确写出来,别让它给你生成 class 组件。
第三层是行为准则。这是最有价值的部分,包括:代码风格(缩进、命名、注释语言)、提交规范、测试要求、禁止事项。比如"所有新功能必须带单元测试""不要修改generated/目录下的文件""提交信息用中文"。
第四层是常见任务的执行方式。比如"跑测试用npm test""构建用npm run build""本地启动用npm run dev"。把这些命令写清楚,Claude 就不会瞎猜。
3.2 不该写什么:三个常见的过度配置
很多人写CLAUDE.md容易走两个极端,要么太简略,要么太啰嗦。我重点说说"太啰嗦"的三种典型:
第一种是把整个 README 复制过来。README 是给人看的,里面有大量安装步骤、背景介绍、贡献指南,这些对 Claude 写代码没帮助,反而占用宝贵的上下文窗口。CLAUDE.md应该只保留和"写代码"直接相关的信息。
第二种是把详细的 API 文档贴进去。接口文档动辄几千行,全塞进去会让上下文爆炸。正确做法是告诉 Claude"接口定义在docs/api.md,需要时去读",而不是把内容直接内联。
第三种是写一堆"正确的废话"。比如"请写出高质量的代码""注意代码可读性""遵循最佳实践"。这些话没有任何可操作性,Claude 看了等于没看。要写就写具体的,比如"函数不超过 50 行""避免嵌套超过 3 层""所有异步操作必须处理错误"。
一个判断标准:如果一条规则你自己都没法判断有没有被遵守,那它就不该写进 CLAUDE.md。
3.3 分层组织:用标题和列表提升可读性
CLAUDE.md是 Markdown 文件,善用标题层级能让 Claude 更容易抓重点。我的建议是控制在两级标题以内,每个标题下用列表而不是长段落。原因很简单:列表的每一条都是独立的指令,Claude 解析起来更清晰;长段落里的信息容易被淹没。
一个实用的结构模板是这样的:
# 项目说明 (一段话讲清楚项目是什么) # 技术栈 - 语言:TypeScript 5.x - 框架:Next.js 14(App Router) - 样式:Tailwind CSS - 测试:Vitest # 目录约定 - `app/` 路由和页面 - `components/` 可复用组件 - `lib/` 工具函数 # 编码规范 - 使用函数组件和 Hooks,不用 class - 组件文件名用 PascalCase - 工具函数用 camelCase - 所有导出必须有 JSDoc 注释 # 常用命令 - 开发:`npm run dev` - 测试:`npm test` - 构建:`npm run build` # 禁止事项 - 不要修改 `app/generated/` 下的文件 - 不要引入新的依赖,除非明确要求 - 不要提交 `.env` 文件这个模板大概 40 行,覆盖了核心信息,又不至于臃肿。你可以根据项目复杂度增减,但尽量控制在 100 行以内,超过这个量级就要考虑拆分或者精简了。
3.4 让 CLAUDE.md 真正生效的三个技巧
写完CLAUDE.md不代表就完事了,还得确保它被正确加载和遵守。三个实操技巧:
技巧一:放在项目根目录。Claude Code 默认会从当前工作目录向上查找CLAUDE.md,放在根目录最稳妥。如果你在子目录里工作,它也能找到上层的,但根目录是约定俗成的位置。
技巧二:用祈使句而不是陈述句。"使用 2 空格缩进"比"本项目使用 2 空格缩进"更有效,因为前者是明确的指令。
技巧三:定期回顾和更新。项目在演进,CLAUDE.md也要跟着改。我一般每个迭代结束会花五分钟扫一遍,把过时的规则删掉,把新踩的坑补进去。这个习惯能让CLAUDE.md一直保持"活"的状态。
4. memory 机制:跨会话记住你的个人偏好
memory 是三者里最容易被忽视、但长期收益最高的一个。settings.json和CLAUDE.md都是"项目绑定"的,换个项目就失效;而 memory 是跟着你这个人走的,无论你在哪个项目、哪个会话,它都能让 Claude 记得你的习惯。
4.1 memory 和 CLAUDE.md 的本质区别
很多人会问:既然CLAUDE.md也能写偏好,为什么还要 memory?关键在于作用域和持久性。
CLAUDE.md是项目文件,会跟着代码库走。如果你把个人偏好写进去,同事拉下代码也会看到,这显然不合适。而且换个项目,这些偏好就没了。
memory 是存在你本地的用户级配置,不进入代码库,跨项目生效。它适合放那些"只关于你、和具体项目无关"的信息。比如:
- 你习惯用中文交流,希望 Claude 也用中文回复
- 你喜欢简洁的回答,不要长篇大论的解释
- 你偏好函数式编程风格
- 你常用的技术栈和版本
- 你希望 Claude 在改动代码前先说明计划
这些内容放进 memory,一次配置,处处生效。
4.2 什么内容值得进 memory:三个筛选标准
memory 不是越多越好,塞太多会让每次对话的上下文都变重,而且过时的记忆反而会误导 Claude。我用三个标准来筛选:
标准一:长期有效。这条信息半年后还成立吗?如果只是当前项目的临时需求,那不该进 memory。比如"这个月我在学 Rust"就不适合,但"我主要用 TypeScript 和 Python"就适合。
标准二:跨项目通用。这条信息在换项目后还有意义吗?如果只在特定项目成立,那应该写进CLAUDE.md。比如"我们团队用 GitLab"是跨项目的,"这个项目用 Jest"是项目级的。
标准三:可操作。这条信息能指导 Claude 的具体行为吗?"我喜欢优雅的代码"太虚,"函数优先于类"才具体。
按这三个标准筛下来,真正该进 memory 的内容其实不多,通常十几条就够了。少而精,比多而杂有效得多。
4.3 memory 的更新与维护:别让它变成垃圾场
memory 最大的风险是"只增不减"。用久了之后,里面堆满了各种过时的偏好,Claude 每次都要读一遍,既浪费上下文又可能产生冲突。我的维护习惯是:
每月清理一次。翻一遍所有记忆条目,问自己"这条现在还成立吗"。不成立的直接删,模糊的改具体。
冲突及时合并。如果发现两条记忆互相矛盾(比如一条说"用分号",另一条说"不用分号"),立刻合并成一条明确的规则。
重要信息前置。memory 的读取也是有顺序的,越靠前的内容越容易被重视。把最核心的偏好放在最前面。
一个实用技巧:给每条 memory 加一个"添加日期"的备注。这样清理的时候一眼就能看出哪些是陈年老账,哪些是最近才加的。
4.4 memory 与 CLAUDE.md 的协同:分工而非重复
理想状态下,memory 和CLAUDE.md应该是互补的,而不是重复的。我的分工原则是:
- memory 放"我是谁":我的技术背景、沟通偏好、通用工作习惯。
- CLAUDE.md 放"这个项目是什么":项目结构、技术栈、编码规范、禁忌事项。
举个例子。假设你是个偏好函数式编程、喜欢简洁回复的开发者,同时在一个用 React 的项目里工作。那么:
- memory 里写:"偏好函数式风格,避免可变状态;回复简洁,不需要过多解释。"
CLAUDE.md里写:"本项目用 React 18 + TypeScript,组件用函数式写法,状态管理用 Zustand。"
这样 Claude 在任何项目里都知道你的个人风格,进入这个项目后又知道具体的技术约束。两者叠加,效果最好。
如果发现某条规则在两个地方都写了,那说明它可能放错了位置。要么它是个人偏好(该只在 memory),要么它是项目规范(该只在CLAUDE.md)。重复不会加强效果,只会增加维护成本。
5. 三套配置的联动实战:从零搭一个顺手的开发环境
讲了这么多理论,最后用一个完整的场景把三者串起来。假设你要在一个新的 TypeScript 项目里配置 Claude Code,让它既安全又高效,还符合你的个人习惯。
5.1 第一步:先配 settings.json 打好安全底座
先创建用户级的~/.claude/settings.json,把通用的安全规则和偏好设好:
{ "permissions": { "deny": [ "Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)", "Bash(rm -rf:*)", "Bash(curl:*)", "Bash(wget:*)" ], "ask": [ "Bash(git push:*)", "Bash(git reset --hard:*)" ], "allow": [ "Bash(git status)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(npm run test:*)", "Bash(npm run lint:*)" ] } }这一层的核心目的是兜底。敏感文件读不了,危险命令跑不了,常用只读命令免确认。配完之后,无论你在哪个项目,基本的安全边界都有了。
然后在项目里创建.claude/settings.json,只加项目特有的:
{ "permissions": { "allow": [ "Bash(npm run dev)", "Bash(npm run build)", "Bash(npx prisma:*)" ] } }注意这里没有再写 deny,因为用户级的 deny 已经生效了,项目级不需要重复。
5.2 第二步:写 CLAUDE.md 给项目建立上下文
在项目根目录创建CLAUDE.md,按前面讲的四层结构来写。重点是把项目特有的信息写清楚,通用的个人偏好留给 memory。
# 项目说明 一个基于 Next.js 14 的内容管理后台,支持多租户。 # 技术栈 - TypeScript 5.3,严格模式 - Next.js 14 App Router - Prisma + PostgreSQL - Tailwind CSS + shadcn/ui - Vitest 做单元测试 # 目录约定 - `app/` 路由和页面组件 - `components/ui/` 基础 UI 组件(来自 shadcn) - `components/features/` 业务组件 - `lib/` 工具函数和配置 - `prisma/` 数据库 schema 和迁移 # 编码规范 - 组件用函数式,不用 class - 服务端组件优先,需要交互才加 'use client' - 所有数据库操作走 Prisma,不写原生 SQL - 错误处理用 Result 类型,不抛异常 - 提交信息用中文,格式:类型(范围): 描述 # 常用命令 - 开发:`npm run dev` - 测试:`npm test` - 迁移:`npx prisma migrate dev` - 生成客户端:`npx prisma generate` # 禁止事项 - 不要修改 `components/ui/` 下的文件,那是 shadcn 生成的 - 不要直接操作数据库,一律通过 Prisma - 不要在客户端组件里引入服务端代码这份CLAUDE.md大概 35 行,信息密度很高,Claude 读完就能对项目有清晰认知。
5.3 第三步:用 memory 固化个人习惯
最后在 memory 里加上你的个人偏好。这些内容不进入代码库,只影响你自己的使用体验:
- 用中文回复,技术术语保留英文
- 回答简洁,先给结论再给理由
- 改动代码前先说明计划,等我确认
- 偏好函数式风格,避免可变状态和副作用
- 代码注释用中文,变量名用英文
- 遇到不确定的地方主动提问,不要瞎猜
这几条配好之后,你在任何项目里用 Claude Code,它都会按这个风格和你协作。不用每次重新交代,省心很多。
5.4 联动效果与常见冲突排查
三套配置都到位后,一个典型的交互流程是这样的:Claude 启动时读取用户级 settings 建立安全边界,读取项目级 settings 加载项目权限,注入 memory 了解你的偏好,注入CLAUDE.md了解项目上下文。然后你让它改一个功能,它会先说明计划(memory 生效),用函数式风格写代码(memory 生效),遵循项目的目录约定(CLAUDE.md生效),跑测试时自动放行(settings 生效),但 push 前会问你(settings 生效)。
如果发现某条规则没生效,按这个顺序排查:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 权限规则不生效 | 字段名拼错或路径不对 | 检查 JSON 语法,确认路径是相对项目根 |
| 项目规范没遵守 | CLAUDE.md 没被加载 | 确认文件在项目根目录,重启会话 |
| 个人偏好丢失 | memory 没保存或冲突 | 检查 memory 内容,看是否有矛盾条目 |
| 配置改了没反应 | 需要重启进程 | 关闭并重新启动 Claude Code |
排查的核心思路是:先确认配置有没有被读到,再确认有没有被覆盖,最后确认内容本身对不对。大部分问题都出在第一步——文件放错位置或者 JSON 写错了。
6. 几个容易踩的坑和长期维护建议
最后分享几个我在长期使用中总结的坑,都是文档里不太会提但实际很常见的。
坑一:JSON 里写注释。settings.json是严格的 JSON,不支持注释。很多人习惯性加//说明,结果整个文件解析失败,所有配置静默失效。要写说明就单独放个 README,别往 JSON 里塞。
坑二:路径写绝对路径。CLAUDE.md和项目级 settings 里的路径尽量用相对路径,绝对路径换台机器就失效了。特别是团队协作时,绝对路径会直接坑到同事。
坑三:memory 里写项目信息。我见过有人在 memory 里写"当前项目用 Vue",结果换个 React 项目后 Claude 还在推荐 Vue 写法。项目信息一定要放CLAUDE.md,memory 只放跨项目的个人偏好。
坑四:deny 写太宽。有人为了安全把Bash(git:*)整个 deny 了,结果 Claude 连git status都跑不了,每次都要手动确认。deny 要精准,只拦真正危险的操作。
坑五:CLAUDE.md 长期不更新。项目重构了、换框架了、改规范了,CLAUDE.md还原封不动,Claude 就会按过时的规则干活。建议把更新CLAUDE.md纳入代码评审清单,改架构的时候顺手改一下。
关于长期维护,我的建议是建立一个简单的节奏:每周花十分钟回顾 memory,每月花半小时整理 CLAUDE.md,每次大重构后检查 settings 的权限是否还合适。这个投入不大,但能让你的 Claude Code 一直保持在一个"顺手"的状态。配置这东西,一次配好不难,难的是持续维护。把它当成项目的一部分来对待,收益会远超预期。