说实话Claude Code 装好就能跑但“能跑”和“顺手”之间隔着一大截。我最开始用它改代码几乎每开一个新会话都要重新解释一遍项目结构、代码风格、哪些文件不能动甚至它写出来的提交信息格式每次都跟商量好了似的各不相同。浪费 token 还是小事关键是同样的约束反复交代它照样会“忘”。直到我花了一个周末把它的自定义体系彻底捋了一遍才意识到问题不在这个工具本身而在我没有正确使用它的配置能力。这篇文章就围绕“Claude Code 自定义”这件事把记忆、命令、权限、钩子、MCP、输出风格这几条主线全部过一遍。内容按我真实配置的顺序展开里面所有示例都是我实际用过的写法适合刚开始接触 Claude Code 的开发者也适合已经用了挺久、但总觉得“差点意思”的人。目标很简单让这个终端里的 AI 助手真正变成“长在你项目上的老员工”而不是每次都重新入职的实习生。1. 自定义之前先搞懂这些配置入口和加载顺序1.1 三层配置项目级、用户级、本地级Claude Code 的自定义不是散落在一堆命令行参数里的它的配置体系可以分成三个层次。第一层是项目级配置放在仓库根目录下的.claude/目录里包括settings.json、commands/文件夹、CLAUDE.md、skills/、agents/等。这类配置跟着仓库走提交到远端后整个团队都能共享是“团队约定”天然的家。第二层是用户级配置位于用户主目录的~/.claude/下同样有settings.json和CLAUDE.md。用户级配置对你电脑上的所有项目生效适合放个人习惯比如“我永远不需要它编辑某个目录”或者“所有代码审查都默认用某个模型”。第三层是本地级配置一般以.claude/settings.local.json的形式存在项目里但会被忽略提交不上传到远端。它适合放只有你一个人需要的临时偏好比如测试某条权限规则、临时切换模型。三者的优先级从低到高大致是用户级 → 项目级 → 本地级会话内用/config、/model这类命令做的调整优先级最高。这个顺序理解起来不复杂但它是排查“我明明配置了为什么不生效”的第一把钥匙。比如你在项目级settings.json里配了model本地文件里也配了一个最后生效的一定是本地文件里的值。1.2 配置文件体系一览把整个自定义体系拆开看核心就这几类东西配置载体位置主要作用CLAUDE.md项目根目录 / 用户主目录给 AI 注入长期记忆与项目约定settings.json.claude/目录权限、模型、钩子、状态栏等行为参数commands/*.md.claude/commands/自定义斜杠命令skills/.claude/skills/可跨会话复用的技能包agents/*.md.claude/agents/自定义子代理人设与工具集合MCP 服务通过claude mcp add注册接入外部工具与数据源如果你刚开始不用所有东西都上。我的建议是先做 CLAUDE.md 和 settings.json 的权限再补斜杠命令最后根据实际痛点决定要不要上 hooks 和 MCP。下面按这个顺序讲。2. CLAUDE.md把项目约定焊进 AI 的长期记忆2.1 为什么默认状态下它总是“记不住”很多人的第一个困惑是我跟 Claude Code 说了八百遍“用 pnpm 不要用 npm”换个会话它又用 npm 了。原因在于 Claude Code 默认不会把上一个会话的全部内容带进下一个会话。每个新会话都像新入职的员工你之前在对话里交代的上下文session 一结束就散场了。真正能跨会话保持一致的是写入文件的东西。CLAUDE.md 就是这个“写入文件”的机制——它会在每次会话开始时被自动加载到上下文里相当于 AI 的入职手册。理解这一点很重要。你要沉淀的不是“让 AI 记住对话内容”而是“把约定沉淀成文件让 AI 每次开工前都读一遍”。2.2 记忆分层的正确姿势CLAUDE.md 不是只允许有一个。官方设计里用户主目录~/.claude/CLAUDE.md和项目根目录CLAUDE.md都会被读取前者面向个人后者面向项目。还可以用路径的导入语法把更细粒度的约定拆成多个小文件按需组合。我实践中比较顺手的组织方式是这样的~/.claude/CLAUDE.md只放跨项目通用的个人偏好比如“输出使用中文技术术语保留英文原文”。项目根目录CLAUDE.md放团队级约定比如技术栈、目录结构、测试要求、提交信息规范。项目内docs/下拆几个专题文件比如docs/coding-standards.md、docs/deployment.md然后在根目录的 CLAUDE.md 里用docs/coding-standards.md引入。这样做的最大好处是“按需加载”。全部堆在一个巨型 CLAUDE.md 里不是不行但会白白占用上下文窗口而且太多琐碎信息反而会稀释真正重要的约定。官方在文档里也明确建议CLAUDE.md 要“具体、简短、避免空泛描述”。2.3 怎么写才有效少讲道理多给约束写 CLAUDE.md 最容易犯的错是写“正确的废话”。比如“请写出高质量的代码”这句话对模型几乎没有任何约束力因为它不知道在你的项目里“高质量”具体意味着什么。有效的写法是给出可验证、可执行的规则。举个例子# 项目约定 - 包管理器一律使用 pnpm不要使用其他包管理器不要提交额外的版本锁文件 - 测试新增功能必须同时提交对应的单元测试测试文件放在 src/__tests__/ 下文件名为 xxx.test.ts - Git 提交提交信息使用 Conventional Commits 格式例如 feat(login): 支持短信验证码登录 - 禁止事项不要修改 generated/ 与 vendor/ 目录下的任何文件 - 常用命令pnpm lint 检查代码风格pnpm typecheck 做类型检查CI 跑全量命令每条规则都能判断对错用了别的包管理器就是违反没写测试就是违反提交格式不对就是违反。AI 在执行任务时会逐条比对这些约束这比一句“请遵守项目规范”有效得多。2.4 实测中的两个提醒第一个提醒CLAUDE.md 里写“禁止”类规则时最好同时给出替代方案。如果只写“不要手动修改某文件”AI 遇到需要修改的场景会犹豫甚至反复问你如果补一句“如需改动请先向用户确认”行为就会明确很多。第二个提醒CLAUDE.md 本身也是文件会随着项目演进。我习惯每隔一段时间主动让 Claude Code 审一遍 CLAUDE.md把已经过时的命令、目录、约定更新掉避免它拿着半年前的规范指挥现在的项目。提示CLAUDE.md 不是一次性写完就完事的“遗嘱”它更像你带新人时不断更新的团队手册需要随项目一起演进。3. 自定义斜杠命令把高频操作做成“一键触发”3.1 斜杠命令和普通对话的区别CLAUDE.md 解决的是“记忆”问题斜杠命令解决的是“动作”问题。比如“审查一下刚才的改动”这种操作如果每次都用自然语言描述不仅啰嗦而且描述一含糊AI 的理解就飘。把这类高频操作固化成/review这种斜杠命令输入三个字就能触发一套固定动作。自定义斜杠命令的实现方式是把 Markdown 文件放进.claude/commands/目录文件名去掉.md后缀就是命令名。比如.claude/commands/review.md对应/review.claude/commands/commit.md对应/commit。子目录也可以给命令分组具体分隔符以当前版本的命令提示为准。3.2 命令文件的结构与 frontmatter一个自定义命令文件由两部分组成开头的 YAML frontmatter 和正文内容。frontmatter 里可以声明这个命令的描述、参数提示、可用工具、模型等元信息。看一个实际例子这是一个“按团队规范提交代码”的命令文件--- description: 生成符合规范的 Git 提交信息并提交 argument-hint: 建议的提交描述可省略 allowed-tools: Bash(Git:*), Read --- 根据用户提供的信息和当前 git diff完成以下步骤 1. 运行 git status 和 git diff --stat了解改动范围 2. 运行 git diff 查看具体改动内容 3. 结合 CLAUDE.md 中约定的提交信息格式生成一条 Conventional Commits 提交信息 4. 如果用户通过参数提供了描述信息$ARGUMENTS把它融入提交信息如果参数为空根据改动内容自行概括 5. 确认后执行 git commit注意这里用了$ARGUMENTS这个变量它会把你在/commit 添加登录页表单校验中斜杠后面的文字原样替换进正文。类似的变量还有$CWD当前工作目录等具体有哪些以当前版本文档为准。这套变量机制是斜杠命令真正好用的前提——它让命令文件从“写死的脚本”变成了“可接收输入的模板”。3.3 用好 allowed-tools 限制命令的工具范围frontmatter 里的allowed-tools很多人会忽略但对安全性和稳定性非常关键。比如一个只负责审查代码的命令就不应该让它有编辑文件的权限一个只负责生成提交信息的命令限制它能执行Git:系列工具就够了。这样即使 AI 在生成步骤上产生偏差工具权限也会帮你兜底。有个细节值得注意allowed-tools限制的是该命令执行期间的工具调用范围所以我把审查类命令的 allowed-tools 经常写成Read, Bash(Git:*)这样它能读文件、能跑 Git 命令但改不了源代码出了差错也不会弄脏工作区。3.4 一套我实际在用的命令组合在我自己维护的几个项目里最常用的三组命令是/review审查当前分支的改动按 CLAUDE.md 约定逐条检查输出问题清单和修改建议。/commit生成提交信息并提交上面示例就是。/explain 路径解释某个模块的设计思路输出包含调用关系、关键逻辑、潜在风险的说明文档。每一组命令文件都不长但把高频动作模板化以后Claude Code 的输出质量明显稳定了一个台阶。原因在于自然语言对话里 AI 的注意力会被你冗长的描述分散而命令文件把步骤写死了它只需要按剧本执行。4. settings.json 与权限模型让助手既能干活又守规矩4.1 权限分级allow、deny、ask 到底怎么选Claude Code 的权限模型是整个自定义体系里最值得花时间研究的部分。它的核心概念是三类规则allow允许直接执行、deny禁止执行、ask执行前必须询问用户。这三类规则一般写在 settings.json 的permissions字段里。我的经验是遵循“最小必要”原则对完全可信、重复执行且无破坏性的操作用 allow比如Bash(pnpm test)、Read(src/**)。对高风险操作用 deny 或者 ask比如Bash(rm -rf *)、Write(prod-config/**)。拿不准的操作宁可 ask 也不 allow多问一句的成本远低于一次误操作。具体写法大致是这样{ permissions: { allow: [ Read(./src/**), Bash(pnpm test), Edit(./src/**) ], deny: [ Bash(pnpm deploy), Write(./generated/**) ], ask: [ Bash(npm run db:*), Write(./config/prod/**) ] } }有一个反模式要特别提一下很多人图省事用跳过权限确认的全局参数来跑任务等于把整个权限系统关掉。一次性可信任务可以用但我强烈不建议把它当成日常默认姿势。权限系统存在的意义不是烦你而是在你注意力不集中的时候拦住 AI 的误操作。4.2 常用配置项逐条解读除了 permissionssettings.json 里还有几个高频配置项我把实际用过的整理成一张表配置项作用我常用的值model设定默认模型通过 /model 选好后写入maxTurns单次任务最大轮数上限50-100includeCoAuthoredBy是否在提交信息里附带 AI 协作署名falsecleanupPeriodDays清理历史会话的周期30statusLine自定义状态栏显示内容见本文第 7 节hooks工具调用前后触发的外部命令见本文第 5 节env注入特定环境变量视项目而定配置这些项有两个入口直接编辑 settings.json或者用命令行claude config set来修改。命令行方式的好处是不会写错 JSON适合快速调整直接编辑文件的好处是可以批量修改、方便评审。两者效果是等价的看你习惯哪一种。4.3 优先级与“一问三不知”的坑有一个经典坑项目级 settings.json 里配了权限但用户级 settings.json 里也有同样的规则名最后实际生效的是谁答案是用户级和项目级会合并但同一类规则里更具体的匹配模式优先级更高。如果出现“我以为我配了 deny它却照样执行”的情况八九不离十是另一层配置里有 allow 规则覆盖了它。排查这种问题有个笨但有效的办法直接问 Claude Code 自己用/config或让它读取当前所有 settings 文件并列出生效的权限规则。它能把多层配置合并后的最终结果解释得明明白白比人眼扫 JSON 高效多了。5. Hooks在工具调用前后“做手脚”5.1 Hook 触发的几个关键时机settings.json 里另一块强大但容易踩坑的能力是 hooks。你可以把 hooks 理解成“钩子”当某个事件发生时Claude Code 先执行一段你指定的外部命令根据这个命令的输出决定后续行为。常见的钩子类型包括用户提交提示词之后、某个工具被调用之前、某个工具执行完毕之后、会话结束时等。每一类钩子都能匹配具体的工具或事件。它们非常适合做一件事把“人的检查”编码成“自动检查”。5.2 一个真实例子拦截危险数据库操作拿“工具调用前”这个钩子举例。假设你的项目里有个脚本scripts/run-migration.sh只能在特定环境下执行你担心 AI 在排查问题时手滑跑到生产库上。可以在 settings.json 里加一个钩子{ hooks: { PreToolUse: [ { matcher: Bash, command: if echo \$CLAUDE_TOOL_INPUT\ | grep -qE production|prod; then echo block; fi } ] } }这段命令的逻辑是每次 Bash 工具执行前先检查工具的输入内容里是否包含production或prod关键字如果包含就输出block。Claude Code 的这个钩子一旦在标准输出里看到block就会阻止这次工具调用。这个机制非常灵巧——它没有把判断逻辑写死在程序里而是把“什么情况算危险”的裁量权完全交给了你的 shell 脚本。5.3 Hook 的常见误区和调试方法Hook 最大的坑是超时和静默失败。默认情况下钩子命令有超时限制如果你的脚本里有个慢操作比如网络请求钩子会被杀掉而 Claude Code 往往会直接放行工具调用造成“钩子失效”的假象。我在项目里就遇到过写了个做在线检查的钩子结果对方服务响应稍慢钩子超时危险命令照常执行。后来把超时调大并把钩子脚本的日志写到独立文件里才彻底修复。另一个误区是把钩子写得太复杂。钩子里只应做“判断”和“简单处理”不要在里面跑重量级逻辑。它每次工具调用都可能触发如果每触发一次就消耗几百毫秒整个会话的响应速度会肉眼可见地变慢。调试钩子时可以先在终端里手动执行一下钩子命令确认输出格式和判断逻辑正确再挂到配置文件里。我踩过太多次“脚本单独跑没问题挂到 hooks 里不生效”的坑了排查下来全是路径问题——钩子里用了相对路径但 Claude Code 执行钩子时的工作目录和你手动的终端不一定一样。6. 接入 MCP给 Claude Code 接上“外部器官”6.1 MCP 到底解决了什么问题CLAUDE.md 给了记忆斜杠命令给了动作权限和 hooks 给了约束但 Claude Code 能接触的世界仍然只有文件系统、终端这些本地资源。当你希望它直接查数据库、搜索内部文档、操作远程服务时就需要 MCP模型上下文协议。MCP 的定位可以理解成“AI 的工具插座”它定义了一套标准化的协议让各种外部能力数据库、浏览器、API 服务都能以统一的方式被 AI 调用。对 Claude Code 来说接入一个 MCP 服务器就等于给它新长了一只手。6.2 接入姿势stdio 传输 本地进程实际项目中最常用的接入方式是通过claude mcp add命令注册一个本地进程。基本结构是这样的claude mcp add local-db --scope project -- dbserver --db-path ./data/app.db这条命令把名为local-db的 MCP 服务器注册到当前项目--scope project启动方式是通过 stdio 传输运行dbserver这个进程并传入了数据库路径参数。注册完成后可以用claude mcp list查看所有已连接的服务。选择--scope project而不是默认值很重要。项目范围意味着这个 MCP 连接只对当前项目生效团队其他人拿到仓库后不需要手动配置用户范围则是你个人所有项目都能用适合接个人常用的服务。6.3 我的实测体验与建议我在一个内部工具项目里接了一个关系型数据库服务和本地文档检索服务。实测下来接数据库之后 Claude Code 写查询语句的能力提升是质的它可以直接查看表结构、实际跑查询、根据结果调整语句而不是凭记忆猜字段名。接文档检索之后它回答内部知识类问题的准确率也高了很多。但这里有个很重要的提醒MCP 给 AI 的权力很大它相当于把外部系统的操作权限交到了模型手里。所以我对 MCP 的建议和权限模型的态度一致——只接入必要的服务能用只读权限就不要用读写权限在配置里尽量让相关操作落在 ask 规则里让关键写操作过一道人工确认。7. 个性化表达模型、输出风格与状态栏7.1 模型绑定不同任务用不同脑子Claude Code 默认使用的模型不一定适合你的所有场景。需求明确、逻辑复杂的大任务用能力更强的模型批量格式化、简单重构这类任务用响应更快的模型成本和速度都更划算。切换模型有两个层面会话内用/model随时切换或者直接在 settings.json 里写入默认模型。我通常的做法是把默认模型设为均衡型然后在斜杠命令的 frontmatter 里通过model字段给特定命令指定专用模型。比如代码审查命令用更强的模型日常小修小改用默认模型。这样“按任务分派模型”的思路实际效果比全局一个模型好很多。7.2 输出风格别让 AI 写一堆“正确的废话”Claude Code 在回答问题时默认输出风格偏“清单体”简洁但有时候简过头。如果你需要它输出结构更完整的文档、带小标题的长文、或者面向特定读者群体的内容可以利用输出风格机制。最简单的入口是会话内使用/output-style命令它会引导你指定想要的风格并生成配置。之后 Claude Code 的输出会明显贴合你的偏好——比如我在写技术方案时用“先给结论、再列背景、最后给实施步骤”的风格生成出来的文档基本可以直接进项目文档库不用大改。7.3 状态栏脚本把关键信息钉在眼皮底下在终端里使用 Claude Code 时底部会有一个状态栏。这个状态栏的内容也是可以定制的通过 settings.json 里的statusLine字段指定一段命令命令的输出会实时显示在状态栏里。我遇到的一个实际需求是每次让 AI 跑长任务时我总想知道当前这个会话烧了多少 token。后来写了个小脚本从会话数据里捞 token 用量通过 statusLine 显示出来。跑大批量重构的时候看一眼状态栏就能决定要不要切到更便宜的模型。除了 token 用量常见的状态栏内容还有当前分支、未提交文件数等。statusLine 的配置大致长这样具体字段名以当前版本文档为准{ statusLine: { type: command, command: scripts/claude-status.sh, timeout: 5000 } }这里有个容易忽略的点状态栏命令在每次渲染时都可能被执行所以脚本一定要轻量。如果你放一个跑 10 秒的脚本进去整个界面都会跟着卡顿。8. 团队共享与版本演进自定义配置的工程化8.1 让整套配置跟着仓库走当自定义配置不止服务于你一个人时就要考虑工程化了。我的做法是把.claude/下的 settings.json、commands、CLAUDE.md、agents、skills 全部纳入版本管理跟随仓库一起提交。新成员拿到仓库Claude Code 自动就有完整的团队约定和命令集。有一个细节很容易踩坑哪些文件该提交、哪些不该提交一定要分清。settings.local.json和个人相关的密钥绝对不能提交。我在团队里见过把本地调试用的数据库连接信息写进 settings 然后推到仓库的情况教训相当惨痛。正确的做法是敏感信息一律走环境变量配置文件里只存变量名。8.2 基于实际反馈迭代配置自定义配置不是写一次就完事的。随着项目演进和技术栈调整配置里的规则一定会过时。我现在每隔两到三周会专门花半小时“审配置”让 Claude Code 基于最近的会话记录和代码变化列出 CLAUDE.md 里可能过时的条目再人工确认哪些要改。这个过程成本极低但能让整套自定义体系始终保持鲜活。8.3 最后一条经验如果让我只说一条关于 Claude Code 自定义的经验那就是从小处开始遇到痛点才加配置不要第一天就堆出一套庞然大物。先写一个二十行的 CLAUDE.md观察两天再补一个自己最常重复的命令用顺手了再碰 hooks 和 MCP。配置这东西密度越高上下文占用越大排查成本也越高。真正好的自定义不是把每个功能都塞满而是让每个配置项都恰好对应一个真实痛点。我自己的配置也是这么一步步长起来的最开始只有一段 CLAUDE.md后来陆续加了提交规范命令、权限规则、数据库 MCP、工具调用前钩子。每次加一样东西都是因为实际项目里真的被坑过、真的需要。这种需求驱动的配置方式比照着文档把所有功能全开一遍要靠谱得多。