1. 为什么你的 Claude Code 每次都要重新解释项目
Claude Code 是 Anthropic 推出的终端原生 AI 编程助手,它跑在命令行里,能直接读写文件、执行 shell 命令、创建 git 提交。但很多人第一次用完之后会有个共同的困惑:明明昨天刚跟它讲过"这个项目用 pnpm 不用 npm""接口错误统一返回{code, message}",今天开个新会话,它又按默认习惯给你生成一堆 npm 命令和裸抛异常。
问题不在模型,在于你没把项目约定沉淀下来。Claude Code 每次会话启动时会读取一个叫CLAUDE.md的记忆文件,以及.claude/settings.json里的配置。这两个东西不写,它就等于每次都在"空手"进你的仓库。这篇就围绕 CLI 环境下的配置落地来讲:怎么写出能真正生效的CLAUDE.md,怎么用 Slash Commands 把高频操作固化成一条命令,以及怎么逐条验证它们确实被加载了。
适合谁看:已经在终端里跑过claude命令、但还没系统配置过项目记忆和自定义命令的开发者。如果你连安装都还没做,先npm install -g @anthropic-ai/claude-code,然后claude --version确认能打印版本号再往下看。
2. 前置准备:把 CLI 和项目目录理顺
2.1 确认运行环境
Claude Code 对 Node 版本有要求,低于 18 会在启动时报错。用 nvm 切到 22 LTS 最稳:
nvm install 22 nvm use 22 node -v # 期望输出 v22.x.xWindows 用户注意:原生 PowerShell 下部分命令行为不一致,建议在 WSL2 或 Git Bash 里操作,路径分隔符和权限模型都更接近文档描述。
2.2 进入项目并初始化
cd your-project claude首次启动会走一次授权流程,完成后令牌会缓存到本地,后续不用重复登录。进去之后先别急着让它写代码,第一件事是执行/init:
/init这个命令会在项目根目录生成一个初始的CLAUDE.md,内容是根据你仓库结构自动推断出来的项目描述、技术栈和常见模式。自动生成的东西只能算草稿,真正有价值的是你手动往里补的规则。
2.3 关于模型接入的一点说明
Claude Code 默认走 Anthropic 官方接口。如果你希望通过兼容协议接入其他模型服务,可以在~/.claude/settings.json里配置ANTHROPIC_BASE_URL和ANTHROPIC_AUTH_TOKEN两个环境变量指向对应的 API 端点。TaoToken 提供了 Anthropic 兼容的 API 接入方式,控制台里可以创建密钥:
接入文档:https://taotoken.net/api 密钥管理:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
配置好之后,/model命令切换模型时就会走你设定的端点。这一步不是必须的,但如果你手头有多个模型想对比着用,提前配好省得来回改。
3. 可复制的 settings.json 骨架
3.1 配置文件的三层结构
Claude Code 的配置分三层,优先级从低到高:
| 路径 | 用途 | 是否提交 Git |
|---|---|---|
~/.claude/settings.json | 全局个人偏好 | 否 |
项目.claude/settings.json | 团队共享配置 | 是 |
项目.claude/settings.local.json | 本地个人覆盖 | 否(加进 .gitignore) |
团队规范放中间那层,个人习惯放最上面或最下面那层。这样别人 clone 你的仓库后能直接继承团队约定,又不会把你的本地路径带进去。
3.2 一份能直接用的骨架
在项目根目录建.claude/settings.json,写入:
{ "permissions": { "defaultMode": "acceptEdits", "allow": [ "Read", "Glob", "Grep", "Edit", "Bash(git status)", "Bash(git diff *)", "Bash(pnpm run *)", "Bash(pnpm test *)" ], "deny": [ "Read(**/.env*)", "Read(**/.ssh/**)", "Read(**/*.pem)", "Bash(sudo *)", "Bash(rm -rf *)" ] }, "hooks": { "PostToolUse": [ { "matcher": "Write(*.ts)", "hooks": [ { "type": "command", "command": "npx prettier --write $file" } ] } ] } }几个关键点解释一下。defaultMode设成acceptEdits表示文件修改自动接受,但 shell 命令仍然要确认——这是安全和效率的折中。allow里我特意把Bash(pnpm run *)这种带通配的放进去,因为日常跑脚本太频繁,每次都点确认很烦。deny里把.env、.ssh、.pem全部挡掉,防止模型在探索代码库时把密钥读进上下文。
hooks里的PostToolUse是文件写入后的自动格式化。$file是 Claude Code 注入的变量,代表刚被修改的文件路径。注意 matcher 写的是Write(*.ts),只对 TypeScript 文件生效,避免误格式化 JSON 或 Markdown。
3.3 权限模式的选择
defaultMode有三个常用值:
default:每次修改和命令都确认,最安全,适合刚上手或敏感仓库acceptEdits:文件修改自动执行,shell 命令仍需确认,日常开发推荐plan:只读模式,只分析不改动,适合读陌生项目
我试过在重构老项目时先用plan模式让它把架构梳理清楚,确认方案后再切acceptEdits执行,比一上来就让它动手稳得多。
4. CLAUDE.md 模板:让项目记忆真正生效
4.1 自动生成只是起点
/init生成的CLAUDE.md通常长这样:项目名、技术栈、目录结构说明。这些信息模型从代码里也能推断出来,价值有限。真正要补的是那些"代码里看不出来、但你必须遵守"的约定。
4.2 一份带具体规则的模板
把下面这段追加到CLAUDE.md末尾,按你项目实际情况改:
# 项目约定 ## 包管理 - 使用 pnpm,禁止使用 npm 或 yarn - 新增依赖前先确认是否已有同类库 ## 认证 - 使用 JWT,不使用 session - token 存储在 httpOnly cookie 中 - 刷新逻辑统一走 src/auth/refresh.ts ## 错误处理 - API 返回结构化错误:{ code: number, message: string } - 禁止直接 throw 字符串 - 网络层错误统一在 src/api/errorHandler.ts 处理 ## 测试 - 所有 API endpoint 必须有测试 - 使用 Vitest,不使用 Jest - 测试文件与被测文件同目录,命名 *.test.ts ## 代码风格 - 函数参数超过 3 个时改用对象传参 - 禁止 any,必要时用 unknown 加类型守卫4.3 为什么这些规则能被记住
Claude Code 每次会话启动时会读取CLAUDE.md并注入上下文。所以你在里面写的每一条,都相当于每次对话开头都跟它重申一遍。规则要写得可执行——"使用 pnpm"比"注意包管理规范"有用得多,因为前者是明确指令,后者模型只能猜。
一个容易踩的坑:CLAUDE.md不要写太长。它占的是上下文窗口,写个几百行会把真正有用的代码空间挤掉。只放高频、易错、代码里看不出的约定,其余交给模型自己读代码。
4.4 用 /memory 快速编辑
不想退出会话去改文件,直接在交互模式里敲:
/memory它会打开CLAUDE.md供你编辑,保存后当前会话立即生效,不用重启。
5. Slash Commands 自定义命令实战
5.1 内置命令先摸一遍
在会话里输入/会列出所有可用命令。常用的几个:
| 命令 | 作用 |
|---|---|
/init | 生成 CLAUDE.md |
/compact | 压缩对话历史,回收上下文 |
/clear | 完全清空对话 |
/context | 查看当前上下文用量 |
/model | 切换模型 |
/doctor | 诊断安装和配置问题 |
/cost | 查看本次会话 token 消耗 |
/compact有个进阶用法,可以指定保留什么:
/compact preserve all architecture decisions, file paths, and error messages这样压缩后关键信息不会丢。建议在/context显示用到 70% 左右时就压,别等满了再处理。
5.2 自定义命令放在哪
自定义 Slash Command 本质是一个 Markdown 文件,放在.claude/commands/目录下,文件名就是命令名。比如建.claude/commands/review.md,之后就能用/review调用。
5.3 写一个代码审查命令
创建.claude/commands/review.md:
--- description: 对指定文件做三重审查 --- 请对 $ARGUMENTS 执行以下审查,逐项输出结果: 1. 类型安全:是否存在 any、类型断言滥用、未处理的 null 2. 错误处理:是否有未捕获的 Promise rejection、裸 throw 3. 边界条件:空数组、超长输入、并发调用是否处理 对每个问题给出:文件路径:行号、问题描述、修复建议。 不要直接修改文件,先列清单。$ARGUMENTS是调用时传入的参数。用法:
/review src/api/user.ts它会把src/api/user.ts替换进$ARGUMENTS的位置。description字段会显示在/命令列表里,方便记忆。
5.4 写一个提交前检查命令
创建.claude/commands/precommit.md:
--- description: 提交前跑一遍检查清单 --- 按顺序执行: 1. 运行 `pnpm lint`,如有报错逐条修复 2. 运行 `pnpm test`,确认全部通过 3. 检查 git diff,确认没有遗留的 console.log 和调试代码 4. 生成一条符合 Conventional Commits 规范的提交信息 每步完成后报告结果,遇到失败停下来等我确认。这个命令把提交前的重复劳动固化了。注意最后一句"遇到失败停下来等我确认"——不加这句,模型可能会自作主张跳过失败的测试继续往下走。
5.5 命令的验证方式
写完命令文件后,在会话里敲/看列表里有没有出现你定义的命令名和 description。有就说明加载成功。然后实际调用一次,观察$ARGUMENTS是否正确替换。
6. 逐条验证配置是否生效
配置写完不验证,等于没配。下面几条命令按顺序跑一遍。
6.1 验证 CLAUDE.md 被读取
在会话里直接问:
我们这个项目用什么包管理器?如果CLAUDE.md里写了"使用 pnpm",它应该回答 pnpm 而不是 npm。答错了说明文件没被读到,检查是不是放在了项目根目录、文件名大小写是否正确。
6.2 验证权限规则生效
让它尝试读一个被 deny 的文件:
读一下 .env 文件的内容正常情况应该被拦截,提示权限不足。如果它真读出来了,检查deny规则里的 glob 写法,Read(**/.env*)里的**是匹配任意层级目录。
6.3 验证 hook 触发
让它创建一个测试用的 TS 文件:
在 src 下创建一个 tmp-test.ts,内容随便写个函数创建完成后,打开那个文件看格式是否被 prettier 处理过(比如缩进、分号风格统一)。没变化的话,检查 hook 里的command路径能不能在项目根目录直接执行。
6.4 验证自定义命令
/review src/index.ts观察它是否按你定义的三个维度输出审查清单,而不是泛泛地评价代码。
6.5 环境异常先跑 /doctor
如果上面任何一步行为诡异,先执行:
/doctor它会检查安装完整性、配置语法、权限设置,是环境问题的第一排查手段。
7. 本篇常见报错与排查
7.1 settings.json 语法错误导致配置静默失效
JSON 不允许尾随逗号,多一个逗号整个文件就解析失败,而且 Claude Code 不一定会明确报错,表现是配置"看起来没生效"。排查方法:
cat .claude/settings.json | python3 -m json.tool能正常格式化输出说明语法没问题,报错就按提示的行号改。
7.2 CLAUDE.md 写了但模型不遵守
先确认文件位置对:必须是项目根目录的CLAUDE.md,不是.claude/CLAUDE.md。其次检查规则是否可执行——"代码要优雅"这种模型没法执行,"函数参数超过 3 个改用对象传参"才能落地。最后看长度,超过几百行时关键规则可能被稀释,精简一下。
7.3 自定义命令不出现
三个检查点:文件是否在.claude/commands/目录下、扩展名是否是.md、frontmatter 的---是否成对闭合。少一个闭合的---,整个文件会被当成普通文本而不是命令定义。
7.4 hook 里的 $file 没被替换
$file只在PostToolUse且 matcher 匹配到具体文件时才注入。如果你写的 matcher 是Write(*)但实际触发的是Edit工具,就不会替换。确认 matcher 里的工具名和实际操作一致。
7.5 上下文很快用满
/context看用量,超过 70% 就/compact。另外检查CLAUDE.md是不是太长,以及有没有把大文件整个读进上下文。精准引用文件用@src/utils/auth.ts这种写法,比让它自己 Glob 搜索省得多。
8. 把配置沉淀成团队资产
配置这件事的价值在于复用。CLAUDE.md和.claude/settings.json提交到 Git 后,新同事 clone 下来第一次跑claude就自动继承了团队约定,不用口头交接。自定义命令同理,/review、/precommit这些固化了团队流程的命令,比写在文档里没人看强得多。
如果你还在对比不同模型在代码任务上的表现,可以在 TaoToken 控制台创建密钥后,通过/model切换着试:
模型对话体验:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 接入文档:https://taotoken.net/api
长期跑编码任务、需要稳定额度的话,Coding Plan 更适合日常高频使用:
Coding Plan:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite
配置落地之后,你会发现 Claude Code 真正好用的地方不是它能写多少代码,而是它记住了你项目的规矩,不用每次从头解释。