如果你正在用 Claude Code或者刚从别的 AI 编程工具切过来我特别建议你先停下来花半小时把它的配置文件体系搞明白。我花了整整三天把用户级配置、项目级配置、MCP 接入、权限规则、hooks 自动化全部摸了一遍中间踩了不少坑——有些配置项官方文档写得云里雾里有些则是网上攻略版本太老照着抄反而报错。这篇指南就是我三天摸查的完整记录全程聚焦配置文件本身不聊安装不聊订阅适合已经跑起来、想进一步调优的人也适合刚装好、想一次性把配置写对的新手。Claude Code 和很多终端工具不一样它没有一个万能的 config.yaml让你从头配到尾而是分散在好几个位置、好几个文件里。你如果不搞清楚这套分层逻辑经常会遇到明明改了配置为什么不生效这个文件到底要不要提交到 Git这类问题。下面我会按照配置体系全景、核心文件拆解、权限与安全、hooks 与高级自定义、问题排查这条线把整套体系讲透。1. 配置体系全景先搞清楚 Claude Code 到底有几层配置1.1 三层配置都在哪Claude Code 的配置不是单一文件而是按用户级、项目级、本地级三个层次分布的。理解了这个模型后面所有问题都好办了。第一层是用户级配置存放在你家目录下的~/.claude/目录。这里主要是两份东西~/.claude/settings.json管全局行为~/.claude/CLAUDE.md管全局记忆。这一层配置对所有项目生效相当于你的个人习惯预设。比如你希望 Claude Code 在所有项目里都默认用中文回复或者统一禁用某些危险工具写操作那就可以放在这一层。第二层是项目级配置放在项目根目录下的.claude/目录或者直接放在项目根目录。常见文件包括.claude/settings.json和项目根目录的CLAUDE.md、.claude/CLAUDE.md。这一层配置会跟随项目仓库走提交到 Git 里团队协作时大家共享同一套规则。它比用户级配置优先级高适合放项目专属的构建命令、测试命令、代码规范、禁用规则等。第三层是本地级配置特指.claude/settings.local.json和CLAUDE.local.md。这两个文件同样放在项目.claude/目录里但不应该提交到 Git。它们的用途是承载只属于你个人的、不适合共享的设置比如你本机特有的路径、个人偏好的模型、本地调试参数等。Claude Code 在生成这类文件时通常会提醒你加入.gitignore但有些时候它不会自动帮你加得自己留意。这三层之外还有一份容易被忽略的~/.claude.json全局状态文件。它记录的是 Claude Code 运行过程中的历史会话、项目缓存、权限选择记录等状态信息不建议手动编辑但你可以通过它确认某些设置是不是已经被记录下来了。1.2 配置优先级与合并规则配置分层之后最核心的问题就是当多个层的配置冲突时到底听谁的按照 Claude Code 的合并逻辑优先级从高到低大概是这样的优先级配置来源典型文件最高命令行参数--settings、--model、--permission-mode高项目本地配置.claude/settings.local.json中项目级配置.claude/settings.json、CLAUDE.md低用户级配置~/.claude/settings.json、~/.claude/CLAUDE.md最低内置默认工具出厂设置我做一个生活化的类比用户级配置就像手机的全局主题项目级配置像是某个 App 内的自定义设置而settings.local.json则是你这个 App 里只属于当前账号的私有设置。三者在同一台设备上叠加生效但是越往下越专也就越优先。这里有个特别容易踩坑的地方很多人以为项目里的 settings.json 优先级一定高于用户目录下的 settings.json但如果你在项目里同时存在settings.json和settings.local.json两个文件后者的优先级会更高。也就是说你辛辛苦苦在项目级配置里设了一个model结果某天调试时在settings.local.json里也写了个model那实际生效的其实是本地那个。这个顺序反过来的情况我一开始也搞错过。另外permissions这类配置在合并时有自己的一套规则。allow、deny、ask三个列表不是简单覆盖而是会做规则级合并并且deny的优先级通常高于allow也就是说你允许执行某个操作但在另一个层里显式拒绝了那最终结果还是拒绝。这一点在后文权限部分我会展开讲。2. 核心配置文件逐个拆解2.1 settings.json全局行为的控制台settings.json是 Claude Code 所有 JSON 配置的载体不管是在~/.claude/还是在项目.claude/目录下文件名都叫settings.json。它承担的职责很杂包括模型选择、权限规则、环境变量注入、hooks 挂载、Git 提交信息等。我挑几个高频字段给你看这是我整理的一个精简配置示例{ model: claude-sonnet-4-5, permissions: { allow: [ Bash(npm run build), Read(~/projects/blog/**) ], deny: [ Bash(rm -rf *), Edit(~/.ssh/**) ], ask: [ Bash(git push *) ] }, env: { MY_APP_TOKEN: 改我 }, includeCoAuthoredBy: true, cleanupPeriodDays: 30, hooks: {} }先解释几个容易误解的字段。model字段很好理解就是指定默认使用的模型。这里注意一点不是所有模型都能随便填得是你账号有权限访问的模型名。我见过有人把模型名写成了带日期的旧版本号结果启动直接报模型不存在。命名这种事最好在交互界面里用/model命令确认一下当前可选列表再写进配置里别凭记忆硬写。includeCoAuthoredBy是控制 Git 提交时是否自动追加Co-Authored-By: Claude标记。这个字段我觉得挺有意思它本身不影响代码质量但如果你所在团队对提交信息有严格的格式要求就可能需要关掉它。打开方式很简单设成true就行。cleanupPeriodDays控制的是历史会话的清理周期默认是 30 天。它删除的是本地缓存的会话记录不是云端数据。如果你经常有敏感代码出现在终端里想减少本地残留可以把数值调小一点。env字段则是给 Claude Code 启动的子进程注入环境变量用的。比如你希望它执行某个脚本时自动带上API_BASE_URL又不想污染系统全局环境变量就可以放在这里。但要小心不要把真实的密钥硬编码进settings.json再提交到 Git 仓库这种泄漏方式我见过太多次了。项目级环境下如果你的配置里需要引用环境变量更安全的做法是在系统环境变量里定义好后在 Claude Code 的env字段里只做MY_APP_TOKEN: ${MY_APP_TOKEN}形式的引用。2.2 CLAUDE.md项目记忆与行为约定如果说settings.json管的是机械参数那CLAUDE.md管的就是行为记忆。Claude Code 每次会话启动时都会读取这个文件把它当作关于项目和用户偏好的长期记忆来源。这个文件的核心价值在于你不用每次开新会话都重新交代一遍项目背景和代码规范。比如你写一个 Python 后端项目可以在项目根目录的CLAUDE.md里写明# 项目说明 这是一个基于 FastAPI 的订单服务Python 3.12依赖管理使用 uv。 ## 常用命令 - 安装依赖uv sync - 跑测试uv run pytest tests/ -q - 启动开发服务uv run uvicorn app.main:app --reload ## 代码约定 - 所有接口返回统一格式{code: 0, data: ..., message: ok} - 数据库操作必须走 async session不允许多线程共用 session - 修改数据库表结构后必须同步生成迁移脚本你可以用/memory命令在会话里随时查看当前生效的记忆文件也可以用/init命令让 Claude Code 根据现有代码仓库自动生成一份初始的 CLAUDE.md。CLAUDE.md 在读取上还有一个细节它支持语法引入其他文件比如docs/architecture.md。如果你有一份非常长的架构说明文档不希望全塞进主记忆文件可以拆出去然后在 CLAUDE.md 里引用。这种方式很适合知识库类的内容。CLAUDE.local.md是它的本地变体这个文件不会被提交到 Git放的是只有你自己需要、不想让别人看到的偏好。比如你个人不喜欢某个构建工具的提示或者在本机有特殊的代理路径设置就可以放这里。我实测下来CLAUDE.md 不是写得越多越好。塞太多冗余内容反而会让 Claude 在无关的信息上消耗注意力。合理的做法是高频使用的命令、铁律类的约定、项目结构概览这三样优先剩下的能省则省。我在项目里遇到过有人把整个 README 几千字全复制进 CLAUDE.md结果 Claude 经常被里面过时的功能说明带偏这属于典型的记忆冗余。2.3 .mcp.jsonMCP 接入配置MCPModel Context Protocol是 Claude Code 扩展能力的核心机制而.mcp.json是项目级 MCP 服务器的标准配置文件。如果你要在项目里接入数据库、文件系统、搜索引擎等外部工具基本就是通过这个文件声明。一个典型的本地 stdio MCP 服务配置长这样{ mcpServers: { sqlite: { command: uvx, args: [mcp-server-sqlite, --db-path, ./data.db], env: { SQLITE_DB_PATH: ./data.db } }, remote-fetch: { type: http, url: https://your-mcp.example.com/mcp, headers: { Authorization: Bearer your-token }, enabled: true } } }本地服务用的是commandargs这种标准形式Claude Code 会帮你启动子进程走 stdio 通信。远程服务一般用type: http声明走 streamable HTTP 或 SSE。enabled字段可以控制该服务默认是否启用这点很实用——有些服务你可能只是偶尔用平时没必要每次启动都去连那就把enabled设为false。.mcp.json这个文件默认是设计为可以提交到 Git 的方便团队共享 MCP 服务配置。但这里有个安全提醒如果你在headers里写了真实的 token或者某个服务连接的是内网地址那就不要放到 Git 里要么改成环境变量引用要么直接在 settings.local.json 里配置私有服务。MCP 配置改完之后不是马上就能在会话里生效的。你需要重启 Claude Code 会话然后可以用/mcp命令查看服务连接状态。我一开始不知道这一点改了配置后反复刷新都没看到新服务差点以为文件格式写错了。如果你也遇到配置了却看不到服务的问题优先考虑重启会话而不是先怀疑命令写错。3. 权限、密钥与敏感项配置3.1 权限系统怎么配置权限系统是整个 Claude Code 安全模型里最重要的一环也是我建议你花最多时间理解的地方。它的核心是三类规则allow允许执行、deny拒绝执行、ask执行前询问。我直接给一个包含规则的权限配置示例{ permissions: { allow: [ Bash(npm run test), Bash(npm run build), Read(~/projects/my-project/**), Write(./src/**) ], deny: [ Bash(rm -rf *), Edit(~/.ssh/**), Read(~/.aws/credentials) ], ask: [ Bash(git push *), Edit(./secrets/**) ] } }规则的结构是工具名(参数模式)工具名包括Bash、Read、Write、Edit、WebFetch等。参数模式里支持通配符*和**。*匹配单层路径**匹配多层路径。如果你在配置文件里看到Bash(*)、Read(*)这种全量放行的写法要特别警惕。全量放行意味着 Claude Code 可以在你的终端里执行任意命令、读取任意文件这相当于把电脑的钥匙直接交给了 AI。我自己的习惯是宁可在allow列表里把构建、测试这类高频命令写细一点也不要图省事直接开全量。还有一个细节deny的优先级高于allow。即便你在某个层级设置了Bash(*)全量允许如果另一个层级有Bash(rm -rf *)的拒绝规则那rm -rf这个命令还是会被拦截。Claude Code 在判断规则时逻辑上倾向于保守优先这种设计是有道理的。3.2 环境变量与密钥管理密钥管理是配置环节里最不能马虎的部分。Claude Code 在运行时会读取很多环境变量有的管模型行为有的管鉴权有的管输出格式。以下是几个在生产环境里经常被用到的环境变量环境变量作用ANTHROPIC_API_KEYAPI 鉴权密钥ANTHROPIC_MODEL默认模型优先级低于 settings.json 里的 model 字段ANTHROPIC_SMALL_FAST_MODEL后台轻量任务如标题总结用的快速模型ANTHROPIC_APP_NAME自定义当前会话归属的 App 名称可用于日志区分我强烈建议避免把真实密钥写进任何会被提交的配置文件中。哪怕你只是在本地用一旦哪天忘了加.gitignore一提交就全漏了。安全的方法是密钥放在操作系统的环境变量里比如在 shell 配置文件中export ANTHROPIC_API_KEYxxx。如果必须放进settings.json的env字段那至少用${ANTHROPIC_API_KEY}这种引用形式由 Claude Code 启动时去系统环境变量取值。项目级敏感配置全部放settings.local.json并在.gitignore里明确加上.claude/settings.local.json。我还想说一个心得不要在登录和运维阶段图省事把skipAuth类的配置开开就完事。任何绕过鉴权的配置都意味着降低安全水位除非你明确知道自己在做什么否则默认策略就好。4. Hooks、Agent Skills 与高级自定义4.1 Hooks 事件与自动化Claude Code 的 hooks 体系让我觉得它已经不像一个简单的 AI 终端工具而更像一个可编程的自动化平台。hooks 允许你在特定事件发生时让 Claude Code 自动执行外部命令并根据命令的退出码来决定后续行为。目前常用的 hooks 事件包括事件名触发时机典型用途PreToolUse调用任意工具前拦截危险命令、审查文件路径PostToolUse工具执行完成后记录命令执行结果、自动格式化Notification任务需要用户关注时发桌面通知或 IM 消息SessionStart会话启动时加载环境信息、打印自定义提示语UserPromptSubmit用户提交提示词后对提示词做预处理Stop一次生成过程结束时记录 token 消耗、保存日志hooks 的配置方式是在 settings.json 的hooks字段里按事件挂载命令{ hooks: { PreToolUse: [ { matcher: Bash, hooks: [ { type: command, command: /path/to/my-check.sh } ] } ], Notification: [ { hooks: [ { type: command, command: /usr/bin/osascript -e display notification \Claude Code 需要你注意\ } ] } ] } }hooks 命令运行时会通过标准输入收到一份 JSON 格式的事件数据里面包含工具名、参数、会话 ID 等信息。你可以用jq在脚本里解析这些数据实现很灵活的判断。这里重点说PreToolUse的一个典型用途命令拦截。如果你的脚本对传入参数做了检查退出码为 2 时Claude Code 会阻止该工具执行退出码为 0 则放行。这个机制非常实用。我有一次就是用PreToolUse拦截了写操作避免 AI 在非约定目录里创建文件。matcher字段可以精确到工具类型也可以留空匹配所有工具但留空时要注意你的脚本逻辑必须足够健壮否则所有工具都会被影响。4.2 Skills 与自定义指令Skills 这一部分是我这次摸查过程中觉得最有挖掘空间的功能。简单理解Skills 是给 Claude Code 准备的技能包里面是一份SKILL.md加配套脚本、模板和资源文件。你可以在项目级.claude/skills/skill-name/SKILL.md下定义项目专属技能也可以在用户级~/.claude/skills/定义全局技能。一个最小的 SKILL.md 示例--- name: brand-style-check description: 检查文案是否符合品牌语气规范,在需要统一文案风格时使用 allowed-tools: Read, Edit --- # 品牌语气检查 遵循以下规则 - 使用简短句避免过于正式 - 禁止使用被动语态 - 所有数字统一用阿拉伯数字 - 产品名称固定为星云frontmatter里的name是技能名description很关键因为 Claude Code 会根据 description 判断在什么时候调用这个技能。allowed-tools用于限制该技能默认可用的工具集。Skills 和 CLAUDE.md 的区别在于CLAUDE.md 是一种常驻记忆Claude 每次都能读取Skills 则像一个按需调用的工具箱只有任务匹配到描述时才会被激活。我自己的实践是把那些会长期约束行为的规则放进 CLAUDE.md把那些特定场景才用的能力比如代码审查、发版检查、单元测试模板生成写成 Skills这样既能控制上下文消耗又能在需要时获得专项能力。5. 三天摸出来的常见问题与排查实录5.1 配置不生效的排查思路如果你发现改了配置但行为没变化可以参考我下面的排查顺序这是我踩了无数次坑后总结出来的。第一先确认你改的是不是实际生效的那个文件。记住优先级顺序settings.local.json压过settings.json项目级压过用户级。你可以用/status命令来查看当前会话实际加载的配置路径也可以直接看~/.claude.json里的项目映射确认。第二检查是不是类型写错了。settings.json是严格 JSON不是 JSONC注释是不允许的。如果你在里面写了注释整个文件可能解析失败Claude Code 会回退到默认配置并且不一定给你明显报错。这是最坑的情况之一表面上看配置读取正常实际全部用的是默认值。第三MCP 类和 hooks 类的配置改动很多都需要重启会话才能生效。尤其是 MCP 服务列表.mcp.json修改后几乎必须重启。判断是否生效可以用/mcp命令查看服务连接状态。第四开启调试模式看日志。使用claude --debug启动它会输出详细的配置加载和工具调用日志。日志里能直观看到哪些配置被读取、哪些规则被匹配。我曾经排查一个权限拦截问题就是靠 debug 日志发现是用户级配置里一条老旧的 deny 规则在作怪。5.2 常见报错速查表报错或异常现象可能原因解决方案配置看起来改了但行为没变读取了优先级更高的其他配置文件用/status确认当前生效配置路径settings.json 里写了注释导致解析失败JSON 文件不允许注释删除注释或用独立 JSON 文件MCP server 连接失败command 路径不存在、环境变量缺失先手动在终端执行该 command确认能正常启动弹出 Permission denied权限规则 matches 了 deny 列表检查 allow/deny/ask 规则结合 debug 日志模型名报错model 字段写了不存在的模型名用/model查询可用列表或移除 model 字段hooks 命令一直不执行事件名大小写错误、stdin 解析失败核对事件名PreToolUse 不能写成 pretooluse在脚本里加入 jq 容错CLAUDE.md 内容没被引用文件名或路径不对确认是 CLAUDE.md全部大写放项目根目录或.claude/下token 消耗异常快MCP 服务太多、CLAUDE.md 太长禁用不常用 MCP 服务精简记忆文件另外补充一个我在排查时发现的细节MCP server 连接失败时Claude Code 终端里看到的错误信息通常比较笼统只提示failed to connect之类的。这时最有效的排查方式是直接在终端里手动执行command部分看是不是命令本身就有问题。比如你配置的是uvx mcp-server-sqlite先在终端跑一遍如果 uvx 提示找不到包那就要先解决运行环境的问题再回头看 Claude Code 的配置。hooks 排查也是类似的思路。先确认事件名完全正确再在命令里加上日志输出到文件方便你确认到底有没有触发。我在最初写 Notification hook 时因为事件信号量处理不对导致通知脚本每次都失败但 Claude Code 并不会在界面上弹错误只有日志里能看到。最后再分享一个小技巧用 Git 管理你的配置。我会把~/.claude/目录里允许提交的配置文件放到一个单独的 dotfiles 仓库里项目级配置则随项目一起走。这样换新电脑时只要把仓库拉下来软链接指好整套配置环境几分钟就恢复不用重新摸索一遍。我个人在实际操作中的体会是Claude Code 的配置体系并不复杂但它胜在灵活灵活带来的代价就是需要你花点心思理解每一条规则的边界。与其一次性把所有高级功能都堆上去不如从最小可用配置开始跑通了再加一个模块这样出了问题也能快速定位。