Claude Code に .env を貼り付けて渡している ── AI エージェントに渡す token は 1 つだけ

上原正吉(EarthLink Network Co., Ltd.)。AI会社・AI社員による業務自動化と、人の逐次介入なしに24時間自動開発を回す仕組みを自社で実践しています。開発ノウハウと具体的な設定方法、運用して分かった改善点を公開しています。

Claude Code に .env を貼り付けて渡している ── AI エージェントに渡す token は 1 つだけ

Claude Code に .env を貼り付けて渡している ── AI エージェントに渡す token は 1 つだけ

この記事は、連載「dotvault の使い方 ── .env を手で配るのをやめ、CI・チーム・AI エージェントに 1 コマンドで配るまで」の第 8 回です。この連載が終わる時に、dotvault を誰でも無料で使える形で公開する予定です。

Claude Code に「この .env を使って動かして」と頼む時、.env の中身を会話に貼り付けるか、.env を読ませることになります。値は会話の記録に残り、Claude Code が動かすコマンドの出力にも出ます。dotvault に値を置いてあっても、Claude Code に dotvault login をさせるには、自分のメールアドレスとパスワードを渡すことになります。

「AI エージェントに secret を渡すには、値そのものか、自分の login を渡すしかない」と考えがちですが、渡すのは dotvault の service token 1 つで足ります。project を 1 つに絞った、値を読み書きするための token(Read/write)です。Claude Code はこの token だけで .env を dotvault に取り込み、pull で受け取ります。人のパスワードは渡しません。使わせなくする時は、console で token を取り消します(Revoke)。

この回では、token を 1 つ発行して Claude Code の設定ファイルに置き、Claude Code に取り込みから pull までを任せ、Revoke で token を取り消すところまでを確かめます。Claude Code は token 1 つだけで 3 つの key を取り込み、pull で 3 つを受け取りました。token を取り消した後に同じ pull を頼むと、AUTH_REQUIRED と終了コード 3 で止まりました。

結論

  • Claude Code に渡す token は 1 つです。 console の Service Tokens → Create token で、Role を Read/write、Project を作業する project にした token を作ります。Read/write は、pull に加えて key の追加・更新・削除ができます。
  • project は、人が console で作ります。 Read/write の token では project を作れません。project の作り方は 2 回目で扱いました。
  • token は、そのリポジトリの .claude/settings.local.json の env に DOTVAULT_TOKEN として置きます。 ファイルには token が平文で書かれるので、.gitignore で外します。
  • Claude Code は、人の login なしで値を取り込み、受け取ります。 dotvault init → import → pull → run → whoami を Claude Code が自分で実行し、3 つの key を取り込んで、pull で 3 つを受け取りました。
  • dotvault scan . は、設定ファイルの token を見つけます。 1 つの token を 2 件として出し、終了コード 1 を返します。
  • 使わせなくする時は、console で token を取り消します(Revoke)。 取り消した後、Claude Code の pull は AUTH_REQUIRED(終了コード 3)で止まりました。AI に渡した token は、取り消して発行し直し(再発行)、設定ファイルの 1 行を書き換えれば済みます。AI が使う API キーの値は、提供元で作り直したキーに dotvault の値を入れ替えます。その仕組みは 11 回目で扱います。

本文(読了 約9分)

前提

7 回目で扱った service token の発行と取り消しの続きです。この回は、同じ画面で作った token を Claude Code に渡します。7 回目を読んでいなくても追えます。

1. token を 1 つ発行する

先に、Claude Code に使わせる project を console で作っておきます。ここでは、Projects の New project で demo-agent-app を作りました。作り方は 2 回目と同じです。Read/write の token では project を作れないので、project は人が作ります。

次に、サイドバーの Service Tokens → Create token を開きます。Name を claude-agent、Role を Read/write (member。dotvault の中での役の名前です)、Project を demo-agent-app、Expiry を 30 days にし、Environments は production だけに印を付けました。

Create service token のモーダル。Name に claude-agent、Role は Read/write で「In addition to pull, can add, update, and delete keys.」の説明。Project は demo-agent-app で「Project-scoped tokens receive only the Global keys bound to this project (they cannot see the Global keys list itself).」の注記。Expiry は 30 days。Environments (envs) は development・staging・production のうち production だけに印があり、「Leave empty for all environments. Picking some restricts the token to them.」の説明。右下に Cancel と Create のボタン。

