密钥与配置:别让工具覆盖你的设置
密钥只放环境变量或钥匙串,配置切换工具可能整份重写你的设置
密钥只放两个地方:环境变量(本地是不进 git 的 .env,线上是部署平台的环境变量)和系统钥匙串。不要写进代码、CLAUDE.md、settings.json,或任何会被同步、备份、复制的配置文件。另外要防两件容易忽略的事:配置切换工具可能整份重写你的 ~/.claude/settings.json;各种备份文件里,常常躺着明文密钥。
密钥放哪
| 场景 | 放哪 |
|---|---|
| 项目运行时用的密钥(数据库、第三方 API) | .env,第一天就加进 .gitignore;线上用部署平台的环境变量 |
| 本机命令行工具的 token | macOS 钥匙串,用的时候再取 |
| MCP 服务的凭证 | 优先用 OAuth,在 /mcp 里授权;必须用 token 时,在项目的 .mcp.json 里写 ${API_KEY},引用环境变量 |
| CI | 代码托管平台的 secrets |
注意 claude mcp add 的 -H "Authorization: Bearer ..." 和 -e KEY=...:它们会把值明文写进 ~/.claude.json,用户级和本地级的 MCP 配置都存在这个文件里(见官方文档)。
macOS 钥匙串:security 命令
# 存入。-w 放在最后,会提示你输入,密钥不会留在 shell 历史里
security add-generic-password -a "$USER" -s cloudflare-api-token -w
# 更新已有的条目:加 -U
security add-generic-password -U -a "$USER" -s cloudflare-api-token -w
# 取出:只输出密钥本身
security find-generic-password -a "$USER" -s cloudflare-api-token -w
# 删除
security delete-generic-password -a "$USER" -s cloudflare-api-token用的时候只在那一条命令里取,不要导出成全局环境变量:
CLOUDFLARE_API_TOKEN="$(security find-generic-password -a "$USER" -s cloudflare-api-token -w)" wrangler deploy别让 agent 把密钥打印出来
Claude 运行命令的输出会进对话记录,而对话记录以 jsonl 文件保存在 ~/.claude/projects/ 下。让它单独执行一次 security find-generic-password ... -w,密钥就留在了对话记录里。只在 $(...) 里取用;更稳的做法是给这条命令加一条 ask 规则 Bash(security find-generic-password *)。ask 规则对 $(...) 里的子命令同样生效,Claude 每次要取密钥都得你点头。
配置切换工具会整份覆盖设置
我用一个模型供应商切换工具(CC Switch 这类)从第三方模型切回官方时,它把 ~/.claude/settings.json 整份重写了:权限规则、hook、插件启用状态全部丢失。表面症状只是“所有插件都关了”,过了很久我才意识到,护栏也跟着没了(见切换工具会整份覆盖设置)。
公平地说,CC Switch 现在的文档(截至 2026-10)写的是:切换时只改连接相关的字段,权限、hook、插件启用状态都不动。但这类工具的合并逻辑会随版本变化,也可能有 bug。规则不变:切换之后检查一遍。
# 切换后,看权限、hook、插件还在不在
jq '{deny: .permissions.deny, hooks: (.hooks // {} | keys), plugins: .enabledPlugins}' ~/.claude/settings.json更彻底的做法有两个:
- 试用中 关键的 deny 规则和体检 hook 放进托管设置。切换工具只写用户级文件,碰不到它(写法见权限规则)
- 业界做法 不让工具改
settings.json。Claude Code 也从环境变量读ANTHROPIC_BASE_URL和ANTHROPIC_AUTH_TOKEN,可以给每个供应商写一个 shell 函数,token 放钥匙串,启动时临时注入。前提是settings.json的env里没有残留的同名变量
# 放进 ~/.zshrc;地址换成供应商给你的
claude-alt() {
ANTHROPIC_BASE_URL="https://api.example.com" \
ANTHROPIC_AUTH_TOKEN="$(security find-generic-password -a "$USER" -s alt-provider-token -w)" \
claude "$@"
}备份文件里也可能留着明文密钥
密钥常常藏在你想不到的地方:
~/.claude/settings.json的env:供应商切换工具会把第三方的 key 明文写在这里- 这个文件的各种副本:你手动备份的
settings.json.bak,以及切换工具自己的备份。据 CC Switch 的文档,它第一次改写配置前会备份原文件,数据库和备份都放在~/.cc-switch/下 ~/.claude.json:用-H、-e添加的 MCP 凭证。Claude Code 每次写这个文件之前,会在~/.claude/backups/里留一份备份,保留最近 5 份- 对话记录:
~/.claude/projects/下的 jsonl,前提是密钥曾经被打印出来 - shell 历史:直接敲过的
export TOKEN=...,或者把密钥写在-w后面的命令
查一下哪些文件里有疑似密钥的字段。-l 只列文件名,不会把内容打印出来:
grep -rlE 'TOKEN|API_KEY|SECRET|PASSWORD' ~/.claude/settings.json ~/.claude.json ~/.claude/backups ~/.cc-switch 2>/dev/null找到之后,先轮换密钥,再删文件。密钥一旦落进备份、同步盘或别人可能看到的地方,删掉文件也收不回来。之后把密钥搬进钥匙串或环境变量,旧备份定期清理。如果你用 dotfiles 仓库同步 ~/.claude/,把 settings.json 的 env、~/.claude.json 和 backups/ 都排除在外。