Yyatmita

opencode の xAI Grok OAuth は X Premium でも通る — ただし『Headless / Remote / VPS』を選ぶと詰む

opencode 1.15.7 で入った xAI Grok OAuth、X Premium サブスクでも公式に通るはずなのに、メニューの『Headless / Remote / VPS』を選ぶと数秒で『無効または期限切れのコード』が返ってきて詰む。切り分けの記録と、PKCE loopback フロー + ssh tunnel で通すまで。

自分のエージェント基盤を組む#opencode#xai#grok#oauth#x-premium#ssh-tunnel#dev-container

opencode を 1.4.1 → 1.15.7 に更新したら、目玉として xAI Grok OAuth サインインが入っていた(v1.15.7 / 2026-05-21 リリース、@Jaaneek 実装)。SuperGrok / X Premium のサブスクをそのまま使えるという触れ込みで、xAI 公式アナウンス も「Grok or X Premium subscribers」と謳っている。

API キー管理は面倒だし、せっかく X Premium 払っているのだから使わない手はない。さっそく dev コンテナで認証を通そうとして、見事に 1 時間以上溶かした。

結論から書くと、メニューに 2 つあるフローのうち、X Premium で通るのは片方だけで、もう片方を選ぶと数秒で「無効または期限切れのコード」が返ってきて詰む。しかもラベル名がミスリーディングで、Premium ユーザーは詰む側に誘導される構造になっている。

TL;DR(同じエラーで来た人向け)

メニュー項目実態X Premium
xAI Grok OAuth (SuperGrok Subscription)PKCE loopback(127.0.0.1:56121 callback)✅ 通る
xAI Grok OAuth (Headless / Remote / VPS)device-code(accounts.x.ai/oauth2/device 手入力)❌ 数秒で「無効または期限切れのコード」

「SuperGrok」ラベルでも X Premium で通る。Headless / VPS でも ssh -L 56121:127.0.0.1:56121 で手元から tunnel すれば PKCE loopback の方を使える。詳細手順は #解決: PKCE loopback フロー + ssh tunnel へ。

何が起きるのか

opencode auth login -p xai を打つと、ログイン方式の選択メニューが出る。

┌  Add credential
◆  Login method
│  ● xAI Grok OAuth (SuperGrok Subscription)
◇  Login method
│  xAI Grok OAuth (Headless / Remote / VPS)

dev コンテナや VPS で動かしているなら、素直に下の 「Headless / Remote / VPS」 を選びたくなる。実際自分もそうした。コンテナにはブラウザがないので、device-code フロー(CLI が短いコードを表示、別端末のブラウザで accounts.x.ai/oauth2/device に入力して承認)が筋に見える。

ところが、ブラウザでコードを入力して承認ボタンを押した瞬間、こう返ってくる。

承認エラー
無効または期限切れのコードです。ログインのフローを再起動してください。

数秒前に発行されたコードがいきなり expired と言われる。再試行しても同じ。

切り分け(全部外れた)

最初に疑うのは順番に:

  1. コードの転記ミス: 0/O 1/l あたり。何度やっても同じ
  2. コードのコピー期限切れ: 表示から数秒。コードの TTL は通常 10〜15 分のはずなので無関係
  3. URL の ?user_code= 自動入力バグ: opencode が表示する 2 つの URL のうち、?user_code= 付きの方ではなく、パラメータ無しで開いて手入力 → 同じく数秒で expired
  4. ブラウザのセッション衝突: シークレットウィンドウで X Premium アカウントだけにログイン → 同じく失敗
  5. アカウント不一致: X Premium 契約アカウントと、accounts.x.ai でログインしているアカウントが完全一致しているか確認 → 一致している

ここまでで「サーバ側で何か弾かれている」と判断するしかなくなる。

途中で「SuperGrok 必須なのでは」と疑った(メニューラベルが "SuperGrok Subscription" だったので)。が、xAI 公式アナウンスは "Grok or X Premium" と言っている。ツイートのリプライにも「Premium で詰む」と文句を言っている人はいない。自分のアカウント固有の何かが原因と考えた方が筋が通る。

決定打: Hermes が同じ X Premium で通っている

ローカルの auto-memory を漁ったら、5 日前に立てた Hermes Agent(個人用、Pi5 上)が同じ X Premium アカウントで xai-oauth provider を通している事実が出てきた。Hermes Agent は NousResearch/hermes-agent の OSS で、v0.14.0 (2026-05-16) から any paying Grok subscriber 対応になっている。

つまり「X Premium で xAI OAuth は実際に通る」のは実証済み。であれば、opencode 側で何かが違う

