もう.envrcにAPIキーを平文で置くのはやめるけど、環境変数は使いたい

追記(2026.03.18):TouchID, Apple Watch対応にした。

もう.envにAPIキーを平文で置くのはやめた — macOS Keychain管理CLI「LLM Key Ring」を読んで、過去に一度、.envrcがGitHubにpushしてしまってから、.envrcを自前スクリプトで管理してきたが、ちゃんとした仕組みを作りたい欲が出てしまったので書いた。

envrcctlという、何の工夫もないネーミングだけれど。

なんで書いたの?

素直にlkrを使わせていただけば良いのだけれど、環境変数もまとめて管理したいとか、親ディレクトリの.envrcの値も継承したいとか、諸々理由がある。

例えば、.envrcには、そのディレクトリ(プロジェクト)固有の環境変数、自分の場合は$BREW_FORMULA等が設定される。

git add hoge.rb

じゃなく、

git add $BREW_FORMULA

でOK。どのディレクトリでも同じコマンドで良くなる。

あるいは、複数のプロジェクトで同じOPENAI_API_KEYを使う、ということもあるので、source_upを使う。

インストール

macOSならHomebrewでインストールできる。

brew install rioriost/tap/envrcctl

direnvを使っていることが前提なので、もし無ければ追加でインストール。

brew install direnv

使い方

既に.envrcが存在するディレクトリで、doctorサブコマンドを実行すると分かりやすい。

envrcctl doctor
WARN: Managed block not found in .envrc. Run `envrcctl init`.
WARN: unmanaged exports outside block: BREW_FORMULA, UV_PUBLISH_TOKEN. Run `envrcctl migrate` to move them.
WARN: possible plaintext secrets in exports: UV_PUBLISH_TOKEN. Consider `envrcctl secret set` for these values.

BREW_FORMULAがenvrcctlで管理されてないよ、と、UV_PUBLISH_TOKENはシークレットなのに平文だよと教えてくれる。

envrcctl migrate
Migrate unmanaged exports into the managed block? [y/N]: y
direnv: error /Users/rifujita/ownCloud/bin/test_envrcctl/.envrc is blocked. Run `direnv allow` to approve its content

migrateしてenvrcctlの管理下に。

envrcctl secret set --account 'uv_token_test_envrcctl' UV_PUBLISH_TOKEN
Secret value:
Confirm secret value:
direnv: loading ~/ownCloud/bin/test_envrcctl/.envrc
direnv: export +BREW_FORMULA +ENVRCCTL_SECRET_UV_PUBLISH_TOKEN

secret setで、Keychainに放り込む。これで、.envrcからUV_PUBLISH_TOKENを消してもOK。

envrcctl unset UV_PUBLISH_TOKEN

secretではないので、単純にunsetすれば良い。

direnv allow
direnv: loading ~/ownCloud/bin/test_envrcctl/.envrc
direnv: export +BREW_FORMULA +ENVRCCTL_SECRET_UV_PUBLISH_TOKEN

direnv allowすれば、実際にexportされるものが分かる。ENVRCCTL_SECRET_UV_PUBLISH_TOKENは、UV_PUBLISH_TOKENに展開される。

envrcctl exec -- python3 -c 'import os; print(os.environ.get("UV_PUBLISH_TOKEN")); print(os.environ.get("BREW_FORMULA"))'
py-hogehoge
agentops_mcp_server.rb

UV_PUBLISH_TOKENとBREW_FORMULAが取得できている。

実際の.envrcの中身は以下のようになっているので、間違ってGitHubで公開しても問題は無し。

cat .envrc
# >>> envrcctl:begin
# managed: true

export BREW_FORMULA=agentops_mcp_server.rb

export ENVRCCTL_SECRET_UV_PUBLISH_TOKEN=kc:st.rio.envrcctl:uv_token_test_envrcctl:runtime

# <<< envrcctl:end

execでいちいち呼ぶのは面倒臭い場合、–injectを付けてinitサブコマンドを使う。

envrcctl init --inject

これで対面式、つまりTTYからであれば環境変数を参照できる。

cat .envrc
# >>> envrcctl:begin
# managed: true

export BREW_FORMULA=agentops_mcp_server.rb

export ENVRCCTL_SECRET_UV_PUBLISH_TOKEN=kc:st.rio.envrcctl:uv_token_test_envrcctl:runtime

eval "$(envrcctl inject)"

# <<< envrcctl:end

その他の使い方は、READMEかhelpを。

envrcctl --help

 Usage: envrcctl [OPTIONS] COMMAND [ARGS]...

 Manage .envrc with managed blocks.

╭─ Options ──────────────────────────────────────────────────────────────────────╮
│ --install-completion          Install completion for the current shell.        │
│ --show-completion             Show completion for the current shell, to copy   │
│                               it or customize the installation.                │
│ --help                        Show this message and exit.                      │
╰────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────╮
│ init     Create .envrc if missing and insert managed block.                    │
│ inherit  Toggle source_up inheritance in the managed block.                    │
│ set      Set a non-secret export in the managed block.                         │
│ unset    Unset a non-secret export in the managed block.                       │
│ get      Get a non-secret export value from the managed block.                 │
│ list     List non-secret exports in the managed block.                         │
│ inject   Emit export statements for all secret references.                     │
│ exec     Execute a command with managed secrets injected into the environment. │
│ eval     Show the effective environment (masked secrets).                      │
│ doctor   Run security and consistency checks for .envrc.                       │
│ migrate  Move unmanaged exports into the managed block.                        │
│ secret   Manage secret references.                                             │
╰────────────────────────────────────────────────────────────────────────────────╯

なお、Linux用のコードは実装してあるけれど、未テストです。

タイトルとURLをコピーしました