并行 Vibe Coding 的密钥管理:一个 .envrc 搞定所有 WorktreeDan Begel / Unsplash

エッセイ

并行 Vibe Coding 的密钥管理:一个 .envrc 搞定所有 Worktree#

Asuka 著

用 Claude Code 等 Vibe Coding 工具做开发时,经常需要同时开多个 Agent 并行工作。最常见的做法是通过 Git Worktree 为每个 Agent 创建独立的工作目录——每个 worktree 有自己的文件和分支,互不干扰。

问题在于:每个新创建的 worktree 都是一个「干净」的工作目录,项目运行所需的密钥文件(API keys、OAuth tokens、各种 credentials)都不存在。于是每次创建 worktree 之后,都得手动把 .env 或密钥文件复制过去。手动维护这些密钥会严重阻塞工作流程。

经过一番研究,发现 direnv 可以很好地解决这个问题。

direnv 如何工作#

direnv 是一个 shell 扩展,用 Go 编写,支持 bash、zsh、fish 等主流 shell。它的工作方式很简单:

  1. 在每次 shell prompt 刷新前,direnv 检查当前目录及 父目录 中是否存在 .envrc 文件。
  2. 如果存在且已授权,就在一个 bash 子进程中执行 .envrc,把导出的环境变量注入当前 shell。
  3. 离开该目录时,自动卸载这些环境变量。

「父目录继承」这个特性正好适用于 worktree 场景:只要在 worktree 的公共父目录放一个 .envrc,所有子目录中的 worktree 都能自动获取到密钥配置。

安装和配置

Bash
# macOS
brew install direnv

# 在 ~/.zshrc 末尾添加 hook(zsh 为例)
eval "$(direnv hook zsh)"

安装完成后重启 shell 即可。direnv 有一个安全机制:新的或修改过的 .envrc 文件需要执行 direnv allow 才能生效,防止恶意目录注入环境变量。

路径一:VS Code GitLens Worktree#

使用 VS Code 的 GitLens 插件时,通过 Create Worktree 命令可以从当前仓库创建 worktree。假设当前仓库目录是 foo,新创建的分支是 feature/bar,GitLens 会将 worktree 放在与 foo 同级的 foo.worktree/feature-bar/ 下(分支名中的 / 会被替换成 -)。

目录结构如下:

Auto
foo/                          # 主仓库
foo.worktree/                 # GitLens worktree 根目录
├── .envrc                    # ← direnv 配置,所有 worktree 自动继承
├── feature-bar/              # feature/bar 分支的 worktree
├── feature-baz/              # feature/baz 分支的 worktree
└── bugfix-123/               # bugfix/123 分支的 worktree

只需要在 foo.worktree/ 目录下创建一个 .envrc 文件:

Bash
# foo.worktree/.envrc
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export DATABASE_URL="postgres://..."

然后授权一次:

Bash
cd foo.worktree
direnv allow

之后无论创建多少个 worktree,进入任何一个子目录时 direnv 都会自动加载这些环境变量。不需要在每个 worktree 里再复制 .env 文件。

路径二:Claude Code 的 --worktree 参数#

Claude Code 提供了内置的 worktree 支持。通过 --worktree(或 -w)参数可以直接创建一个隔离的 Git worktree 并在其中启动 Claude:

Bash
# 指定名称创建 worktree
claude -w feature-auth

# 不指定名称,自动生成随机名(如 bright-running-fox)
claude -w

Worktree 会创建在 <repo>/.claude/worktrees/<name>/ 下,分支命名为 worktree-<name>,从默认远程分支派生。退出时,如果没有任何改动,worktree 和分支会被自动清理;如果有改动或 commit,Claude 会询问是否保留。

同样的思路,在 .claude/worktrees/ 目录下放一个 .envrc

Auto
my-project/
├── .claude/
│   └── worktrees/
│       ├── .envrc             # ← direnv 配置
│       ├── feature-auth/      # claude -w feature-auth 创建
│       ├── bugfix-login/      # claude -w bugfix-login 创建
│       └── bright-running-fox/# claude -w 自动生成
├── src/
└── ...
Bash
cd .claude/worktrees
cat > .envrc << 'EOF'
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
EOF
direnv allow

之后所有通过 claude -w 创建的 worktree 都会自动继承这些环境变量。

值得一提的是,Claude Code 的 subagent 也支持 worktree 隔离——在自定义 subagent 的 frontmatter 中设置 isolation: worktree,subagent 就会在独立的 worktree 中工作,同样可以享受到 direnv 的自动加载。

关于安全性#

需要注意的是:direnv 加载的环境变量会直接出现在 shell 环境中。Agent 执行 envprintenv 就能看到所有密钥的值。这个方案 并不能阻止 Agent 访问密钥

它真正解决的问题是:

  • 减少文件泄露风险:密钥不以 .env 文件的形式存在于每个 worktree 的项目目录中,降低了被意外 git addgit commit 的概率。
  • 免去重复操作:不需要每次创建 worktree 后手动复制密钥文件。
  • 基本的授权审查.envrc 文件必须通过 direnv allow 明确授权才会生效。如果文件内容被修改,需要重新授权。

如果需要更严格的密钥隔离,应该考虑 vault 类方案或在 CI/CD 层面注入密钥,而不是依赖本地环境变量。但对于日常的 Vibe Coding 并行开发场景,direnv 在便利性和安全性之间取得了不错的平衡。

.gitignore 配置#

使用 Claude Code 的 --worktree 时,官方建议在 .gitignore 中添加:

Auto
.claude/worktrees/

这样 worktree 的内容不会出现在主仓库的 untracked files 中。.envrc 文件放在 .claude/worktrees/ 下时也会被一并忽略,不用担心密钥被提交。

对于 GitLens 的方式,foo.worktree/ 目录本身就在主仓库外面,天然不会被 Git 追踪。

This browser prefers English.

You can switch the site to English and save that choice for future visits.