Claude Code に import で値を取り込ませるので、Read only ではなく Read/write にします。Environments の欄は、何も選ばなければ全部の環境、選べばその環境だけに使える token になります。Claude Code が取り込む先は production だけなので、production だけにしました。

Create を押すと、token が 1 回だけ表示されます。ここで Copy します。

Token created の画面(token は伏せ字)。「Copy this token now — it is shown only once and cannot be retrieved again.」の注意、est_•••• の token、Token ID の 6db15215ff44cb01095ffd38cec39774 と「The Token ID is not a secret.」の説明、Copy と Done のボタン。

一覧には 1 行が並びます。Project は demo-agent-app、Envs は production です。

Service Tokens の一覧に 1 行。claude-agent・Token ID 6db15215ff44cb01095ffd38cec39774・Role は Read/write・Project は demo-agent-app・Envs は production・作成の 30 日後が期限・Last used は Not recorded・Status は active。行の右端に Revoke ボタン。

2. token を Claude Code に渡す

作業するリポジトリ(ここでは ~/dev/demo-agent-app)の .claude/settings.local.json に、token を書きます。Claude Code は、このファイルの env を、自分が実行するコマンドの環境変数として渡します。

{
  "env": {
    "DOTVAULT_TOKEN": "est_••••"
  },
  "permissions": {
    "allow": [
      "Bash(dotvault:*)"
    ]
  }
}
  • DOTVAULT_TOKEN には、1 節で作った Read/write の token を入れます。import・pull・run が読みます。
  • permissions.allow の Bash(dotvault:*) は、dotvault で始まるコマンドを、毎回の確認なしで実行してよいという許可です。

置き場所を、ユーザー全体の ~/.claude/settings.json ではなく、リポジトリの .claude/settings.local.json にしたのは、ユーザー全体に置くと、どのリポジトリで起動した Claude Code にもこの token が渡るためです。このリポジトリでだけ使う token は、このリポジトリに置きます。

このファイルには token が平文で書かれます。.gitignore に .claude/settings.local.json と .env を書いて、commit に入らないようにします。

.env
.claude/settings.local.json

このリポジトリで Claude Code を初めて起動すると、フォルダを信頼するかの確認に、このファイルで許可したコマンドが出ます。

Claude Code の起動時の画面。「Accessing workspace:」とリポジトリのパスの下に、信頼してよいフォルダかを尋ねる文。黄色の「⚠ This folder pre-approves 1 tool permission in .claude/settings.local.json:」の下に Bash(dotvault:*)、続けて「These will apply without asking. Only proceed if you trust this configuration.」。選択肢は No, exit と Yes, I trust this folder。

許可されるのが Bash(dotvault:*) の 1 つだけであることを確かめてから、Yes, I trust this folder を選びます。

3. Claude Code に取り込みから pull までを頼む

リポジトリには、ダミーの値の .env(DATABASE_URL・OPENAI_API_KEY・FEATURE_FLAGS の 3 行)を置いてあります。Claude Code には、こう頼みました。

Move this repo's .env into dotvault without asking me. The project demo-agent-app already exists. Use the dotvault CLI: init the config as demo-agent-app, import .env into production, pull it back from production, then check two values with dotvault run -E production -- printenv DATABASE_URL and dotvault run -E production -- printenv FEATURE_FLAGS (one name per command, never print the whole environment), and finish with whoami.

(one name per command, never print the whole environment) は、環境変数の全部を出さないための一言です。dotvault run は、取り出した値を環境変数として子のコマンドに渡します。printenv を名前なしで実行すると、渡した値がすべて画面に出て、Claude Code の会話の記録にも残ります。Mac の printenv は、名前を 2 つ渡しても 1 つ目の値しか出さないので、key ごとに 1 回ずつ頼みます。

$ env A=1 B=2 printenv A B
1

Claude Code は 7 個のコマンドを実行しました。初めの 2 個は dotvault --help などで使い方を読むためのもので、残りの 5 個で取り込みから確かめまでを進めました。ctrl+o で展開した、5 個のコマンドとその出力です。

