
Claude Code用久了你会发现真正决定它“聪不聪明”的不是模型本身而是三个配置文件settings.json、CLAUDE.md、memory。这三个东西各管一摊但几乎所有配置混乱都来自没分清楚它们。拿我自己的例子来说一开始我把项目说明全塞进settings.json里结果它根本不读后来又把环境变量写进CLAUDE.md结果密钥跟着每次对话上下文到处走再后来发现它不知什么时候记住了我某次随口抱怨“记忆”里攒了一堆过期结论导致它在新代码里莫名其妙拒绝用某个库。这篇文章就把这三套体系完整拆一遍它们分别管什么、加载优先级怎么排、真实项目里怎么配、以及我踩过的坑。适合三类人看已经装上Claude Code但配置越改越乱的刚入门想在第一天就搭对体系的以及需要帮整个团队梳理Claude Code标准化的同学。1. 三大体系的分工边界能做什么、该怎么做、记住了什么很多人第一次接触Claude Code配置时最先碰到的是settings.json觉得它是个“万能配置入口”什么都想往里塞。其实这三个体系之间有明显分工理解这条分界线后面所有配置决策都会顺很多。1.1 settings.json工具行为的“系统设置面板”settings.json负责的是Claude Code“工具本身”的运行行为——权限边界、默认模型、环境变量、MCP服务、事件钩子、界面显示这些都属于它。它更像操作系统的设置面板而不是项目文档。你在这里写“这个项目是什么、代码风格怎样”它不会按文档的方式理解你因为它的职责是决定“Claude能调用哪些命令、能读写哪些文件、用哪个模型跑推理”。它分三个层级用户级全局配置、项目级共享配置、项目级本地私有配置。这三层的合并覆盖关系我在第二章细讲。1.2 CLAUDE.md项目上下文的“入职手册”CLAUDE.md是一份给AI看的项目说明文档每次新会话启动时Claude Code会自动把相关CLAUDE.md内容注入到上下文里。它的作用是让模型在动手前就知道这个项目用什么技术栈、怎么跑测试、目录怎么组织、有什么禁忌。你可以把它理解成给AI的入职手册。新人入职总得先看公司制度、项目背景、代码规范Claude也一样。没有CLAUDE.md的对话相当于让一个能力很强但完全不了解项目的工程师直接上手改代码他能干但大概率会按“通用最佳实践”来而不是按你项目的实际情况来。1.3 memory跨会话经验的“私人笔记”memory是Claude Code里最容易被忽视但后劲最大的一个体系。它存放在~/.claude/projects/目录下按项目路径隔离模型会在对话中自主判断哪些信息值得长期保留写入对应的记忆文件下次会话遇到相关话题时再自动读取。settings.json和CLAUDE.md都是你主动维护的memory却是模型自己维护的。这个区别极其重要因为它意味着memory的内容不一定是对的——模型判断“值得记”和“真实准确”是两码事。我见过不少项目问题恰恰出在模型记住了不该记的事情上这个坑放到第四章专门说。1.4 优先级别让三者打架这三个体系不是平级的。我用一个表格把它们的职责、维护方、生效时机说清楚维度settings.jsonCLAUDE.mdmemory管什么工具运行行为项目行为规范跨会话经验沉淀谁来维护开发者手写开发者手写或/init生成Claude自主读写作用范围全局或单个项目全局、项目、子目录按项目路径隔离生效时机会话启动时加载会话启动时注入模型判断需要时读取冲突时的表现权限配置硬性生效作为上下文参考上下文参考可能过时真正的执行优先级是这样的你在对话框里直接下达的指令最高其次是通过工具调用明确指定的文件再往下是CLAUDE.md和memory这类上下文信息settings.json里的权限配置反而更像“法律法规”决定了模型有没有资格执行某个动作。权限判断和上下文参考是两条线不要混在一起理解。举个例子你在CLAUDE.md里写了“不要删除dist目录”但模型还是尝试执行了删除命令最后是settings.json里的deny规则拦住了它。CLAUDE.md只是建议settings.json才是硬边界。2. settings.json 实操从权限白名单到MCP服务相比另外两个体系settings.json是最偏“技术配置”的一个也是出错后最让人摸不着头脑的一个。这章我按实际使用频率把每个配置项拆开讲。2.1 三个层级的配置文件与合并规则你最多会有三个settings.json同时存在用户级全局配置~/.claude/settings.json对你机器上所有项目生效适合放个人偏好的默认模型、全局权限、通用MCP。项目级共享配置项目根/.claude/settings.json跟着项目走可以提交到Git仓库适合放项目特定的MCP服务、hooks、团队统一的环境变量。项目级私有配置项目根/.claude/settings.local.json个人专用不要提交到版本库适合放个人偏好、本机路径、临时调试用的覆盖项。合并优先级是settings.local.json覆盖settings.json覆盖用户级settings.json。注意是“覆盖”不是“叠加”——如果项目级配置里写了某条权限用户级里同一条会被顶掉但不同配置项之间不存在冲突各自生效。我一开始在这个地方吃了亏把常用的读文件权限放在用户级项目级只写了一个permissions: {ask: [Write]}结果项目级配置整体把这个字段覆盖了用户级的allow规则对当前项目全部失效导致Claude干什么都要弹确认框。所以你在项目级写配置时要想清楚是“全量覆盖”还是“补充”字段一旦出现就会整体替换同名字段。2.2 高频配置项逐个拆解先给一份实际项目里比较完整的示例后面逐项解释{ permissions: { allow: [ Bash(npm run lint), Bash(npm run test), Read ], deny: [ Bash(rm -rf *), Write(git/*) ], ask: [ Write, Bash ] }, apiKeyHelper: env:ANTHROPIC_API_KEY, env: { NODE_ENV: development }, model: sonnet, mcpServers: { github: { command: npx, args: [-y, modelcontextprotocol/server-github], env: { GITHUB_PERSONAL_ACCESS_TOKEN: 你的token } } }, hooks: { PostToolUse: [ { matcher: Write|Edit, command: node scripts/check-format.js } ] } }permissions最核心的安全配置三个子项分别是allow直接允许、deny直接拒绝、ask执行前询问。规则可以精确到具体命令和参数比如Bash(npm run lint)就只允许执行这一条命令不带任何匹配符。我的经验是刚开始可以激进一点全allow跑熟了再收敛但生产环境的项目建议一开始就用白名单方式收敛。model默认使用的模型可以根据版本填opus、sonnet、haiku等也可以在会话里用/model临时切换。要注意启动时如果加了--model命令行参数它的优先级高于settings.json里的model字段。env注入到Claude Code子进程的环境变量适合放非敏感的开关比如NODE_ENV、CI这类。它不会设置到你的shell环境里只对Claude Code启动的子进程生效。mcpServersMCP服务配置等于给Claude外接“工具集”。比如上面示例里的github服务目的是让Claude能直接查仓库、开Issue、看PR。配置文件里的env字段就是给MCP服务本身用的环境变量。hooks事件钩子能在Claude执行工具的前后触发外部命令。比如PostToolUse匹配Write|Edit每次写完文件后自动跑一遍格式检查检查失败就会中断操作。这是做质量门禁最直接的手段。apiKeyHelper指定如何获取API密钥常见写法是env:ANTHROPIC_API_KEY意思是从环境变量里取。也可以指向一个自定义脚本从密钥管理服务里拉取。2.3 环境变量、密钥与安全边界密钥管理最容易出问题。我在第二章开头说过项目级settings.json是可以提交到Git的所以绝对不要在里面写真实密钥。正确做法是个人密钥放系统环境变量比如~/.zshrc或~/.bashrc里exportClaude Code会自动继承。项目内共享的非敏感配置才写进.claude/settings.json的env字段。需要给MCP服务用的敏感token优先走MCP服务自己的环境变量机制不要在settings.json里明文写。另外apiKeyHelper支持自定义脚本从远程密钥管理工具拉取团队场景下值得考虑能避免把密钥分发到每台开发机上。2.4 我在settings.json上踩过的三个坑第一个坑JSON格式错误导致整份配置失效。这个听起来基础但我和同事都踩过多一个逗号或少一个引号Claude Code不会给你报错提示而是直接不加载这份配置然后表现得“像没配过一样”。排查方式用python -m json.tool settings.json校验一下格式。第二个坑权限开太宽把“Bash”直接allow了。当时图省事允许了所有Bash命令结果Claude在修改代码时顺手执行了部署脚本虽然没出大事但足够吓人。后来改成精确到具体命令的白名单风险小了很多。建议至少把Bash(rm -rf *)、Bash(git push *)这类危险操作放进deny。第三个坑改了配置不重启新配置不生效。settings.json是会话启动时加载的你在运行中修改文件当前会话不会自动感知。记得改完执行/reload或重启Claude Code再用/config命令确认实际生效值。3. CLAUDE.md 的正确写法是给AI看的项目手册不是给人看的技术文档CLAUDE.md写得好不好直接影响Claude Code生成代码的贴切程度。很多人把它当成普通README写结果Claude读了一堆项目介绍却不知道你希望它遵守什么规范。这章我按“写什么、不写什么、怎么分层”来讲。3.1 为什么CLAUDE.md能显著影响生成质量Claude Code每次会话启动时会把相关CLAUDE.md注入上下文。上下文窗口有限因此这份文档的质量和长度直接决定了模型“从哪开始思考”。我做过一个对比测试同一个需求一个项目没有CLAUDE.md另一个项目有详细但精简的CLAUDE.md。没配的前者会按通用最佳实践写可能结构漂亮但和现有代码风格不一致配好的后者能直接沿用项目的命名规范、目录约定、异常处理方式Review时几乎不用怎么改。差别不是“写得好不好”而是“知不知道项目规矩”。从这个角度说CLAUDE.md本质上是在给模型“初始化思维”你希望它在动手前知道什么就写什么。3.2 必须写的内容清单与推荐结构我实践下来的推荐结构如下基本按信息密度从高到低排# 项目名称 ## 项目概述 两三句话说明项目做什么、面向谁。 ## 技术栈 列出主要语言、框架、关键依赖比如 Next.js 14 TypeScript Tailwind。 ## 常用命令 - dev: npm run dev - build: npm run build - test: npm run test - lint: npm run lint - 数据库迁移: npm run migrate ## 目录结构 只写关键目录的职责不要罗列所有文件 - src/appNext.js路由页面 - src/componentsUI组件 - src/lib业务逻辑与工具函数 - src/api接口层 ## 代码风格与约束 - 组件用函数组件 Hooks不用class - 命名文件名用kebab-case组件名用PascalCase - 样式一律用Tailwind不写CSS Modules - 不要修改 src/lib/api 下的生成代码 - 所有错误处理必须try/catch并返回错误码 ## 禁止做的事 - 不要删除public/assets下的静态资源 - 不要升级package.json里的锁版本每一栏都尽量用“可执行”的句子而不是描述性的“项目采用了组件化开发”。模型理解指令的方式偏字面你写得越像规则它执行得越准。3.3 千万别写进CLAUDE.md的东西至少四类内容不要进CLAUDE.md密钥和敏感信息CLAUDE.md会被注入每次会话上下文也容易被复制传播明文密钥放进去等于裸奔。频繁变化的信息比如“当前服务部署在哪个端口”“某个临时环境地址”今天写了明天就过期反而误导模型。所有文件清单目录结构只需要写关键目录模型需要找具体文件时会自己用工具去翻而不是靠你投喂。超过200行的长篇大论CLAUDE.md越长占用上下文越多留给真正工作内容的窗口就越少。如果项目规范确实很多优先精简成要点详细文档放在项目wiki里需要时再让模型去读文件。3.4 多级CLAUDE.md根目录、子目录与全局的搭配CLAUDE.md不只有项目根目录一份。它有三种存在位置职责不同项目根目录CLAUDE.md描述整个项目的全局约定所有会话都会参考。子目录CLAUDE.md比如src/components/CLAUDE.md当Claude在操作该子目录下的文件时会按需读取适合写这一层的局部约定比如“组件文件的默认导出结构”。用户级全局CLAUDE.md放在~/.claude/CLAUDE.md所有项目通用适合写你个人的代码风格偏好、常用工具链偏好。多个CLAUDE.md叠加时离当前工作目录越近的优先级越高。举个例子全局CLAUDE.md里写着“代码格式用prettier”子目录CLAUDE.md里写着“该模块代码格式用eslint-disable风格”Claude会倾向于参考更贴近当前目录的那份。我实际经验是全局CLAUDE.md保持精简只写“我这个人偏好什么”项目根目录CLAUDE.md写“这个项目是什么”子目录CLAUDE.md写“这部分代码有什么特殊规矩”。三层各司其职不要试图一份文件解决所有问题。创建项目CLAUDE.md最快的方式是用/init命令它会扫描项目结构和文件生成一份初稿你再手工删改。比从白纸写起省不少事。4. memory让Claude越用越懂你但也可能“记错事”memory是Claude Code里最像“人”的一部分它会自己记笔记、自己做总结。但既然是模型自己做判断就会有判断偏差。这章讲清楚它的机制以及怎么防止它记错事。4.1 memory文件到底存在哪里memory的根目录是~/.claude/projects/下面是按项目路径生成的目录。每个项目的目录会命成一个类似路径哈希的字符串不容易直接认出是哪个项目但你可以用/memory命令在当前项目中打开对应的memory目录不用自己去找。目录里放着一堆.md文件文件名大致分两类_global_xxx.md跨项目的全局记忆和具体项目无关。项目标识_xxx.md针对当前项目的记忆按写入时间或主题命名。这些文件都能直接打开、编辑、删除。它本质上是普通Markdown只是由Claude Code按规则维护。4.2 memory的自主读写机制何时写入、何时读取模型不会把所有对话都写进memory它有自己的一套判断逻辑。从实际行为来看大致是这几类信息会被写入你明确表达偏好的内容比如“这个项目不要用Prettier用ESLint自带的格式化”。项目里反复出现的模式比如“接口返回格式统一是{code, data, message}”。你纠正过它的错误比如“之前生成的登录鉴权方式不对应该走session加cookie”。新会话开始时模型会先扫描当前项目的memory目录判断哪些文件与本次任务相关再把相关文件读进上下文。当它引用了某条记忆还可能会更新记忆文件里的时间戳或补充新细节形成类似“复习”的机制。这整个读写过程都不是你主动控制的是模型自主决定。好处是省心风险是它可能记错。4.3 记忆污染最常见的慢性问题我在一个项目里碰到过这个问题项目早期我随口说了一句“这个模块的代码风格不太行别按它的写法写”当时只是想让它别模仿旧代码。结果模型把这句话写进了memory之后整个项目里只要涉及类似功能它都拒绝参考那个模块的实现哪怕后来那个模块已经重构好了。这就是典型的“记忆污染”——把一次性的临时反馈记成了长期规则。另一种常见污染是“结论过期”。比如Claude在某个时间点发现项目里某个依赖版本过老写了“不要使用xx库的新特性”后来依赖升级了这条记忆还是留着导致它在新版本环境下也不敢用新特性。所以说memory和CLAUDE.md有个本质区别CLAUDE.md是你明确写下的规则memory是模型猜出来的规则。猜测自然会出错所以memory必须定期清理。4.4 memory清理实操清理手段不复杂用/memory命令在当前会话中列出memory目录和文件直接打开、编辑、删除。定期检查我现在的习惯是一到两周检查一次memory目录看有没有明显过期的条目。遇到可疑记忆当场处理如果发现模型引用了你根本没说过的“偏好”立刻让它打开对应的memory文件把那条删掉。项目重构后主动清理目录结构、技术栈变了旧memor大概率全是废料干脆清空重建。另一个实用技巧某些记忆不去删除而是利用它校正行为。比如你正在做一个短期任务希望Claude忽略某条历史记忆可以在对话里明确说“临时忽略memory里关于xxx的规则”这次会话的记忆读取会受影响但不会删除文件。临时覆盖和永久删除两条路都能走。5. 三个体系协作实战从0到1搭一套干净的分层配置前面四章都是拆开讲最后合起来看它们怎么配合。配置的关键不是三套都堆满而是“静态配置下沉动态经验上浮”——越稳定的越放在底层越易变动的越放在上层。5.1 设计思路静态配置下沉动态经验上浮我搭配置的顺序固定是这样用户级settings.json只放个人默认比如默认模型、全局权限白名单、全局MCP。用户级CLAUDE.md写个人风格的通用偏好所有项目共享内容控制在十几条以内。项目级settings.json放项目特定的MCP服务、hooks、团队统一的环境变量入库共享。项目级CLAUDE.md放项目技术栈、目录结构、常用命令、代码约束、禁止事项。子目录CLAUDE.md只在有特殊局部约定时创建。memory不主动写让它自然沉淀定期检查清理。这个顺序有个好处越靠上的配置越少被修改越靠下的配置可以随时调整而不会影响全局。你不需要在每次新项目启动时重新设计整套体系只需要拷贝项目级模板改技术栈和命令部分即可。5.2 可直接抄作业的配置模板下面这份是我现在每个新项目的起点。项目级settings.json{ permissions: { allow: [ Read, Bash(npm run lint), Bash(npm run test), Bash(npm run build), Bash(git status), Bash(git diff) ], deny: [ Bash(rm -rf *), Bash(git push *) ], ask: [ Write, Edit ] }, env: { NODE_ENV: development }, hooks: { PostToolUse: [ { matcher: Write|Edit, command: npm run lint:fix } ] } }项目级CLAUDE.md模板# 项目名称 ## 项目概述 一句话。 ## 技术栈 Next.js 14 / TypeScript / Tailwind CSS / Prisma ## 常用命令 - dev: npm run dev - build: npm run build - test: npm run test - lint: npm run lint ## 目录结构 - app/路由页面 - components/UI组件 - lib/业务逻辑 - prisma/数据库模型与迁移 ## 代码约束 - 组件用函数组件不用class - 命名组件PascalCase文件kebab-case - 样式统一Tailwind不写CSS Modules - 接口错误统一返回 { code, message } ## 禁止 - 不修改 lib/api 下的生成代码 - 不升级package.json中的锁版本用/init生成初稿再改成这份模板速度最快。钩子那部分根据自己的项目灵活改没有就删掉。5.3 配置不生效的排错链路如果Claude Code表现得像没读过配置按下面顺序排查能解决九成以上问题检查文件位置配置文件放错了层项目级写到了用户级或者反过来都会产生“好像生效了又好像没生效”的奇怪行为。校验JSON格式用python -m json.tool 文件或任意JSON格式化工具确保语法没坏。重启会话配置在会话启动时加载运行中改配置不会热更新。执行/reload或重启Claude Code。用 /config 查看生效值这个命令会把当前生效的配置项和来源用户级/项目级/本地级列出来能直接看到覆盖关系是不是出了问题。检查命令行参数比如启动时用了--model sonnet它会覆盖settings.json里的model字段这时候你改settings是没用的。开debug日志以claude --debug模式启动查看配置文件加载过程定位哪一步没读进来。这套流程我走了很多遍最快一次定位到问题只花了三分钟基本就是JSON里一个多余逗号。5.4 进阶玩法hooks与团队资产化最后说点进阶的。settings.json里的hooks其实是个被低估的功能它能把Claude Code和你们团队的现有工具链绑在一起。比如PostToolUse匹配Write|Edit每次自动跑lintlint不过就中断操作等于给AI生成代码加了一道强制检查。PreToolUse匹配Bash在执行部署类命令前弹出确认或直接拦截。Notification在任务开始时推送消息到团队IM。团队资产化方面我的建议是.claude/settings.json和根目录CLAUDE.md入库团队共享作为项目代码库的一部分。.claude/settings.local.json加入.gitignore个人偏好不入库。memory目录天然不入库它属于个人和本机团队成员各自维护自己的。可以再补一份.claude/commands/目录把团队常用的自定义斜杠命令也入库比如/review、/deploy-check让所有成员用同一套流程。这样搭下来Claude Code对一个团队来说就不再是“某个人的AI助手”而是一套有边界、有规范、可以复用的工程化工具。最后分享一个我自己的习惯新项目落地时先只配CLAUDE.md和权限白名单等真正用起来发现哪里别扭再补MCP和hooks不要一开始就堆满配置。memory我固定两周检查一次防止积攒过期结论。另外每次升级Claude Code版本后我都会用/config看一眼当前生效配置确认没有因为版本更新产生意外变化。配置这种东西最怕的不是少而是旧。我遇到的绝大多数“Claude Code不听话”的问题最后都指向同一件事配置文件里有内容已经过时了而Claude在忠实地执行。所以定期清理、保持精简比任何花哨的配置技巧都管用。