ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Claude Code配置三件套:settings.json、CLAUDE.md与memory的边界与实战

Claude Code配置三件套:settings.json、CLAUDE.md与memory的边界与实战 1. 配置体系全景三个文件各管哪一块接触过 Claude Code 的人十有八九都会经历这样一个阶段安装跑通之后立刻开始折腾配置。网上教程零零散散今天看到有人改 settings.json 解决了权限弹窗明天看到有人说 CLAUDE.md 能让代理更懂项目后天又听说 memory 可以实现跨会话记忆。三样东西搅在一起很容易把配置改成一锅粥。我自己的经历也差不多。最早我把所有想让它记住的东西全往 CLAUDE.md 里塞项目迭代几轮之后这个文件越来越臃肿每次会话开始都要读一大段背景信息真正关键的操作指令反而被稀释掉。后来踩了几次坑才慢慢摸清楚这三个文件解决的是完全不同层面的问题理解边界之后配置才谈得上是一个体系。1.1 三者的核心边界程序配置、项目指令、知识沉淀先说结论。settings.json 管的是Claude Code 这个程序怎么运行CLAUDE.md 管的是Claude 进入某个代码库时该懂什么规矩memory 管的是跨会话要记住什么信息。三者生命周期不同、维护方式不同、生效机制也不同。我用一张表把这个边界摊开来看配置文件本质谁来维护更新频率生命周期settings.json客户端配置使用者低频按需调整全局或单个项目CLAUDE.md项目指令说明人类编写随项目演化定期更新跟随项目长期有效memory 记忆文件动态知识沉淀Claude 与人类共同维护高频随会话积累跨会话保留需定期清理打个生活化的比方。settings.json 类似你手机里的系统设置决定的是工具本身的行为习惯CLAUDE.md 类似新员工入职时拿到的那本《团队手册》写清楚了这边的代码风格、发布流程、哪些雷区不能踩memory 则是你工位上的笔记本今天记一笔这个服务用 8080 端口明天补一句客户那边要求走内网域名随着工作推进不断增删。搞混三者的典型后果是什么把动态知识写进 CLAUDE.md会导致这个文件频繁变动每次改动都要提交、review效率极低把稳定规则写进 memory会导致规则在各种上下文里时隐时现今天有效明天可能就丢了而试图在 settings.json 里写业务约定那更是找错了地方。1.2 加载顺序与生效时机为什么我明明配了却不生效三个文件的加载机制差异很大这也是很多人困惑的源头。settings.json 在会话启动时读取修改后通常新的会话才生效CLAUDE.md 分全局、项目、子目录三层按需加载memory 则是在会话过程中按相关性动态载入并且可能在对话中被实时写入。具体来说settings.json 有两个层级全局配置在~/.claude/settings.json项目配置在项目根目录的.claude/settings.json。同名配置项项目级会覆盖全局级但覆盖粒度是按配置项合并不是整个文件覆盖。CLAUDE.md 的加载顺序是全局~/.claude/CLAUDE.md最先载入随后是项目根目录的CLAUDE.md当 Claude 实际访问某个子目录时才加载该目录下的CLAUDE.md。memory 一般存放在~/.claude/memory/和项目目录的.claude/memory/下启动会话或进入相关任务时Claude 会根据相关性挑选记忆文件读取。这里有一条可以解释 80% 配置问题的经验先判断你改的那个文件属于哪个加载层级再判断它是否在该生效的时机被读取。很多人改了项目级 settings.json 却发现所有项目都受影响是因为全局配置里同样的字段还留着旧值也有人把 CLAUDE.md 放进子目录却在项目根目录下对话自然读不到。2. settings.json项目环境的出厂设置2.1 配置位置与覆盖规则settings.json 是 Claude Code 的客户端配置文件承担的是类似 IDE 里 Preferences 的角色。最需要注意的就是它的两个存放位置以及它们的关系全局配置~/.claude/settings.json对当前用户的所有项目生效。项目配置.claude/settings.json项目根目录下只对当前项目生效。按配置项合并的意思是项目配置里写了permissions全局配置里的permissions不会整个被替换而是同名子项以项目为准项目没写的子项仍继承全局。这种做法比全量覆盖灵活得多但副作用就是排查问题时容易看漏。我建议在改动项目级配置之前先打开全局配置对照一遍避免出现两边互相打架的情况。值得一提的还有那些通过命令行工具切换第三方 API 的使用场景。无论是本地模型还是第三方中转服务本质上都是在修改最终传给客户端的模型标识和环境变量这些能力最终都会落到 settings.json 的env字段上。理解了这个文件的结构就能理解为什么那些切换工具能做到一次切换、全局生效。2.2 权限控制先学会划边界再谈效率权限配置是 settings.json 里价值最高、也最需要谨慎的部分。Claude Code 默认会对危险操作弹出确认这本来是保护机制但如果每次跑个git status都要确认一次体验确实很糟。合理的做法不是把权限全放开而是让安全的操作静默通过把真正危险的操作挡在门外。下面是我个人比较推荐的配置结构{ permissions: { allow: [ Read, Edit, Grep, Glob, Bash(bash:git status), Bash(bash:git diff), Bash(bash:git log), WebFetch(domain:docs.anthropic.com) ], deny: [ Write, Bash(bash:rm -rf /*), Bash(bash:git push --force) ], ask: [ Bash(bash:sudo *), Bash(bash:curl *) ] } }这里的逻辑是三层allow里的工具或命令模式直接放行deny里的一票否决ask里的仍然需要人工确认。我特别想强调的是 Bash 的写法——最好精确到命令前缀。你可以允许git status但不要去允许一个裸的Bash否则等于把终端完全交给了模型。等你哪天看到它自作主张执行了一条git push --force再想收紧就晚了。另一个实用技巧是会话中可以用/permissions命令查看当前生效的权限配置。排查某个工具怎么突然不能用的时候先看这里比瞎猜快得多。2.3 模型选择、环境变量与钩子settings.json 里除了权限还有三个高频配置项模型指定、环境变量注入、生命周期钩子。下面是一份完整的示例{ model: claude-sonnet-4-20250514, env: { ANTHROPIC_MODEL: claude-sonnet-4-20250514, ANTHROPIC_SMALL_FAST_MODEL: claude-haiku-4-20250514 }, hooks: { PreToolUse: [ { matcher: Bash, command: echo \即将执行 Bash 命令\ /tmp/claude_hook.log } ], PostToolUse: [ { matcher: Edit, command: echo \文件已被修改\ } ] } }先看model字段。它的作用是固定每次会话默认使用哪个模型避免在长对话中模型意外切换。配合ANTHROPIC_MODEL和ANTHROPIC_SMALL_FAST_MODEL这对环境变量可以同时控制主模型和轻量模型用于标题生成、短任务等的选型。如果你在本地部署了模型服务或者接了第三方兼容接口一般也是通过这里的环境变量来路由原理是一样的。再看 hooks 钩子。它允许你在 Claude 调用工具的前后插入自定义脚本常见的用途包括把每次工具调用写入审计日志、拦截特定命令并追加参数、任务结束时发送桌面通知。我建议第一次使用 hooks 时先打印日志确认触发时机和参数格式再逐步加固逻辑。注意hook 脚本执行失败不应阻断主流程所以脚本里要做好容错别因为一个 echo 命令写错路径导致整个会话报错。2.4 修改配置的生效与调试习惯settings.json 修改后一般不需要重启 Claude Code 进程新的会话就会按新配置执行但当前正在进行的会话通常会沿用启动时的配置。所以调试配置时建议开一个新的会话验证。我踩过最蠢的一个坑是手一抖把 JSON 里加了注释然后死活不生效。注意settings.json 是标准 JSON不是 JSONC不支持注释写//会导致解析失败。另一个高频问题是引号和中英文标点混用尤其是在中文输入法下编辑文件。建议改完配置后用编辑器自带的 JSON 格式化功能校验一遍再确认无红错。如果你需要跨机器同步配置我建议把项目级的.claude/settings.json纳入 Git 追踪。全局配置则不建议提交到代码仓库它通常包含本机特有的路径和环境变量属于个人环境的一部分。3. CLAUDE.md写给 Claude 看的项目说明书3.1 没有 CLAUDE.md 时Claude 有多没谱很多人第一次用 Claude Code 时感觉它能力很强但不太懂这个项目。这很正常——它做的是通用代码模型而每个项目都有自己的历史包袱、约定和潜规则。举个例子在一个 pnpm monorepo 里如果你不告诉它应该用 pnpm它可能默认就用 npm 安装依赖然后跑出各种版本冲突在一个发布前必须跑 lint的项目里你不告诉它这条规矩它可能改完代码直接提交把 CI 弄得一片红。CLAUDE.md 就是用来补上这些信息差的。它本质上是给 Claude 读的 Markdown 说明书会在会话启动时自动加载到上下文里告诉它这个项目是什么、怎么开发、怎么测试、有哪些禁忌。用一份好的 CLAUDE.mdClaude 的行为模式会立刻从通用编程助手切换成熟悉这个仓库的协作者。3.2 最值得写进 CLAUDE.md 的四类内容不是所有内容都值得写。写得太多、太碎反而会让模型抓不住重点。我归纳下来四类内容的性价比最高。第一类是项目概览与架构两三句话讲清楚这个仓库是做什么的、核心模块在哪、数据流大概长什么样。第二类是常用命令把启动、测试、构建、代码生成这些命令写全模型就不需要去猜。第三类是代码风格与约定比如命名规范、组件组织方式、是否强制使用 TypeScript 严格模式。第四类是已知的坑和禁止事项这部分的经验价值极高比如这个模块不要动重构计划还没定。给你看一个实际项目的 CLAUDE.md 骨架# 项目说明 电商后台管理系统前端 React TypeScript Vite后端 Node.js 服务在 server/ 目录。 ## 常用命令 - 安装依赖pnpm install - 启动前端pnpm dev - 运行测试pnpm test - 构建生产包pnpm build ## 代码约定 - 组件统一使用函数式组件 hooks - 新代码必须通过 TypeScript 严格检查 - 状态管理使用 zustand不要引入新的全局状态库 ## 已知问题 - legacy/ 目录是旧代码不要迁移后续会整体移除 - 修改数据库相关代码前先和 dba 确认变更脚本关键是要简洁。每个条目都应该是读了就能照做的操作级描述而不是口号式的自我要求。3.3 全局、项目、子目录三层文件的加载逻辑CLAUDE.md 不是只能有一份。它支持全局、项目根目录、子目录三个层级加载逻辑比较灵活~/.claude/CLAUDE.md全局规则适合放你的个人通用偏好比如所有代码用中文写注释提交信息必须用英文。项目根目录CLAUDE.md项目级规则上面说的四类内容一般放在这里。子目录CLAUDE.md当 Claude 实际操作到某个子目录时该目录下的 CLAUDE.md 才会被加载。适合放此目录专属的约束比如某个服务子目录有自己的部署流程。我建议保持全局文件极简因为全局内容会在每个会话中都占一份上下文。全局写得太多相当于每个项目都背着一大段无关背景既浪费上下文窗口也可能干扰项目特定指令。子目录文件也不要滥用只有在那个目录确实有独立规则时才值得单独维护一份。3.4 写了却不生效多半是这五个原因用户最常见的反馈是我写了 CLAUDE.md但它好像没读。排查下来原因基本集中在下面几个第一文件名或路径不对。注意是CLAUDE.md全部大写放在项目根目录不少人建成了claude.md或者放进了docs/目录。第二内容跑题。CLAUDE.md 是给模型读的不要在上面写给自己看的 TODO。第三和会话指令冲突。对话过程中明确下达的指令优先级高于文件里的静态规则所以你以为文件没生效其实是会话上下文压过了它。第四太冗长。几百行的 CLAUDE.md 里有效信息被淹没模型抓不住重点。第五你还没有让 Claude 主动读取。新版工具一般启动时按需加载但个别版本或场景下可能需要在对话中提示一下。如果你不确定怎么写最省事的做法是直接在项目根目录运行初始化命令让 Claude 自己读一遍代码库生成一份初始 CLAUDE.md你再在它基础上增删。比自己从零写快得多而且它生成的细节往往更贴合实际代码。4. memory跨会话记忆的工作机制与维护4.1 memory 到底在存什么memory 解决的是 上次聊过的内容下次开场就忘 的问题。它的价值不在于记住所有对话而在于把对话中产生的、对未来有复用价值的知识沉淀下来。适合放进 memory 的典型内容包括用户的操作偏好发布前必须先跑迁移脚本、项目事实生产数据库连接串放在 .env.production、踩坑结论这个 SDK 在 v2 之后弃用了旧的初始化方法、以及团队约定提交信息必须遵循 conventional commits 规范。这些信息的特点是它们在对话过程中被明确或隐含地表达出来且在后续任务中可能反复使用。memory 存放位置和前面的配置类似也分全局与项目两层~/.claude/memory/存个人通用记忆.claude/memory/存项目相关记忆。每个记忆通常是一个独立的 Markdown 文件文件名就是这个记忆的主题标签。保持一个文件一个主题的习惯很重要后续查找、清理都方便。4.2 一条记忆从对话到落盘的完整路径很多人的误区是对话里说了一句记住这个就觉得万事大吉。实际上这句话要真正生效需要经历一次写入-读取的闭环。写入环节是这样的你在对话中表达某个偏好或事实Claude 判断它值得跨会话保留就会把内容整理后写入对应的 memory 文件。比如你说以后部署都用 npm run deploy不要用 npm start它很可能会新增或更新一个deployment.md的记忆文件。读取环节则发生在新的会话里启动时或进入相关任务时Claude 根据当前任务主题从 memory 目录中挑出相关性高的文件加载到上下文。你可以用/memory命令查看当前已有的记忆文件也可以直接用编辑器打开那个 md 文件手动修改。验证记忆是否真的写入的唯一方式就是去看文件系统里有没有对应的 md 文件而不是看它在当前对话中是否点头。我在使用早期就吃过亏以为口头确认过就万事大吉结果换了个会话它照旧忘得干干净净。4.3 memory 与 CLAUDE.md 的边界什么该搬进记忆库和 CLAUDE.md 相比memory 最大的特点是动态。判断一条信息该放哪我有一条很实用的标准这条信息的有效期是项目生命周期还是当下这个阶段稳定不变的规则比如这个仓库必须用 pnpm禁止修改 legacy 目录放 CLAUDE.md因为它长期有效、由人维护、随项目代码一起评审。而大概率会变的动态信息比如这台测试服务器的部署脚本路径客户的 UAT 环境账号用 xx 格式放 memory因为它们在运行过程中产生且更新频繁不值得每次改 CLAUDE.md 都要走一次提交流程。如果你发现自己频繁修改 CLAUDE.md 里的某一段每次都是因为同样的临时信息变了那说明这条信息应该挪到 memory 里去。反过来如果 memory 里有一条规则长期不变、每次都要用那也该升级进 CLAUDE.md减少动态加载的不确定性。4.4 记忆膨胀从资产变成负担memory 的文件多了以后会带来一个隐蔽的问题。会话启动时Claude 按相关性挑记忆文件加载如果 memory 目录里塞满了过时、重复甚至互相矛盾的记录它可能会读到错误的信息。更麻烦的是你以为某条旧记忆已经被覆盖了实际上旧文件还在新的文件也写着相反的结论模型两头为难。我的建议是开启一个固定节奏每隔一两周打开/memory看一遍删掉明确过时的文件合并重复的主题。你甚至可以直接在对话里让 Claude 帮你清理过期记忆给它一个淘汰标准比如所有 2024 年的部署记录都归档掉。不要担心删错memory 是动态的删掉的只要需要随时能重建。真正危险的反而是保留了一堆看似无害、实则过时的知识它在悄悄影响每一个新的会话。另外一个我认为很重要的提醒敏感信息放 memory 要格外慎重。memory 文件会随着会话被反复加载某种意义上它比普通配置文件的暴露面更大。涉及密钥、生产环境地址这类敏感信息优先放到 gitignored 的环境变量文件里而不是写进记忆库。5. 三套配置组合实战一套可复制的落地样例5.1 一个真实项目的完整配置模板说了这么多最后给一套可以抄的作业。假设一个 Node.js React 技术栈的中后台项目我会这样组织三套配置。首先是项目级.claude/settings.json{ permissions: { allow: [ Read, Edit, Grep, Glob, Bash(bash:git status), Bash(bash:git diff), Bash(bash:pnpm run *) ], deny: [ Write, Bash(bash:git push --force), Bash(bash:rm -rf /) ] }, model: claude-sonnet-4-20250514, hooks: { PreToolUse: [ { matcher: Bash, command: echo \$(date) $CLAUDE_TOOL_INPUT\ /tmp/claude_bash.log } ] } }然后是项目根目录的CLAUDE.md# 中后台管理系统 React TypeScript Vite 前端Node.js 服务在 server/ 目录。 ## 常用命令 - 安装依赖pnpm install - 启动前端pnpm dev - 启动服务端pnpm dev:server - 执行测试pnpm test ## 约定 - 所有新代码必须通过 TypeScript 严格检查 - API 调用统一走 src/api/ 下的封装禁止直接 fetch - 环境变量文件为 .env.local不要提交 ## 注意事项 - legacy/ 目录代码不迁移等待整体替换 - 修改 server/ 下的数据库逻辑前需要先查看 migrations/ 目录的迁移记录最后是 memory 目录里可能出现的两个记忆文件# 部署 - UAT 环境部署npm run deploy:uat - 生产部署需要先确认 .env.production 中的版本号 - 上次部署踩坑迁移脚本必须先于构建执行# 用户偏好 - 代码注释使用中文 - 提交信息遵循 conventional commits 格式 - 重构时优先小步提交不要一次性大改你会发现三套配置各司其职settings.json 管程序行为CLAUDE.md 管项目规则memory 管动态知识。它们组合在一起才是完整的配置体系。5.2 配置不生效的排查思路按顺序走完这三步最后分享一下配置出问题时的排查顺序。别瞎猜按这个链路走绝大多数问题五分钟内能定位。第一步确认配置被正确读取。先看会话状态确认当前加载的是哪个层级的 settings.json以及 CLAUDE.md 有没有被载入。如果项目配置没生效优先怀疑放错位置或 JSON 解析失败。第二步判断是不是权限先拦了。功能没按预期执行时不一定是配置错很可能是权限模块把某个工具调用静默拦截或转成了确认。用/permissions查看当前会话的实际权限再对照你配置文件里的 allow/deny。第三步区分规则类问题和知识类问题。如果规则时灵时不灵查 CLAUDE.md 是否被子目录文件覆盖、是否被会话指令覆盖如果是对某个事实的记忆时有时无直接打开 memory 目录的文件看它到底在不在、内容是否过时。把问题归类到程序配置、项目指令、动态知识这三个桶里你自然知道该查哪个文件。5.3 我个人的几条配置心得用到现在我对这套配置体系最深的体会是不要追求完美配置要追求可维护配置。权限宁可先紧后松一开始全放开省事等出了事故再收紧留下的烂摊子反而更多。CLAUDE.md 不需要一次写完跟着项目演进每隔一段时间让它自己读一遍代码库看看有没有新的约定要补进去。memory 的关键不是记得越多越好而是可清理隔段时间就删一批过时文件。还有一个容易被忽略的习惯把项目级配置都纳入版本控制。.claude/settings.json和CLAUDE.md提交到 Git 里好处是所有人共享一套规则改了什么一目了然出问题还能回溯。memory 文件则可以看情况决定是否提交——团队项目建议提交公共约定部分个人偏好部分留在本地就好。这套配置体系说复杂也复杂说简单也简单归根结底就是一件事让 Claude 在正确的时机读到正确的信息。边界划清楚问题就已经解决了一半。
返回列表