2025年、海外での展示に参加するため滞在していたホテルで、それまで快調に動いていた Antigravity のエージェントが突然沈黙しました。チャットは「送信中」のまま戻らず、タブ補完だけがときどき思い出したように働く。半日かけてたどり着いた原因は、ホテルの回線に挟まっていた透過型プロキシでした。HTTPS の一部だけが静かに書き換えられていて、ストリーミング接続だけが選択的に死んでいたのです。
接続トラブルの厄介さは、「ネットワークが悪い」という一言ではくくれないところにあります。Antigravity は認証、モデル API、エージェントのツール実行、拡張機能の更新といった性質の異なる通信を同時に張っていて、プロキシはそのうちの一部だけを壊します。結果として「補完は効くのにエージェントが動かない」「サインインだけが通らない」という中途半端な壊れ方になり、原因の見当がつけにくくなります。
私は2005年に独立する前、NTT データで企業ネットワークの内側から開発していた時期があります。プロキシと認証サーバーの機嫌をうかがいながら開発する感覚は、当時も今もあまり変わっていません。違うのは、いまの私が展示会場とホテルを移動しながら個人開発のアプリ群をメンテナンスし続けている点です。以下では、その両方の経験から少しずつ固まってきた「制限ネットワークで Antigravity を止めないための接続設計」を書いていきます。
Antigravity の通信は一本道ではない — 止まり方からレイヤーを逆引きする
Antigravity が外と話す経路は、私が観測している範囲で大きく5つに分かれます。
認証系 : Google アカウントのサインインと OAuth コールバック。IDE 内ではなく既定ブラウザを経由するため、IDE とブラウザが別々のプロキシ設定を見ているとここだけ失敗します
モデル API : Gemini などクラウドモデルとのやり取り。応答はストリーミングで届くため、長生きする HTTPS 接続を嫌うミドルボックスに最初に殺されます
エージェントランタイム : ツール実行で子プロセスとして起動される git・npm・curl 類。これらは IDE の設定画面ではなく環境変数を見ます
拡張機能・更新系 : マーケットプレイスと自動更新。失敗しても当日の開発は続けられますが、放置すると古い拡張が別の不具合を呼び込みます
ローカル LLM : Ollama や LM Studio への localhost 通信。ここは逆に、プロキシを「通ってはいけない」経路です
この5分類を頭に置くと、症状からレイヤーを逆引きできるようになります。
サインインだけ失敗する → 認証系。ブラウザ側のプロキシ設定と食い違っていないか
チャットが「送信中」のまま固まる → モデル API。ストリーミングがプロキシに切られている可能性
最初の応答は来るのに途中で切れる → プロキシのアイドルタイムアウト。長文生成ほど切られやすい
エージェントのコマンド実行だけ失敗する → 環境変数が IDE に渡っていない
直結環境では見えていたローカルモデルが見えない → NO_PROXY の不備
何もかも繋がらない → キャプティブポータル未認証か DNS
私はこの対応表を作ってから、初見のネットワークで原因特定にかける時間が半日から10分前後まで縮みました。次のセクションで、その10分の中身を手順にします。
最初の10分でやる診断 — 現在地を5つのコマンドで確認する
設定をいじり始める前に、いまどのレイヤーで止まっているかを確かめます。闇雲に設定を変えると、直った理由も壊れた理由も分からなくなるからです。観測を先に、変更を後に。これは順番の問題ではなく、復旧時間を左右する分岐点です。
# (1) 環境変数にプロキシが入っているか — 「誰がプロキシを名乗っているか」の確認
env | grep -i proxy
# (2) キャプティブポータルに捕まっていないか — 204 が返れば素通りできている
curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 \
http://captive.apple.com/hotspot-detect.html
# (3) モデル API 系へ素の HTTPS が通るか・誰が証明書を出しているか
curl -sv --max-time 10 https://generativelanguage.googleapis.com -o /dev/null 2>&1 \
| grep -E "issuer:|HTTP/"
# (4) プロキシ経由を明示すると通るのか(社内で配られている値を入れる)
curl -sv --max-time 10 -x http://proxy.example.co.jp:8080 \
https://generativelanguage.googleapis.com -o /dev/null 2>&1 \
| grep -E "CONNECT|issuer:|HTTP/"
# (5) ローカル LLM が生きているか — プロキシとは無関係に直結で返るべき
curl -s --max-time 3 http://127.0.0.1:11434/api/tags | head -c 120
(2) は Apple がキャプティブポータル検出に使っている素朴な HTTP エンドポイントで、204 以外(302 や、200 なのに HTML が返る等)なら、回線が壊れているのではなくまだホテルの同意画面を通過していません。ブラウザを開いて認証するのが先です。
(3) の出力で私が最初に見るのは issuer の行です。
# 直結できている環境の例 — 発行者が公的 CA
issuer: C=US; O=Google Trust Services; CN=WR2
# SSL 検査型プロキシの内側にいる例 — 発行者が見知らぬ社内 CA に化ける
issuer: O=ExampleCorp Security; CN=ExampleCorp TLS Inspection CA
issuer が見知らぬ名前になっていたら、その回線は HTTPS を復号して検査しています。後述の証明書対応が必須で、ここを飛ばしてプロキシ設定だけ変えても直りません。
(5) が応答しない場合は、Ollama 側の問題とプロキシ巻き込みの2通りがあります。Ollama 自体の診断は Antigravity でローカルLLM(Ollama)が接続できない・認識されないときの診断ガイド に書いたので、ここでは「プロキシ環境変数が立っているときほど (5) を疑う」とだけ覚えておいてください。
基本のプロキシ設定 — settings.json と環境変数、両方そろえる理由
Antigravity 本体(Chromium 層)は settings.json と OS のプロキシ設定を参照します。まずはここから。
// settings.json — プロキシの基本三点セット
{
// 社内で配られているプロキシの値に置き換える
"http.proxy" : "http://proxy.example.co.jp:8080" ,
// OS 設定との二重管理を避けたいので、私は settings.json を正にしています
"http.proxySupport" : "override" ,
// 証明書検証はオンのまま運用する(切らない理由は次のセクション)
"http.proxyStrictSSL" : true
}
一方、エージェントが子プロセスとして呼ぶ git・npm・curl などは settings.json を読みません。読むのは環境変数だけです。「補完は通るのにエージェントのツール実行だけ失敗する」場合、たいていここに穴があります。
# ~/.zshenv — CLI ツール・子プロセス用のプロキシ設定
export HTTPS_PROXY = "http://proxy.example.co.jp:8080"
export HTTP_PROXY = " $HTTPS_PROXY "
# 小文字しか見ないツールが残っているため、両方定義しておく
export https_proxy = " $HTTPS_PROXY "
export http_proxy = " $HTTP_PROXY "
export NO_PROXY = "localhost,127.0.0.1,::1"
export no_proxy = " $NO_PROXY "
ここで macOS 特有の落とし穴があります。Dock や Spotlight から起動した GUI アプリは、シェルの設定ファイルを読みません 。ターミナルから起動したときだけ動き、Dock から起動すると沈黙する——「昨日は動いたのに今日は動かない」の正体が起動方法の違いだったと気づくまで、私も数日遠回りをしました。
GUI 起動にも環境変数を効かせたい場合は launchctl を使います。
# GUI 起動(Dock / Spotlight)の Antigravity にも効かせる — macOS
launchctl setenv HTTPS_PROXY "http://proxy.example.co.jp:8080"
launchctl setenv HTTP_PROXY "http://proxy.example.co.jp:8080"
launchctl setenv NO_PROXY "localhost,127.0.0.1,::1"
# 反映にはアプリの完全終了 → 再起動が必要(Cmd+Q してから開き直す)
「settings.json と環境変数のどちらか片方でいいのでは」と思われるかもしれませんが、私は必ず両方そろえます。IDE 本体だけ通ってエージェントのツール実行が全滅する、あるいはその逆という「半分だけ動く」状態は、全滅よりも原因究明に時間を取られるからです。
SSL 検査型プロキシ — 検証の無効化ではなく、信頼の追加で通す
診断 (3) で issuer が社内 CA に化けていた場合、何も対応しなければ self signed certificate in certificate chain や UNABLE_TO_VERIFY_LEAF_SIGNATURE といったエラーが出ます。最短の応急処置は "http.proxyStrictSSL": false ですが、この設定の恒久化には反対の立場を取っています。
理由は単純で、Antigravity がモデル API に送っているのは自分のソースコードだからです。検証を切るということは、その通信を誰が復号していても気づけなくなるということで、社内プロキシ「だけ」を信頼するための手段としては粗すぎます。同じ設定がホテルの怪しい回線でも効いてしまう点が特に危険です。
私が推奨する正攻法は、検査プロキシが使っている社内 CA 証明書を「信頼するルート」に追加することです。情シスから配布されていればそれを使い、なければ自分で取り出せます。
# (1) プロキシが差し込んでいる証明書チェーンを取り出す
mkdir -p ~/certs
openssl s_client -connect generativelanguage.googleapis.com:443 \
-showcerts < /dev/null 2> /dev/null \
| awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' > ~/certs/corp-proxy-chain.pem
# (2) 何者の証明書かを目視確認 — issuer に社内 CA 名が出るはず
openssl x509 -in ~/certs/corp-proxy-chain.pem -noout -subject -issuer
# 出力例:
# subject= /O=ExampleCorp Security/CN=ExampleCorp TLS Inspection CA
# issuer= /O=ExampleCorp Security/CN=ExampleCorp Root CA
取り出した証明書を、レイヤーごとに配ります。
# (3) Node 系ランタイム(エージェント・拡張機能)への信頼追加
# NODE_EXTRA_CA_CERTS は既定のルート証明書への「追加」であり、置き換えではない
export NODE_EXTRA_CA_CERTS = " $HOME /certs/corp-proxy-chain.pem"
# (4) エージェントが子プロセスで呼ぶツールにも同じ信頼を配る
git config --global http.sslCAInfo " $HOME /certs/corp-proxy-chain.pem"
npm config set cafile " $HOME /certs/corp-proxy-chain.pem"
# (5) IDE 本体(Chromium 層)にはキーチェーン経由で効かせる — macOS
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ~/certs/corp-proxy-chain.pem
NODE_EXTRA_CA_CERTS を選んでいる理由は二つあります。第一に「追加」であって「置き換え」ではないため、公的 CA への信頼はそのまま残ること。第二に、環境変数なので外すのも一行で済むことです。社内ネットワークを離れたら unset するだけで、検査用 CA への信頼ごと消えます。trustRoot に入れたものも、常駐や出張が終わったタイミングで削除しておくと、信頼の置き忘れが残りません。
認証付きプロキシ — 資格情報を平文でばらまかない中継構成
社内プロキシにユーザー認証が付いている場合、最初に思いつくのは URL に埋め込む書き方です。
# 動きはするものの、おすすめしない書き方
export HTTPS_PROXY = "http://masaki:P@ssw0rd@proxy.example.co.jp:8080"
これが筋悪なのは、パスワードが env の出力・シェル履歴・プロセス一覧・dotfiles に平文で残るからです。私は設定ファイル類を Git で同期しながら2台の Mac を行き来する運用をしているので、この書き方を選ぶと「資格情報をリポジトリに push する事故」まであと一歩になります。アプリ事業で AdMob や決済まわりの鍵を扱ってきた経験からも、平文の置き場所を増やす構成は最初から候補に入れないのが安全だと考えています。
代わりに使っているのが、ローカル中継プロキシを一段挟む構成です。
Antigravity →(認証なし)→ 127.0.0.1:3128 のローカル中継 →(NTLM/Basic 認証)→ 社内プロキシ
中継には px のような軽量ツールが使えます。資格情報を知っているのは中継プロセスだけになり、Antigravity 側の設定からはパスワードが消えます。
// settings.json — IDE 側には資格情報を一切置かない
{
"http.proxy" : "http://127.0.0.1:3128" ,
"http.proxySupport" : "override"
}
# 環境変数側も中継に向ける — パスワードはどこにも書かれない
export HTTPS_PROXY = "http://127.0.0.1:3128"
export HTTP_PROXY = " $HTTPS_PROXY "
この構成の利点は、資格情報の置き場所が中継ツールの設定一箇所に集約されることです。パスワードのローテーションがあっても変更箇所は一つで、Antigravity・git・npm 側は何も触らずに済みます。「秘密は一箇所、参照は多数」という整理は、アプリの API キー管理とまったく同じ発想です。
NO_PROXY の設計 — Ollama と LM Studio をプロキシから確実に外す
プロキシ設定を入れた直後に多いのが、「昨日まで動いていたローカル LLM が見えなくなった」という二次被害です。HTTPS_PROXY を定義すると、明示的に除外しない限り 127.0.0.1 への通信までプロキシへ転送されます。社内プロキシにとっての localhost はプロキシサーバー自身ですから、あなたの Mac で動いている Ollama には永遠に届きません。
NO_PROXY の書き方には実装差という罠があります。
CIDR 表記(192.168.0.0/16)を解釈しないツールがある
ポート付き表記(127.0.0.1:11434)を無視する実装がある
ワイルドカード(*.local)の解釈がツールごとに違う
そのため個人的には、凝った書式に頼らずホスト名と IP の明示列挙に倒すことを推奨します。実際に私の環境でも、この形にしてから挙動のぶれが消えました。
# ローカル推論系をプロキシから外す — 凝った書式を避けて明示列挙する
export NO_PROXY = "localhost,127.0.0.1,::1,192.168.11.20,mac-studio.example-tail.ts.net"
export no_proxy = " $NO_PROXY "
# 確認: プロキシ環境変数が立った状態でも Ollama へ直結できるか
curl -s --max-time 3 http://127.0.0.1:11434/api/tags | python3 -m json.tool | head -6
# 期待出力(モデル一覧が返れば NO_PROXY が効いている):
# {
# "models": [
# {
# "name": "gemma4:27b",
# ...
192.168.11.20 と ts.net のホスト名は、自宅の Mac Studio を推論機にして外から Tailscale で繋いでいる私の環境の値です。LAN 内や VPN 内に推論マシンを置いている場合は、その分も忘れずに列挙します。LM Studio 側で似た症状が出たときは Antigravity で LM Studio のモデルが認識されない・接続が切れる — ポート・CORS・モデル可視性の切り分け の切り分けと対処の手順が役に立つはずです。
ここで NO_PROXY=* という「全部除外」に逃げたくなるかもしれませんが、これはプロキシ必須のネットワークでは外部 API が全滅する設定です。ローカルだけ直結・外部はプロキシ経由、という意図を NO_PROXY の列挙で正確に表現しておくと、ネットワークを移動しても設定の意味が崩れません。
移動先ネットワークの現実 — キャプティブポータル・テザリング・プロファイル切替
ここからは、ホテルや会場のネットワークで開発する場面の話です。個人でアプリ事業を始めて十年あまり、ここ数年は海外の展示に合わせて数週間単位で移動する生活が増えました。累計5,000万ダウンロード分のユーザーレビューとクラッシュレポートは旅先でも待ってくれないので、ホテルの回線で Antigravity を開く機会は必然的に多くなります。
その経験から言えるのは、移動先のネットワークは企業プロキシより行儀が悪い、ということです。
キャプティブポータル未認証の間は、全 HTTPS が同意画面へ横取りされて証明書エラーになります。壊れたのではなく、まだ同意画面を見ていないだけです
安宿や会場の透過型プロキシは、ストリーミング応答をバッファすることがあります。チャットの応答が「長い沈黙のあと一気にドカッと届く」場合はこれで、クライアント側の設定では直せないため回線を変えるのが正解です
従量制テザリングでのモデルのダウンロードは事故になります。私は展示準備の合間に Gemma 4 の 27B を従量テザリングで引いてしまい、数日分のデータ残量を一晩で使い切ったことがあります。ollama pull は固定回線のあるうちに済ませる、という教訓をその夜に得ました
この生活で固まったのが、ネットワーク状態をワンコマンドで切り替え・確認するシェル関数です。
# ~/.zshrc — 接続プロファイルの切り替えと現在地確認
proxy_on () { # 企業・会場プロキシ配下に入るとき
export HTTPS_PROXY = "http://proxy.example.co.jp:8080"
export HTTP_PROXY = " $HTTPS_PROXY " https_proxy = " $HTTPS_PROXY " http_proxy = " $HTTPS_PROXY "
export NO_PROXY = "localhost,127.0.0.1,::1" no_proxy = "localhost,127.0.0.1,::1"
echo "proxy ON: $HTTPS_PROXY "
}
proxy_off () { # 直結・テザリングに戻るとき
unset HTTPS_PROXY HTTP_PROXY https_proxy http_proxy NO_PROXY no_proxy
launchctl unsetenv HTTPS_PROXY 2> /dev/null
launchctl unsetenv HTTP_PROXY 2> /dev/null
echo "proxy OFF"
}
net_check () { # いまの現在地を3行で
echo "captive: $( curl -s -o /dev/null -w '%{http_code}' --max-time 5 http://captive.apple.com/hotspot-detect.html)"
echo "proxy: ${ HTTPS_PROXY :- none }"
echo "ollama: $( curl -s --max-time 2 http://127.0.0.1:11434/api/tags > /dev/null 2>&1 && echo OK || echo NG)"
}
ネットワークが完全に死んでいる移動日でも、ローカルの Gemma 4 さえ動けば補完とリファクタリングの相談は続けられます。オフライン前提の組み方は Antigravity に Gemma 4 ローカルモデルを統合する — オフライン/エアギャップ環境での AI 開発 に、クラウドとローカルを自動で切り替える構成は Antigravity × マルチプロバイダー LLM フェイルオーバー — Gemini / Claude / ローカル Gemma を止めない本番構成 にまとめてあります。プロキシ設計とローカルフォールバックをセットで考えるようになってから、移動中の開発は目に見えて安定しました。
よくある誤りと落とし穴
私自身の失敗と、読者の方からいただいた相談の中から、再発の多い順に並べます。
proxyStrictSSL: false が1年残る : 出張先での応急処置がそのまま恒久設定になるパターンです。応急処置として使うこと自体は否定しませんが、使ったら「戻す手順」をセットで仕込んでおきます。私は設定を変えた日のカレンダーに「strictSSL を戻す」を入れる運用にしています
.zshrc にだけ書いて GUI 起動で効かない : Dock 起動のアプリはシェルの rc ファイルを読みません。launchctl setenv を併用するか、起動方法をターミナル経由に統一するか、どちらかに決めて揺らさないことです
NO_PROXY に CIDR・ポート・ワイルドカードを詰め込む : 一部のツールには効いて一部には効かない、という最悪の中間状態を生みます。明示列挙が退屈でも確実です
settings.json に user:pass@ を直書きして Settings Sync に乗せる : 同期先の全マシンと同期サービスに資格情報が複製されます。プロキシ設定を同期対象から外すか、中継構成にして資格情報そのものを設定から消すか、どちらかにします
キャプティブポータル未認証を証明書問題と誤診する : ホテルで証明書エラーを見て NODE_EXTRA_CA_CERTS をいじり始めると、帰宅後も壊れたままになります。診断の順序を「captive → proxy → issuer」に固定しておくと、この誤診は構造的に防げます
会社では動くのに自宅で動かない : launchctl setenv で入れたプロキシが自宅でも残留しているケースが定番です。proxy_off に launchctl unsetenv まで含めているのはこのためです
まとめ — 接続は壊れるものではなく、設計するもの
プロキシ対応というと「動かなくなったときに調べる対症療法」になりがちですが、移動と環境の変化が前提の働き方では、接続レイヤーそのものを設計対象として扱う方が結果的に楽でした。症状からレイヤーを逆引きし、レイヤーごとに設定の置き場所(settings.json・環境変数・証明書・NO_PROXY)を決めておけば、初見のネットワークでも10分で現在地が分かります。
次にネットワークを移動したら、設定を変える前に net_check の3行だけ打ってみてください。「いまどこにいるか」を先に知る習慣が付くと、プロキシは戦う相手ではなく、ただの前提条件になっていきます。移動の多い生活の中で開発を続けている方の参考になれば嬉しいです。