Claude Code の実行の画面(ctrl+o の展開表示)。Bash(dotvault init --name demo-agent-app && dotvault import .env -E production) の出力に「Created project-config.json (project=demo-agent-app). Next: dotvault pull (uses DOTVAULT_TOKEN; no login needed)」と「imported 3 keys into .env [demo-agent-app/production]」。Bash(dotvault pull -E production) の出力に、元の 3 行をコメントにしたという warning と「✓ Wrote 3 keys to …/demo-agent-app/.env」「✔ 1 file synced, 0 excluded, 3 keys total」。dotvault run -E production -- printenv DATABASE_URL の出力にダミーの postgres:// の URL、printenv FEATURE_FLAGS の出力に beta-search。Bash(dotvault whoami) の出力に「Service token (DOTVAULT_TOKEN=est_••••…) — CI / Lambda mode」と、whoami はサーバーに問い合わせないという note。

  • init。 project-config.json を作り、「Next: dotvault pull (uses DOTVAULT_TOKEN; no login needed)」と、token があれば login は要らないと案内しました。
  • import。 「imported 3 keys into .env [demo-agent-app/production]」で、3 つの key が production に入りました。
  • pull。 「Wrote 3 keys」で 3 つを受け取りました。元の .env の 3 行は「# dotvault: moved into the managed block below:」を付けてコメントにし、その下の dotvault が管理する範囲に値を書いた、という warning も出ています。
  • run。 DATABASE_URL と FEATURE_FLAGS のダミーの値が、1 つずつ出ました。
  • whoami。 「Service token (DOTVAULT_TOKEN=est_••••…) — CI / Lambda mode」で、人の login ではなく token で動いていると分かります。

最後に、Claude Code はこう報告しました。

Claude Code の報告の画面。依頼文の下に「Ran 7 shell commands」。報告は「The repo's .env is now in dotvault under demo-agent-app, in the production environment.」で始まり、Init(project-config.json を作った)、Import(3 keys を production へ)、Pull(3 keys を .env へ書き戻し、元の 3 行はコメントにした)、Checks(DATABASE_URL と FEATURE_FLAGS の値)、whoami(service token を使っていて、whoami はサーバーに問い合わせないので token が有効かは確かめられない。確かめるには dotvault list --project demo-agent-app)の 5 項目。最後に「Churned for 24s」。

何を実行し、何が通ったかを、key の数と値の確かめまで含めて返しています。pull で元の行がコメントになったことも、報告に入っています。私が途中で答えたことはありません。

4. console で確かめる

console の Projects で demo-agent-app を開き、Keys の production を選ぶと、Claude Code が取り込んだ 3 つの key が並んでいます。

demo-agent-app の Keys 画面で production を選んだところ。env のファイルに 3 keys。DATABASE_URL・FEATURE_FLAGS・OPENAI_API_KEY の 3 行で、どれも 🔒 の印つき、UPDATED は同じ時刻。右に「Selected key」の欄。

5. scan で token の混入を見つける

5 回目の「.npmrc と kubeconfig を、まだ手で渡している」で使った dotvault scan は、est_ で始まる token も見つけます。リポジトリで scan . を実行しました。

$ dotvault scan .
.claude/settings.local.json:3  [dotvault-service-token] dotvault service token — est_•••• (80 chars)
.claude/settings.local.json:3  [generic-assignment] Generic secret assignment — TOKE•••• (90 chars)

2 potential secret(s) found.
$ echo $?
1

1 つの token が、dotvault service token と Generic secret assignment の 2 つの規則で、2 件として出ました。scan は見つけた文字列の初めと終わりを数文字ずつ出すので、そこも伏せています。.env のダミーの値は出ませんでした。

.claude/settings.local.json は .gitignore で外してありますが、5 回目で書いたとおり、scan . は .gitignore で外したファイルも読みます。commit の前のフックに exec dotvault scan . を置いているリポジトリでは、このファイルがあるだけで commit が止まります。その時は、フックの範囲を exec dotvault scan src/ .github/ のように絞ります。逆に、token を誤って commit されるファイル(チームで共有する .claude/settings.json など)に書いた時は、フックが commit を止めます。

6. Revoke で token を取り消す

