ある夜、AntigravityのエージェントにNext.jsの本番ビルドを任せていたところ、最後のステップで Missing environment variable: STRIPE_SECRET_KEY と表示されてジョブが止まりました。手元のターミナルでは npm run build が問題なく通り、echo $STRIPE_SECRET_KEY でも値が表示されているのに、エージェントから走らせたときだけ環境変数が空になります。同じ症状で何時間も溶かしてしまった方もいるのではないでしょうか。
このエラーは「.envの設定ミス」というより、Antigravityのエージェントがコマンドを実行するときの環境変数の伝搬経路を誤解していることが原因であるケースがほとんどです。ここでは私自身が個人開発で何度も踏んだ落とし穴を3つの経路に分けて整理し、最後に確実に環境変数を伝えるための4ステップ実装を示します。
環境変数がエージェントに届くまでの3つの経路を頭に描く
まず、Antigravityのエージェントから実行されたコマンドが環境変数を受け取るまでには、3つの経路があることを把握しておくと、原因の切り分けが一気に楽になります。
- 経路A: シェル環境からの継承 — Antigravityをターミナル(
antigravity .等)から起動した場合、シェルの初期化スクリプトで読まれたexport文がそのまま子プロセスへ継承されます - 経路B: アプリケーション固有の.envロード — Next.jsの
.env.local、Vite のimport.meta.env、Python のpython-dotenvなど、フレームワーク側で能動的に読み込んでいる仕組み - 経路C: エージェント実行時のenvオプション — Antigravityがサブプロセスを起こすときに渡す環境変数の集合(タスク定義や
AGENTS.mdの記述から組み立てられる)
「ターミナルでは動いたのにエージェントだと動かない」という症状は、ほぼ間違いなくこのいずれかが切れています。一つずつ見ていきます。
ケース1: GUIから起動したAntigravityはshellの環境変数を継承していない
macOSのDockやWindowsのスタートメニューからAntigravityを起動すると、お使いの ~/.zshrc や ~/.bashrc で export した変数は 読み込まれません。私はこれを最初に踏み、半日溶かしました。
確認方法はシンプルです。Antigravityの統合ターミナルを開いて、以下を実行してみてください。
# シェル設定が読まれているかの簡易確認
echo "shell=$SHELL"
echo "node=$(which node)"
echo "stripe=${STRIPE_SECRET_KEY:0:7}..." # 先頭7文字だけ表示
# 期待する出力(GUI起動でも継承されている場合):
# shell=/bin/zsh
# node=/Users/you/.nvm/versions/node/v22.5.0/bin/node
# stripe=sk_test...stripe=... が空のまま、あるいは node がシステム標準(/usr/bin/node)を指している場合、シェルの初期化が走っていないサインです。GUI起動のプロセスは ~/.zshrc ではなく ~/.zshenv(zshの場合)や launchctl setenv(macOS)の値だけを継承するため、ここに入っていない値はエージェントにも届きません。
私の運用では、シークレット系は 必ずプロジェクト内の .env.local に置くと決めています。シェル変数に依存すると、別マシンへ移ったときに必ず壊れます。
ケース2: AGENTS.mdに書いた値はエージェントの「実行環境」ではない
AGENTS.mdが効いていないときの診断方法でも触れていますが、AGENTS.md は エージェントへの自然言語の指示書 であって、プロセスのenvブロックではありません。
# 悪い例(エージェントは「読む」だけで「export」はしない)
## Environment
- API_KEY = sk_live_xxx
- DATABASE_URL = postgres://...このように書いても、エージェントが起こすプロセスに process.env.API_KEY として入るわけではありません。値そのものをドキュメントに書くのは漏洩リスクの面でも避けるべきで、AGENTS.md には「.env.local の API_KEY を読み込む構成です」のように 場所と仕組み を伝えるのが本筋です。
# 良い例
## Environment
- すべての秘密情報は `.env.local` に集約しています
- 追加が必要なときは `.env.example` も同期してください
- ローカル実行時は `npm run dev` が dotenv 経由で自動ロードしますエージェントは指示書を読んで判断するので、実行コマンド自体に環境変数のロード手順を含めるよう促すのが安全です。
ケース3: フレームワーク側のdotenvが「エージェントの作業ディレクトリ」を見ていない
Next.jsやViteの .env.local は、プロセスを起動した カレントディレクトリ を基準にロードされます。エージェントがモノレポのルートで npm run build を打ったつもりでも、実際にはサブパッケージにcdしてから走っていることがあり、そこに .env.local がなければ何も読み込まれません。
// scripts/check-env.mjs — 実行直後の env 状態を可視化するデバッグスクリプト
import { existsSync } from 'node:fs';
import path from 'node:path';
import dotenv from 'dotenv';
const cwd = process.cwd();
console.log('CWD:', cwd);
// 想定パスを順に探索
const candidates = [
path.join(cwd, '.env.local'),
path.join(cwd, '.env'),
path.join(cwd, '..', '.env.local'),
];
for (const file of candidates) {
console.log(file, existsSync(file) ? 'FOUND' : 'missing');
}
// 明示的にロード
const result = dotenv.config({ path: '.env.local' });
console.log('Loaded keys:', Object.keys(result.parsed ?? {}));
console.log('STRIPE prefix:', (process.env.STRIPE_SECRET_KEY ?? '').slice(0, 7));
// 期待する出力(モノレポ直下から実行した場合):
// CWD: /Users/you/projects/myapp
// /Users/you/projects/myapp/.env.local FOUND
// Loaded keys: [ 'STRIPE_SECRET_KEY', 'DATABASE_URL', 'OPENAI_API_KEY' ]
// STRIPE prefix: sk_testこのスクリプトをエージェントに実行してもらうと、**「どこから探したか」「何を見つけたか」**の両方がログに残り、原因切り分けが一気に進みます。私は新しいプロジェクトを立ち上げるたびに、このスクリプトをまず仕込むようにしています。
確実に環境変数を伝えるための4ステップ実装
ここまでの整理を踏まえて、私が個人開発で実際に使っている設定を順に紹介します。Next.jsを例にしていますが、考え方はPython・Goでも同じです。
ステップ1 — .env.local をプロジェクトルートに集約する
複数の .env* を散らさず、ローカル用は .env.local 一本にまとめます。.env.example だけGitに残し、構造変更時はAGENTS.mdから参照させます。
ステップ2 — package.json のスクリプトでロードを明示する
{
"scripts": {
"dev": "next dev",
"build": "next build",
"build:agent": "node -r dotenv/config node_modules/.bin/next build dotenv_config_path=.env.local",
"test:env": "node scripts/check-env.mjs"
}
}build:agent のように エージェント専用のエントリ を用意し、AGENTS.md で「ビルド検証は npm run build:agent を使ってください」と一文書いておくと、伝搬経路が固定されます。
ステップ3 — .vscode/tasks.json にenvFileを設定する
Antigravityはタスク機能を共有しているので、タスク経由で実行する場合は envFile 指定が一番確実です。
{
"version": "2.0.0",
"tasks": [
{
"label": "build (agent)",
"type": "shell",
"command": "npm run build:agent",
"options": {
"envFile": "${workspaceFolder}/.env.local"
},
"problemMatcher": []
}
]
}ステップ4 — エージェントには「ビルド前にtest:envを通す」と書く
AGENTS.md の冒頭に、デプロイ系タスクの前提条件として下記を追加します。
## Pre-flight check
本番ビルドや外部API呼び出しを伴うタスクの前に、必ず `npm run test:env` を実行し、
- `Loaded keys` に `STRIPE_SECRET_KEY` `DATABASE_URL` が含まれていること
- `STRIPE prefix` が `sk_` で始まっていること
を確認してから先に進んでください。空のときは中止して、原因を報告してください。これだけで「実行直前に env が空だったらすぐ気づける」状態になり、ビルドの最後で気づいて15分溶かす、というパターンが目に見えて減りました。
AGENTS.mdの正しい書き方ガイドとAntigravityの.env管理戦略、それにエージェントのコンテキストドリフトを防ぐ方法を合わせて読むと、環境変数の取り扱いがプロジェクト全体で安定します。
同じ症状にぶつかったときの2分チェックリスト
最後に、私が手元で必ず通すチェックリストを置いておきます。長く悩んだときほど、シンプルな確認に立ち戻ると早く抜けられます。
- 統合ターミナルで
echo $SHELLとwhich nodeを確認 — システムバイナリを指していないか npm run test:envを走らせて、想定キーがすべてロードされているか.env.localの所有者が自分(読み取り権限あり)になっているか- モノレポなら
pnpm -wやturbo runのスコープが正しいか - 直前にエージェントが
cdしたまま戻っていないpwdを見る
開発というのは、こういう小さな伝搬経路を一つずつ可視化していく作業の積み重ねだと感じます。エラーメッセージそのものより、その手前で 「環境がどう組み立てられているか」を知っているかどうか で、解決速度が大きく変わります。
今日のチェックリストを scripts/check-env.mjs として手元に置いてみてください。次に同じエラーに出会ったとき、最初のコマンドが決まっているだけで気持ちがずいぶん楽になります。お読みいただきありがとうございました。