差を取ると 1 つだけ違いがあった。OAuth のフローが違う

  • Hermes: PKCE loopback(CLI が 127.0.0.1:56121 で listener を立て、ブラウザが承認後 http://127.0.0.1:56121/callback?... にリダイレクトして直接 token を渡す)
  • opencode で選んだ方: device-code(CLI は polling、ユーザーがブラウザで短いコードを手入力)

両方とも同じ xai-oauth provider、同じ X アカウント、同じ Premium。それなのに片方は通って、もう片方は数秒で invalid を返す。

解決: PKCE loopback フロー + ssh tunnel

opencode のメニューに戻る。

●  xAI Grok OAuth (SuperGrok Subscription)   ← これが PKCE loopback
◇  xAI Grok OAuth (Headless / Remote / VPS)  ← これが device-code(X Premium で詰む)

ラベル "SuperGrok Subscription" の方が PKCE loopback だった。X Premium ユーザーは「自分は SuperGrok じゃない」と思って Headless 側に流れる導線になっているが、実際に Premium で通るのはこっち。

問題は、PKCE loopback はブラウザが http://127.0.0.1:56121/callback を叩く前提なので、CLI とブラウザが同じマシン上にいる必要があること。dev コンテナで opencode を動かしている自分の構成(Windows ホスト + Docker Desktop + dev コンテナ)では、Windows のブラウザから dev コンテナ内の 56121 ポートに直接届かない。

これは Hermes (Pi5) を立てたときも同じ問題で、ssh tunnel で迂回した。同じ手を使う。

手順

Windows PowerShell で ssh tunnel を張りっぱなしにする。dev コンテナの SSH は 2222 で publish 済み。

ssh -p 2222 -N -L 56121:127.0.0.1:56121 dev@localhost

これで Windows の localhost:56121 が dev コンテナの 127.0.0.1:56121 に転送される。

dev コンテナで opencode の認証フローを起動。

opencode auth login -p xai
# → 「xAI Grok OAuth (SuperGrok Subscription)」を選ぶ

URL が表示されるので Windows ブラウザで開く。X Premium アカウントで承認すると、ブラウザは http://127.0.0.1:56121/callback?... にリダイレクト → ssh tunnel 経由で dev コンテナの opencode が token を受け取る → 完了。

opencode auth list
# ●  xAI [oauth]   ← これが出れば OK

ここで初めて Grok 4.3 系を opencode 上で叩けるようになった。

なぜ device-code は X Premium で詰むのか(推測)

xAI の公式ドキュメントに明示が無いので観察ベースの推測になるが、整合性が取れる説明はこれ。

同じ xai-oauth provider でも、サーバ側の subscription チェック実装がフローごとに違うように見える。

  • PKCE loopback: grok.com 経由の Web ログインと同じ token 経路。X Premium のクォータも認識されるので、Premium で通る
  • device-code: SuperGrok ユーザー向けに設計されたまま、Premium 対応のロールアウトが追いついていない(あるいはサーバ側で subscription mismatchinvalid_grant に変換して返している)

opencode 側のメニューラベルが "SuperGrok Subscription" / "Headless / Remote / VPS" になっているのは、実装者の前提が「PKCE = SuperGrok ブラウザログイン / device-code = headless 用」だった名残と思われる。Premium ユーザーが PKCE 側でも通る、という事実が暗黙に成立しているだけで、ラベルにはそれが現れていない。

これは「抜け穴」ではなく、正規の使い方として PKCE loopback フローが Premium を受け入れている、と理解すべき。実装側の罠を回避するだけの話。

副次的に直したこと: opencode plugin 設定の掃除

別件として、起動のたびにこのエラーが出ていた。

ERROR service=plugin pkg=tumf/opencode-openai-device-auth ...
  error=git dep preparation failed failed to install plugin

/workspace/.opencode/opencode.json で参照していた古い OpenAI device-auth プラグイン(tumf/opencode-openai-device-auth)。opencode 自体が OpenAI OAuth をネイティブ対応するようになった今は不要。設定から外したらクリーンになった。

// before
{
  "$schema": "https://opencode.ai/config.json",
  "plugin": [
    "tumf/opencode-openai-device-auth"
  ]
}
 
// after
{
  "$schema": "https://opencode.ai/config.json"
}

OpenAI / xAI 両方とも、opencode 本体側の OAuth 実装が成熟したので、サードパーティのデバイス認証プラグインを噛ませる必要はなくなった。

まとめ

  • opencode 1.15.7 で xAI Grok OAuth に対応、X Premium で正規に使える
  • ただし opencode auth login -p xaiメニューラベルが misleading
    • xAI Grok OAuth (SuperGrok Subscription) → PKCE loopback、Premium で通る
    • xAI Grok OAuth (Headless / Remote / VPS) → device-code、Premium だと数秒で invalid を返して詰む
  • Premium ユーザーは PKCE loopback 側を選ぶのが正解。dev コンテナ/VPS なら ssh tunnel で port 56121 を転送すれば headless でも通る
  • 観察ベースの推測だが、PKCE loopback は grok.com Web ログインと同じ token 経路を踏むので Premium のクォータが認識される、device-code は SuperGrok 前提の実装が残っている、というのが症状と整合する

opencode の Grok 対応はまだ公開から 2 日。メニューラベルや device-code 側の rollout はそのうち直るはずだが、今ハマっている人向けに記録を残しておく。

参考