Service Tokens の一覧で、claude-agent の行の Revoke(取り消し)を押しました。「Revoke token “claude-agent”? CI jobs and services using it will lose access immediately.」の確認で OK を押すと、Status が revoked になります。

Revoked only で絞り、検索欄に Token ID を入れた Service Tokens の一覧。claude-agent(Read/write・demo-agent-app・production)の 1 行で、Last used (hourly) には 3 節で token を使った時刻、Last-use IP は伏せ字、Status は revoked。

Last used は token ごとに 1 時間に 1 回だけ記録されるので、ここに出ているのは 3 節で Claude Code が最初に token を使った時刻です(init と import を続けて実行したコマンド)。token を取り消した後に、Claude Code に同じ pull を頼みました。

Claude Code の画面(ctrl+o の展開表示)。「Pull production from dotvault again with dotvault pull -E production and tell me the exit code.」の依頼に、Bash(dotvault pull -E production; echo "exit code: $?") の出力「✖ AUTH_REQUIRED: invalid, expired or revoked service token」と「exit code: 3」。続く報告は「The pull failed with exit code 3 (AUTH_REQUIRED).」で始まり、token が取り消されたか期限切れの可能性、失敗した pull は何も書いていないので手元の .env は変わっていないこと、console で新しい token を発行して DOTVAULT_TOKEN に入れれば pull をやり直せることを返している。

pull は「✖ AUTH_REQUIRED: invalid, expired or revoked service token」で、終了コード 3 で止まりました。Claude Code は、token が取り消されたか期限が切れたと読み、手元の .env は書き換わっていないこと、新しい token を発行すれば pull をやり直せることを返しました。

whoami では、token が取り消されたかどうかは分かりません。3 節の出力の note のとおり、whoami はサーバーに問い合わせないので、取り消した token でも同じ行を出します。確かめる時は pull か dotvault list --project <name> を使います。

token を取り消した後は、.claude/settings.local.json の DOTVAULT_TOKEN の値も消しておきます。

7. AI に渡しても、token の再発行とキーの入れ替えは簡単にできる

AI に渡した token は、取り消して新しい token を発行し直し(再発行)、.claude/settings.local.json の値を書き換えれば済みます。Claude Code の側で変えるのは、この 1 行だけです。

AI が使うキーの値(この回の OPENAI_API_KEY のような API キー)も、簡単に入れ替えられます。キーそのものは dotvault が作るのではありません。OpenAI などの提供元でキーを作り直し、dotvault に置いた値を新しい値に入れ替えます。取り替えの管理に登録しておけば、漏れた時に retire で誰にも渡らないように止め、新しい値を置けます。キーの入れ替えの仕組みは、11 回目の「漏れた API キーを 1 コマンドで止める」で扱います。

次回

次回は、一人で使ってきた Personal org を Company org に切り替え、人を招待してロールを渡し、辞めた人の権限を止めるところまでを扱います。


dotvault は、.env や設定ファイルの secret をサーバー側に置き、権限のある人・CI・AI エージェントが 1 コマンドで受け取るサービスです(https://dotvault.io)。この連載が終わる時に、dotvault を誰でも無料で使える形で公開する予定です。公開したら、この連載の手順どおりに使い始められます。

興味のある方は、ぜひ「いいね」と記事の購読をお願いいたします。

自社プロダクトは https://www.eln.ne.jp/products にまとめています。

筆者について

上原正吉。EarthLink Network Co., Ltd. 代表。AI社員に日々の業務を任せ、開発では人が逐一指示しなくても作業が進むHOOTL(Human Out Of The Loop)の仕組みを自社で実践しています。このブログでは、業務自動化と24時間自動開発のノウハウ、具体的な設定方法、日々の運用で見つかった問題と改善を共有します。

また、AIで業務や開発を組み替えたい会社・チーム向けに、AI活用のコンサルティングも受け付けています。ご相談は www.eln.ne.jp からどうぞ。


EarthLink Network は、会社の全業務を AI で回すために、必要になったものを自社で作っています。いま作っているプロダクトの一覧と概要は、こちらにまとめています。

→ EarthLink Network が自社でつくっている18のプロダクト

会社と各プロダクトの詳細は、公式サイト www.eln.ne.jp をご覧ください。