Claude Code 配置体系深度解析:settings.json、CLAUDE.md 与 memory 的边界与协同

发布时间:2026/10/8 21:25:44
Claude Code 配置体系深度解析:settings.json、CLAUDE.md 与 memory 的边界与协同 1. 三套配置体系到底在管什么很多人第一次接触 Claude Code看到项目根目录下同时存在settings.json、CLAUDE.md和 memory 相关文件第一反应是懵的——这三个东西看起来都在“配置”到底谁管谁我刚开始用的时候也踩过这个坑把一堆本该写在settings.json里的东西塞进了CLAUDE.md结果权限规则死活不生效排查了半天才发现是放错了地方。先把结论摆在前面这三套体系分别对应三个完全不同的层面。settings.json管的是“工具怎么跑”——权限、环境变量、模型选择、钩子hooks、MCP 服务器注册。它是机器读的格式严格写错一个逗号整个文件就废了。CLAUDE.md管的是“项目是什么”——技术栈、目录结构、构建命令、代码规范、协作约定。它是给模型读的自然语言上下文每次会话启动时会被加载进上下文窗口。memory管的是“跨会话记住什么”——你在对话中让 Claude 记住的偏好、决策、临时约定它会持久化到本地文件下次开新会话还能用。打个比方settings.json像是你给新员工配的工牌和门禁权限CLAUDE.md是放在工位上的项目手册memory 则是这个员工自己的笔记本记着“老板喜欢用 pnpm 不用 npm”这类口头约定。理解了这个分层后面所有的配置问题基本都能对号入座。我见过太多人把权限规则写进CLAUDE.md然后抱怨“为什么 Claude 还是每次都问我”根源就是没搞清楚这三者的边界。1.1 为什么要有三套而不是一套这个问题我被问过不止一次。直觉上把所有配置塞进一个文件不是更简单吗实际上不行原因有三个。第一是加载时机不同。settings.json在进程启动时就要解析决定了这次会话能用哪些工具、走哪个模型。CLAUDE.md是在会话初始化阶段作为上下文注入的它影响的是模型的“认知”而不是“能力”。memory 则是在会话过程中动态读写的随时可能变化。三者生命周期完全不一样硬合并会导致要么启动变慢要么上下文浪费。第二是格式约束不同。settings.json必须是合法 JSON机器要严格解析CLAUDE.md是 Markdown本质是给模型看的自然语言格式宽松得多memory 通常是结构化的键值对或者追加式日志。把自然语言和严格 JSON 混在一个文件里解析器会疯掉。第三是共享范围不同。settings.json里有一部分是项目级提交到仓库团队共享有一部分是用户级放在家目录只对自己生效。CLAUDE.md通常是项目级共享的。memory 则基本是个人本地的。混在一起就没法做这种粒度控制。提示如果你在团队里推广 Claude Code建议把settings.json的项目级部分和CLAUDE.md一起提交到仓库用户级配置和 memory 加进.gitignore。这样新人 clone 下来就能直接用又不会把自己的个人偏好污染给全组。1.2 三者的优先级与覆盖关系实际使用中经常出现“同一个设置在两处都写了”的情况这时候谁生效根据我的实测优先级从高到低大致是命令行参数临时覆盖最高优先级项目级settings.json.claude/settings.json用户级settings.json~/.claude/settings.jsonCLAUDE.md中的约定仅作为上下文提示不强制memory 中的记录最弱模型可能忽略这里有个关键点容易被误解CLAUDE.md和 memory 里的内容不是强制规则它们只是上下文。模型“倾向于”遵守但在复杂任务中可能被忽略。而settings.json里的权限规则是硬约束工具层面直接拦截。所以如果你有“绝对不能让 Claude 执行某类命令”的需求必须写在settings.json的权限配置里写进CLAUDE.md是靠不住的。我踩过一次坑在CLAUDE.md里写了“不要执行 rm -rf”结果某次重构时 Claude 还是建议了一条删除命令。后来老老实实在settings.json里加了 deny 规则才彻底堵住。2. settings.json 深度拆解与实操配置settings.json是整个配置体系里最“硬”的部分也是最容易出错的。它的位置有两个项目级的在项目根/.claude/settings.json用户级的在~/.claude/settings.json。项目级会覆盖用户级的同名配置。2.1 文件结构与核心字段一个完整的settings.json大致长这样{ permissions: { allow: [ Bash(npm run test:*), Bash(git status), Read(//src/**) ], deny: [ Bash(rm -rf:*), Bash(curl:*), Read(./.env) ], ask: [ Bash(git push:*), Write(//src/**) ] }, env: { NODE_ENV: development, PROJECT_ROOT: /Users/me/projects/demo }, model: claude-sonnet-4-5, hooks: { PostToolUse: [ { matcher: Write, hooks: [ { type: command, command: npx prettier --write $CLAUDE_FILE_PATH } ] } ] } }逐个字段说。permissions是最核心的部分分allow、deny、ask三个数组。allow里的规则直接放行不询问deny里的直接拒绝ask里的每次都要用户确认。规则格式是工具名(参数模式)比如Bash(npm run test:*)表示允许所有以npm run test开头的命令。这里有个细节Bash规则的匹配是基于命令前缀的Bash(git status)只匹配完全等于git status的命令而Bash(git status:*)匹配git status后面跟任何参数。冒号加星号是通配符语法别漏了。env是注入到工具执行环境里的变量。注意它不会自动注入到 Claude 的上下文里只是影响 Bash 等工具执行时的环境。如果你想让 Claude 知道某个变量得写在CLAUDE.md里。model指定默认模型。这个字段在不同版本里名字可能有变化有的版本用model有的用defaultModel。建议配置前先跑一次claude config list看看当前支持的字段名。hooks是钩子系统允许在工具调用前后执行自定义命令。上面例子里的PostToolUse表示在 Write 工具执行后跑 prettier 格式化。这个功能非常强大后面单独讲。2.2 权限规则的写法与常见陷阱权限规则写错是新手最高频的问题。我整理了几种典型场景的正确写法。需求错误写法正确写法允许所有 git 命令Bash(git)Bash(git:*)允许读取 src 下所有文件Read(src/*)Read(//src/**)拒绝读取 .envRead(.env)Read(./.env)允许 npm 脚本Bash(npm run:*)Bash(npm run:*)但注意空格允许特定目录写入Write(src)Write(//src/**)几个关键点路径规则里//开头表示相对于项目根目录./表示相对于当前工作目录~/表示家目录。**匹配任意层级*只匹配单层。这个和 gitignore 的语法类似但不完全一样别想当然。Bash规则的匹配是前缀匹配不是正则。Bash(npm run test:*)会匹配npm run test、npm run test:unit、npm run test -- --watch但不会匹配npm run testx。冒号后面的*是必须的不写的话只匹配完全相等的命令。注意deny规则的优先级高于allow。如果一条命令同时匹配 allow 和 deny会被拒绝。这个设计是为了安全但也意味着你写 allow 的时候要小心别和已有的 deny 冲突。2.3 hooks 钩子系统的实战用法hooks 是我认为settings.json里最被低估的功能。它让你能在 Claude 执行工具的前后插入自己的逻辑实现自动化。支持的钩子事件主要有PreToolUse工具执行前触发可以用来做校验、拦截PostToolUse工具执行后触发适合做格式化、lint、通知UserPromptSubmit用户提交 prompt 时触发Stop会话结束时触发一个实用的例子每次 Claude 写完文件自动跑 eslint 修复。{ hooks: { PostToolUse: [ { matcher: Write|Edit, hooks: [ { type: command, command: npx eslint --fix $CLAUDE_FILE_PATH 2/dev/null || true } ] } ] } }matcher支持正则Write|Edit表示匹配这两个工具。$CLAUDE_FILE_PATH是环境变量指向被操作的文件路径。末尾的|| true是为了防止 eslint 报错导致钩子失败阻塞流程。另一个场景在PreToolUse里拦截危险命令。{ hooks: { PreToolUse: [ { matcher: Bash, hooks: [ { type: command, command: echo \$CLAUDE_TOOL_INPUT\ | grep -qE rm -rf / exit 1 || exit 0 } ] } ] } }这个钩子检查即将执行的 Bash 命令里有没有rm -rf /有就返回非零退出码阻止执行。虽然permissions.deny也能做类似的事但 hooks 能做更复杂的逻辑判断。2.4 用户级与项目级的分工策略我的建议是把配置分成两类用户级~/.claude/settings.json放个人偏好默认模型、个人常用的 allow 规则比如允许所有git只读命令、个人 hooks比如通知脚本。项目级.claude/settings.json放团队约定项目特定的构建命令权限、项目 hooks格式化、lint、项目环境变量。这样新人入职时clone 项目就自动获得团队约定同时保留自己的个人偏好。冲突时项目级覆盖用户级符合直觉。有个坑要注意项目级settings.json如果提交到仓库里面不要放任何敏感信息API key、内部路径。环境变量里的密钥应该通过系统环境变量注入而不是写死在配置文件里。3. CLAUDE.md 的写法与上下文管理如果说settings.json是给机器看的CLAUDE.md就是给模型看的。它的质量直接决定了 Claude 对你项目的理解程度进而影响输出质量。我见过太多人把CLAUDE.md写成一句话“这是一个 React 项目”然后抱怨 Claude 生成的代码不符合规范。3.1 一份合格 CLAUDE.md 的必备要素根据我多个项目的实践一份好用的CLAUDE.md应该包含以下内容项目概述一两句话说明项目是干什么的目标用户是谁。这帮助模型建立整体认知。技术栈语言、框架、主要依赖的版本。特别注意标注版本因为不同版本的 API 差异很大。目录结构关键目录的用途说明。不需要列出所有文件但要让模型知道“组件放哪、工具函数放哪、测试放哪”。常用命令构建、测试、lint、启动开发服务器的命令。这是最高频被用到的部分。代码规范命名约定、文件组织约定、导入顺序、注释风格。越具体越好。协作约定提交信息格式、分支命名、PR 流程。如果团队有约定的话。已知限制项目里有哪些坑、哪些地方不要动、哪些依赖不能升级。一个真实的例子# 项目概述 这是一个面向中小企业的库存管理系统前端使用 React TypeScript。 # 技术栈 - React 18.2注意不用 19因为依赖的 UI 库还没适配 - TypeScript 5.3 - Vite 5.0 构建 - Zustand 状态管理不用 Redux - TanStack Query 数据请求 # 目录结构 - src/components/ 通用组件每个组件一个目录 - src/features/ 按业务模块组织的功能代码 - src/lib/ 工具函数和第三方封装 - src/types/ 全局类型定义 # 常用命令 - pnpm dev 启动开发服务器 - pnpm test 跑单元测试 - pnpm lint 代码检查 - pnpm build 生产构建 # 代码规范 - 组件用函数式 hooks不用 class - 文件名用 kebab-case组件名用 PascalCase - 导入顺序react → 第三方 → 内部绝对路径 → 相对路径 - 禁止使用 any用 unknown 加类型守卫 # 已知限制 - 不要升级 react 到 19 - src/lib/legacy/ 下的代码是历史遗留不要重构 - 测试覆盖率要求 80%新代码必须带测试这份CLAUDE.md大概 300 字但信息密度很高。Claude 读完就知道该用什么、不该用什么、命令怎么跑。3.2 上下文窗口的取舍艺术CLAUDE.md不是越长越好。它每次会话都会被加载进上下文窗口占用 token。如果你的CLAUDE.md写了 5000 字那每次对话都先消耗掉一大块上下文留给实际任务的空间就少了。我的经验是控制在 500-1500 字之间。超过这个范围就要考虑拆分把详细的规范文档放在单独的文件里在CLAUDE.md里用引用指向它需要时再让 Claude 去读。比如# 代码规范 详细的代码规范见 docs/coding-standards.md。 核心约定函数式组件、kebab-case 文件名、禁止 any。这样CLAUDE.md保持精简详细内容按需加载。另一个技巧是分层组织。把最重要的信息放在最前面因为模型对开头的注意力更集中。项目概述、技术栈、常用命令放前面已知限制放后面。提示如果你的项目有多个子包monorepo可以在每个子包目录下放一个CLAUDE.mdClaude 会根据当前工作目录自动加载对应的文件。这样每个子包的上下文都是独立的不会互相干扰。3.3 动态更新与版本管理CLAUDE.md应该跟着项目一起演进。我的做法是把它纳入 code review 流程每次有重大的技术决策变更换框架、改目录结构、加新约定都要同步更新CLAUDE.md。有个实用的技巧在CLAUDE.md里加一个“最近变更”小节记录最近几次重要的约定调整。这样模型能感知到项目在演进而不是把它当成静态文档。# 最近变更 - 2024-11从 Redux 迁移到 Zustand旧代码逐步替换 - 2024-10引入 TanStack Query新数据请求都用它 - 2024-09测试框架从 Jest 换成 Vitest这个习惯帮我避免了好几次“Claude 用旧方案写代码”的问题。4. memory 机制的原理与使用技巧memory 是三套体系里最“隐形”的很多人用了很久都没意识到它的存在。它的作用是让 Claude 跨会话记住一些信息不用每次重复交代。4.1 memory 的存储位置与格式memory 通常存储在~/.claude/memory/目录下具体路径可能因版本而异每个项目一个文件文件名基于项目路径的哈希。格式一般是 Markdown 或 JSON记录的是键值对形式的条目。你可以通过对话让 Claude 记住东西比如“记住这个项目用 pnpm 不用 npm”它会自动写入 memory。也可以手动编辑 memory 文件但要注意格式。memory 的条目通常包含内容、创建时间、来源哪次对话、置信度。有些版本还支持过期时间到点自动清理。4.2 什么该记、什么不该记memory 用得好是神器用不好是负担。我的原则是该记的个人偏好“我喜欢简洁的回复不要长篇解释”跨会话的决策“这个项目决定用 Zustand 不用 Redux”临时约定“这周在重构 auth 模块相关代码先别动”不该记的项目结构、技术栈这些应该写在CLAUDE.md里团队共享一次性的任务细节记了也没用任务完成就过时了敏感信息memory 是本地文件但也不建议存密钥我见过有人把整个项目的架构说明都塞进 memory结果每次会话都加载一大堆过时信息反而干扰了判断。memory 应该保持精简只记那些“跨会话仍然有效”的东西。4.3 memory 与 CLAUDE.md 的边界这两者最容易混淆。我的判断标准很简单团队共享的写CLAUDE.md个人专属的写 memory。比如“这个项目用 pnpm”是团队约定写CLAUDE.md。“我习惯看简洁的 diff不要贴大段代码”是个人偏好写 memory。如果一条信息既想团队共享又想个人保留那它大概率应该写CLAUDE.md因为个人偏好可以通过用户级settings.json或 memory 单独处理。有个常见的误区是把 memory 当成“临时便签”记一堆“今天要改 XX 文件”之类的。这些信息下次会话就过时了留在 memory 里只会造成干扰。临时任务应该用 TODO 工具或者直接写在对话里不要污染 memory。4.4 清理与维护 memorymemory 会随着使用不断累积定期清理很有必要。我的做法是每个月过一遍 memory 文件删掉过时的条目。清理时问自己三个问题这条信息现在还准确吗这条信息下次会话还用得上吗这条信息是不是应该挪到CLAUDE.md里三个问题有一个答“否”就考虑删除或迁移。有些版本支持claude memory list和claude memory clear命令可以直接在命令行管理。如果你的版本不支持就手动编辑文件。注意清理 memory 前建议先备份。虽然 memory 丢了不影响项目运行但一些积累的偏好设置重新建立起来挺麻烦的。5. 三套体系的协同与常见问题排查单独理解三套体系不难难的是它们协同工作时出的问题。这一节整理我遇到过的典型故障和排查思路。5.1 配置不生效的排查顺序当你发现某个配置没生效时按这个顺序排查确认文件位置项目级还是用户级路径对不对.claude/settings.json不是claude/settings.json少个点就找不到。确认 JSON 合法性用jq . settings.json验证有语法错误会直接报出来。确认优先级是不是被更高优先级的配置覆盖了项目级覆盖用户级命令行覆盖两者。确认加载时机settings.json改动需要重启会话才生效CLAUDE.md改动下次会话生效memory 改动立即生效。查看日志claude --debug启动可以看到配置加载的详细日志哪条规则被应用了一目了然。我遇到最多的问题是 JSON 语法错误。一个多余的逗号、一个中文引号都会导致整个文件被忽略。建议用编辑器自带的 JSON 校验或者写完跑一次jq。5.2 权限规则冲突的典型案例案例一allow 里写了Bash(git:*)但git push还是每次询问。原因git push可能被ask里的规则匹配了或者用户级配置里有更严格的规则。检查所有层级的配置确认没有冲突。案例二deny 里写了Read(./.env)但 Claude 还是读到了 .env 的内容。原因路径规则写错了。./.env是相对于当前工作目录如果 Claude 的工作目录不是项目根就匹配不上。应该用Read(//.env)或者绝对路径。案例三hooks 里的命令不执行。原因hooks 命令的执行环境可能和你的 shell 不一样PATH 可能不完整。建议用绝对路径调用命令或者在命令前加source ~/.bashrc。5.3 上下文超限的应对策略当CLAUDE.md太长、memory 条目太多时会出现上下文超限表现为 Claude 开始“忘记”前面的内容或者响应变慢。应对方法精简CLAUDE.md把详细内容外链到单独文档清理 memory删除过时条目用/compact命令压缩当前会话的上下文把大任务拆成多个小会话每个会话专注一个子任务我处理大型重构时的做法是先开一个会话专门做规划把规划结果写进CLAUDE.md或 memory然后开新会话执行具体任务。这样每个会话的上下文都很干净。5.4 常见问题速查表现象可能原因排查方法配置完全不生效文件路径错误或 JSON 语法错误jq . settings.json验证权限规则不生效优先级冲突或规则语法错误claude --debug看加载日志Claude 不遵守 CLAUDE.md内容太长被截断或表述模糊精简内容用明确的祈使句memory 不生效条目过期或格式错误检查 memory 文件格式hooks 不执行命令路径问题或权限不足手动跑一遍 hook 命令会话变慢上下文超限/compact或开新会话模型选错model 字段名不对claude config list确认字段名5.5 我的配置管理实践最后分享一套我用了半年的配置管理流程供参考。版本控制项目级.claude/settings.json和CLAUDE.md提交到仓库。用户级配置和 memory 不提交但我会定期备份到私有仓库。模板化我维护了一套配置模板新项目初始化时直接复制改改项目名和技术栈就能用。省去了每次从零写CLAUDE.md的时间。定期审查每季度过一遍所有项目的配置清理过时规则更新技术栈版本。这个习惯帮我避免了好几次“配置和实际不符”的问题。团队同步团队里指定一个人负责维护共享配置其他人有变更需求提 PR。避免多人同时改导致冲突。这套流程跑下来配置相关的故障率明显下降。配置这东西前期花时间搭好后期省的时间是成倍的。关于 memory 的清理我还有个习惯每次项目里程碑结束时把 memory 里和这个阶段相关的条目清掉只保留长期有效的偏好。这样 memory 始终保持在几十条以内不会变成垃圾场。配置体系这东西没有标准答案每个人的工作流不一样最优解也不一样。但理解清楚settings.json、CLAUDE.md、memory 三者的边界和协同方式是搭出适合自己方案的前提。我上面写的都是踩过坑之后总结出来的你可以根据自己的情况调整。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询