一句话定位:用一套
.env + source ~/.zshrc的模式,统一管理 Claude Code、OpenCode、Docker、MCP Server 等所有 AI 工具的 API Key,告别明文硬编码。
核心理念:密钥是基础设施,不是代码——一切 secret 只应存在于一个地方,一切消费者只应通过环境变量读取。

3分钟速览版
点击展开核心概念
核心架构
graph TB
ENV["~/.config/opencode/.env
(唯一密钥源)"]
ZSHRC["~/.zshrc
(set -a; source .env; set +a)"]
CC["Claude Code
${ZHIPU_API_KEY}"]
MCP["MCP Server
env:CONTEXT7_API_KEY"]
DOCKER["Docker Compose
${MYSQL_PASSWORD}"]
OC["OpenCode
直接读 env"]
PROFILE["cc-switch profiles
dev.env / prod-guard.env"]
ENV --> ZSHRC
ZSHRC --> CC
ZSHRC --> MCP
ZSHRC --> DOCKER
ZSHRC --> OC
ZSHRC --> PROFILE
style ENV fill:#ffcdd2
style ZSHRC fill:#bbdefb
style CC fill:#c8e6c9
style MCP fill:#c8e6c9
style DOCKER fill:#c8e6c9
style OC fill:#c8e6c9
style PROFILE fill:#c8e6c9
**🖼️ 插图版(2026-04-17 增量补充)**

方案对比速查
| 方案 | 适用场景 | 复杂度 | 团队协作 | 审计能力 |
|---|---|---|---|---|
.env + source |
个人开发者 / 本地开发 | 低 | 低 | 低 |
| dotenv-vault | 小团队、跨设备同步 | 中 | 中 | 中 |
| Doppler | 中型团队、多环境 | 中 | 高 | 高 |
| HashiCorp Vault | 企业级、合规要求 | 高 | 高 | 高 |
| AWS Secrets Manager | AWS 生态、生产环境 | 中 | 高 | 高 |
决策树
graph TD
Start["你的场景是?"] --> Q1{"团队规模"}
Q1 -->|"个人 / 2-3人"| A1["dotenv + source zshrc"]
Q1 -->|"5-20人"| Q2{"需要审计?"}
Q1 -->|"20+人"| A3["HashiCorp Vault / AWS SM"]
Q2 -->|"否"| A4["dotenv-vault / Doppler Free"]
Q2 -->|"是"| A5["Doppler / Vault"]
style A1 fill:#c8e6c9
style A3 fill:#ffcdd2
style A4 fill:#fff9c4
style A5 fill:#fff9c4
**🖼️ 插图版(2026-04-17 增量补充)**

深度剖析版
1. 问题:AI 工具的密钥散落各处
1.1 典型的混乱现状
当你同时使用 Claude Code、OpenCode、Cursor、MCP Server、Docker 等工具时,API Key 往往散落在:
~/.zshrc中export API_KEY="sk-xxx"明文导出settings.json中硬编码 tokendocker-compose.yml中直接写密码- MCP 配置文件中嵌入 bearer token
- 项目
.env文件被不小心提交到 Git
1.2 这很危险
graph LR
A["明文 Key
散落各处"] --> B["git push"]
B --> C["GitHub 公开仓库"]
C --> D["爬虫扫描"]
D --> E["Key 被盗用"]
E --> F["账单暴涨 / 数据泄露"]
style A fill:#ffcdd2
style E fill:#ffcdd2
style F fill:#ffcdd2
**🖼️ 插图版(2026-04-17 增量补充)**

根据 OpenAI 官方安全指南,被泄露的 API Key 可导致:
- 未授权调用消耗你的配额
- 意外的高额账单
- 数据被第三方访问
1.3 我们需要什么
我们需要一个「一个密钥源 + 多个消费者」的架构:所有 Key 存在一个 .env 文件中,所有工具通过环境变量读取。
2. 架构设计:.env + source ~/.zshrc
2.1 文件布局
1 | ~/.config/opencode/.env # 唯一密钥源(全局) |
2.2 加载机制
graph TD
A["用户打开终端"] --> B["执行 source zshrc"]
B --> C["set -a 开启自动export"]
C --> D["source .env文件"]
D --> E["set +a 恢复"]
E --> F["环境变量加载到环境"]
F --> G["工具启动时继承变量"]
G --> H["工具读取变量使用"]
style A fill:#e1f5ff
style H fill:#c8e6c9
**🖼️ 插图版(2026-04-17 增量补充)**

关键代码(~/.zshrc 中):
1 | # ========== 全局 .env 加载 ========== |
set -a 是核心技巧——它让 source 加载的所有变量自动变成环境变量(等价于每行前加 export),从而被所有子进程继承。
3. 实战:各工具如何接入
3.1 .env 文件规范
1 | # ~/.config/opencode/.env |
3.2 Claude Code (cc-switch)
之前的做法是明文硬编码:
1 | { |
改进后使用环境变量引用:
1 | { |
cc-switch 的 profiles/ 目录存储的是行为策略(model tier、sandbox、approval 等),不存储密钥:
1 | # profiles/dev.env - 仅包含行为配置,无密钥 |
3.3 MCP Server
MCP 服务使用 env:VAR_NAME 语法引用环境变量:
1 | # ai-config/mcp/context7/server.env |
1 | # ai-config/mcp/context7/codex.toml |
根据 Claude Code 官方文档,.mcp.json 也支持 ${VAR} 和 ${VAR:-default} 语法。
3.4 Docker
Docker Compose 原生支持 .env 文件。数据卷独立存放在 docker-data/:
1 | # docker-compose.yml |
Docker Compose 会按优先级读取:
- Shell 环境变量(已通过
source ~/.zshrc加载) - 项目目录下的
.env文件 docker-compose.yml中的default值
3.5 OpenCode
OpenCode 直接读取 shell 环境变量,无需额外配置:
1 | # ~/.zshrc 中已通过 set -a; source .env; set +a 导出 |
4. 安全加固
4.1 文件权限
1 | # .env 文件只允许本用户读写 |
4.2 Git 防泄露
.gitignore(必须配置):
1 | # 环境变量 - 敏感信息 |
Git pre-commit hook(推荐):
1 |
|
4.3 定期审计
1 | # 扫描工作目录中的明文密钥 |
4.4 安全检查清单
-
.env文件权限为600 -
.gitignore包含.env -
~/.zshrc中无明文 Key -
settings.json中无明文 Token -
docker-compose.yml中使用${VAR}而非明文 - MCP 配置使用
env:VAR_NAME - Git pre-commit hook 已启用
- 定期运行密钥扫描
5. 其他方案对比
5.1 方案全景
graph TB
subgraph "Level 1: 本地开发"
A1[".env + source"]
A2["direnv"]
end
subgraph "Level 2: 团队协作"
B1["dotenv-vault"]
B2["Doppler"]
B3["1Password CLI"]
end
subgraph "Level 3: 企业级"
C1["HashiCorp Vault"]
C2["AWS Secrets Manager"]
C3["Azure Key Vault"]
C4["GCP Secret Manager"]
end
A1 --> B1
A1 --> B2
B1 --> C1
B2 --> C1
style A1 fill:#c8e6c9
style B2 fill:#fff9c4
style C1 fill:#ffcdd2
**🖼️ 插图版(2026-04-17 增量补充)**

5.2 详细对比
| 维度 | .env + source | direnv | dotenv-vault | Doppler | HashiCorp Vault |
|---|---|---|---|---|---|
| 安装成本 | 零 | 低 | 低 | 中 | 高 |
| 学习曲线 | 零 | 低 | 低 | 中 | 高 |
| 多环境支持 | 手动 | 自动 | 内建 | 内建 | 内建 |
| 加密存储 | 否 | 否 | 是 | 是 | 是 |
| 访问控制 | 文件权限 | 文件权限 | 团队角色 | RBAC | 策略引擎 |
| 审计日志 | 否 | 否 | 基础 | 完整 | 完整 |
| 密钥轮换 | 手动 | 手动 | 手动 | 自动 | 自动 |
| 价格 | 免费 | 免费 | 免费/付费 | 免费/付费 | 开源/企业版 |
| 适用场景 | 个人开发 | 多项目 | 小团队 | 中型团队 | 企业合规 |
5.3 进阶方案简介
direnv:按目录自动加载环境变量
适合多项目切换的场景。
1 | # 安装 |
Doppler:云端密钥管理
零代码侵入,自动注入环境变量。
1 | # 安装 |
dotenv-vault:加密同步 .env
安全同步到多台设备。
1 | # 安装 |
6. 故障排查
问题 1:环境变量未加载
症状:工具报错 “API key not set” 或 echo $VAR 为空。
排查步骤:
1 | # 1. 检查 .env 文件是否存在 |
问题 2:Claude Code 未使用环境变量
症状:settings.glm.json 中写了 ${VAR} 但工具仍报认证失败。
原因:Claude Code 的 env 字段中 ${VAR} 展开依赖 shell 环境。
解决方案:
1 | # 确认 Claude Code 是从终端启动的(继承了 env) |
问题 3:Docker Compose 变量未替换
症状:MySQL 密码为 ${DISPATCH_MYSQL_PASSWORD} 字面量。
原因:Docker Compose 在非 shell 环境下可能无法读取 zshrc 导出的变量。
解决方案:
1 | # 方案 1:在项目目录放一个 .env(Docker Compose 自动读取) |
问题 4:Key 已提交到 Git
症状:发现 Git 历史中包含明文密钥。
紧急处理步骤:
1 | # 1. 立即在供应商后台轮换/撤销该 Key |
7. 完整实战案例
案例:从零配置 AI 开发环境
目标:配置一台新 Mac,让 Claude Code、OpenCode、Docker、MCP 全部使用统一的 .env 管理。
Step 1 - 创建 .env 文件
1 | mkdir -p ~/.config/opencode |
Step 2 - 配置 zshrc 加载
1 | cat >> ~/.zshrc << 'ZSHRC' |
Step 3 - 配置 Claude Code
在 settings.glm.json 中使用 ${ZHIPU_API_KEY} 引用。在 settings.official.json 中使用 ${ANTHROPIC_API_KEY} 引用。cc-switch 会自动根据 profile 切换。
Step 4 - 配置 MCP Server
1 | # ai-config/mcp/context7/server.env |
在 .mcp.json 中使用:
1 | { |
Step 5 - 启动 Docker
1 | # Docker Compose 自动从 shell env 读取变量 |
Step 6 - 验证
1 | # 验证所有变量已加载 |
8. FAQ
Q1: 为什么选 ~/.config/opencode/.env 而不是 ~/.env?
遵循 XDG Base Directory 规范,将应用配置放在 ~/.config/ 下。同时 OpenCode 原生支持这个路径,减少额外配置。
Q2: set -a 和逐行 export 有什么区别?
功能上等价。set -a 的优势是:.env 文件无需每行写 export,保持与 Docker Compose、direnv 等工具兼容的标准格式。
Q3: 多个 AI 工具会不会有环境变量冲突?
会。例如 ANTHROPIC_API_KEY 可能被 Claude Code 和 Cursor 同时读取。解决方案有三种:
- 使用供应商特定前缀(如
ZHIPU_API_KEY) - 在工具配置中显式映射(如
"ANTHROPIC_AUTH_TOKEN": "${ZHIPU_API_KEY}") - 用 cc-switch profiles 按场景切换
Q4: 生产环境也用 .env 文件吗?
不建议。.env 适合本地开发。生产环境应使用加密的密钥管理服务:
- 容器化部署:Kubernetes Secrets + RBAC
- 云平台:AWS Secrets Manager / Azure Key Vault / GCP Secret Manager
- 自建:HashiCorp Vault
参考 Doppler 的分析:.env 文件在跨环境同步、审计、权限控制方面存在天然局限。
Q5: 如何安全地在多台设备间同步密钥?
推荐方案如下:
| 方案 | 适用场景 |
|---|---|
| dotenv-vault | 加密后同步 .env,轻量 |
| Doppler | 云端管理,CLI 注入 |
1Password CLI (op) |
个人密码管理器集成 |
手动 scp + 加密 |
极简需求 |
Q6: Key 泄露了怎么办?
四步紧急处理流程:
- 立即轮换:在供应商后台生成新 Key,撤销旧 Key
- 清理 Git:使用
git filter-branch或 BFG Repo-Cleaner - 审计影响:检查供应商的用量日志
- 加强防护:部署 Gitleaks 或 TruffleHog 扫描
Q7: cc-switch 的 profiles 和 .env 是什么关系?
分工明确:
.env存储密钥(WHAT credentials)profiles/*.env存储行为策略(HOW to behave)——模型选择、权限级别、审批策略等
两者通过环境变量统一注入,但关注点完全不同。
9. 总结
核心要点
- 单一密钥源:所有 API Key 只存在于
~/.config/opencode/.env,所有工具通过环境变量消费 - 零侵入加载:
set -a; source .env; set +a三行代码实现全局注入,无需修改任何工具代码 - 层次化防护:文件权限 (
chmod 600) + Git 忽略 (.gitignore) + 提交扫描 (pre-commit hook) 三道防线
行动建议
今天就可以做的:
- 将散落在
~/.zshrc和配置文件中的明文 Key 迁移到.env - 配置
.gitignore和文件权限
本周可以优化的:
- 部署 Git pre-commit hook 扫描密钥泄露
- 为 AI 开发环境创建
.env.example模板
长期可以改进的:
- 评估 Doppler 或 dotenv-vault 实现跨设备同步
- 生产环境迁移到 HashiCorp Vault 或云平台 Secrets Manager
- 建立 90 天密钥轮换机制
最后的话
密钥管理的终极目标不是复杂,而是简单——简单到所有开发者都愿意遵守,简单到不需要额外记忆任何步骤。
.env + source就是这样的方案:足够简单地开始,足够灵活地演进。
参考资源
| 资源 | 链接 | 说明 |
|---|---|---|
| OpenAI API Key 安全指南 | OpenAI Help Center | 官方安全最佳实践 |
| Claude API Key 最佳实践 | Claude Help Center | Anthropic 官方建议 |
| Claude Code 环境变量管理 | Claude Help Center | MCP 与 env 集成 |
| 为什么 .env 不适合规模化 | Doppler Blog | .env 局限性分析 |
| dotenv-vault | GitHub | 加密同步 .env |
| Gitleaks | GitHub | Git 密钥泄露扫描 |
更新记录
| 版本 | 日期 | 说明 |
|---|---|---|
| v1.0 | 2026-03-04 | 初始版本:基于实际 AI 开发环境的密钥管理实践 |
| v1.1 | 2026-04-17 | 为 5 个 Mermaid 图表追加 Chiikawa 风格插图(m2c-pipeline 生成) |