メインコンテンツへスキップ

arkor loginarkor logoutarkor whoami

~/.arkor/credentials.json を読み書きするだけの 3 つの短いコマンドです。いずれも .arkor/state.json には触りません。匿名ワークスペースでは、初回 trainer.start()(または初回推論呼び出し)でランタイムがプロジェクトルーティングを自動作成します。OAuth ワークスペースでは学習の前に .arkor/state.json が存在している必要があります。今のところ arkor loginarkor init もこれを作らないので、現実的なパスは { orgSlug, projectSlug, projectId } を手で書くことです。状態ファイルが無くてランタイムがエラーを返すと、このフォールバックを案内します。

arkor login

pnpm exec arkor login
マネージドバックエンドにサインインします。フラグなしの場合、CLI は Arkor Cloud の OAuth と匿名セッションのどちらを使うかを対話的に尋ねます。対話セレクタの初期選択は Anonymous なので、デフォルトを受け入れる(あるいは非 TTY にパイプする)と匿名パスに進みます。OAuth が走るのは明示的に選択するか --oauth を渡したときだけです。

概要

arkor login [options]

オプション

フラグ説明
--oauthピッカーをスキップして Arkor Cloud の OAuth(Authorization Code + PKCE)フローを直接走らせる。--anonymous と排他。process.env.CI が立っていると --oauth needs a browser callback that CI runners can't complete. Use --anonymous in CI.(CI ランナーが完了できないブラウザーコールバックを --oauth は必要とする。CI では --anonymous を使ってください)で失敗します。PKCE はブラウザーコールバックを必要とするため、CI ではループバックが永遠にハングするからです。
--anonymousピッカーをスキップして使い捨ての匿名トークンを要求。--oauth と排他。これは arkor dev の起動時に認証情報がディスクに無いときに走るのと同じパスです。arkor dev は必ずまず匿名でブートストラップします。
--no-browser自動の open(url) 呼び出しを無効化。authorization URL はいずれにせよ表示されます(Browser: <url>(ブラウザー: <url>)行)。このフラグは CLI がブラウザーを起動するのを止めるだけです。ヘッドレス環境(SSH、Docker)で便利。OAuth パスにのみ影響します。

何が起きるか

  1. CLI はクラウド API の /v1/auth/cli/config を呼んでデプロイの OAuth 設定を読みます。
  2. --anonymous が渡されたら、/v1/auth/anonymous から匿名トークンを要求し、mode: "anon"~/.arkor/credentials.json に書きます。
  3. --oauth が渡された場合、ピッカーをスキップして直接 OAuth フローへ。
  4. フラグが渡されない場合、対話ピッカー(OAuth (browser) / Anonymous)を表示し Anonymous が事前選択されます。デフォルトを受け入れる(プロンプトがブロッキングしない非対話的な場面でも同様)と匿名パスが走り、OAuth を選ぶと OAuth フローが走ります。
  5. OAuth フローは PKCE ペアを生成し、クラウド API から提供されたコールバックポートのいずれかでループバック HTTP サーバーを起動し、authorize URL を開く(または表示する)、コールバックを待ちます。コードをトークンに交換する前に state を検証し、不一致は CSRF 防止のため Abort されます。得られた OAuth トークンは mode: "auth0"~/.arkor/credentials.json に書かれます。
ループバックサーバーは finally ブロックで閉じられるので、login が失敗してもサーバーは残りません。

匿名モードを 1 段落で

匿名認証は、アカウントなしで Arkor を試すためのものです。学習、ジョブ、その他の作業は匿名トークンを介してローカルマシーンに紐づきます。あとで OAuth に切り替える(arkor login --oauth、またはピッカーから OAuth (browser) を選ぶ)と認証情報ファイルは差し替えられますが、作業は移行されません。匿名で学習したものを残したいなら、学習を始める前に arkor login --oauth を走らせてください。 匿名アカウントは設計上 単一端末専用 です。クラウド API は匿名ユーザーごとに latest_jti を保持しており、userAuth は受信した JWT の jti が一致しないリクエストをすべて拒否します。jti はトークンのローテーションでしか変わらないので、実際の発火タイミングは大きく 2 つに分かれます。今のところ CLI は匿名トークンの自動 refresh を実装していません(@arkor/cloud-api-clientgetToken() 側で配線予定で、SDK ロードマップ に乗っています)。そのためクライアント側からのローテーションは起こらず、別マシーンにコピーした ~/.arkor/credentials.json も大抵しばらく動いてしまいます。失効するのは、発行ユーザーが明示的に新 identity を発行したとき(arkor login --anonymous が新しい jti でファイルを上書き)か、管理者がサーバー側でローテーションしたとき。そのタイミングで他のコピーは次の呼び出しから失敗します。自動 refresh が入ると、refresh のたびに latest_jti が即座に進むので、別端末(または同じマシーン上の古いバックアップ)に残った旧 jti のコピーは予告なく次の呼び出しで失敗するようになります。いずれにせよ、負けた側のクライアントは HTTP 401 / 409 を code: "anonymous_token_single_device" で受け取り、cli/main.ts がそれを実行可能なガイダンスとして整形します。匿名行そのものが削除された場合は code: "anonymous_account_not_found" も同じ仕組みで surface されます。リカバリー提案は デプロイ形態に応じて分岐 します。OAuth がサポートされているデプロイでは arkor login --oauth を案内して複数端末対応のアカウントへサインアップする経路を示し、匿名専用デプロイ(OAuth 未設定)では代わりに arkor login --anonymous を案内します。後者で --oauth を出すとそのコマンドはそのまま失敗するので、新規匿名 identity の発行が唯一のリカバリ手段になるためです。いずれのパスも、過去の匿名作業は移行されません。前のワークスペースには発行元の credentials ファイルからしか到達できません。

匿名発行時の出力

どちらの匿名パスでも、新しい anonymousId と「同じ id がセッションをまたいで Arkor Cloud がこのクライアントを認識するための識別子である」旨の説明を必ず surface します。ただし出力の形は入口によって異なります。arkor login--anonymous フラグまたはピッカー → Anonymous)はスピナーの停止行として Anonymous id: <id> を出し、続けて「認証情報ファイル(credentialsPath()、Linux と macOS では通常 ~/.arkor/credentials.json)を保持していれば同じ identity を維持できる」旨の info 行を別行で出します。arkor dev の自動ブートストラップはスピナーを使わず、id と同じ説明を 1 本の info 行にまとめて出します。ピッカー → Anonymous のパスでは、さらに成功メッセージと並んで 1 行の warn(Anonymous sessions aren't guaranteed to persist — sign in with `arkor login --oauth` to tie future work to your Arkor Cloud account.、和訳: 匿名セッションは永続性が保証されないので、今後の作業を Arkor Cloud アカウントに紐付けたいなら arkor login --oauth でサインインしてください)が出るので、発行時点でアップグレードのヒントが見えます。明示的な --anonymous ショートカットでは /v1/auth/cli/config の取得をスキップしているため arkor login --oauth がそのデプロイで成功するかわからず、稀に存在する匿名専用デプロイで失敗するコマンドへユーザーを誘導しないよう、warn は意図的に抑制されます。 匿名発行のあらゆる入口で、単一端末の制約も別行の info として surface します。実際の文言は永続性ナッジと同じ oauthAvailable のゲーティング契約に従って分岐します。OAuth サポートのデプロイでは Note: anonymous accounts work on this machine only. Run `arkor login --oauth` to sign up for multi-device access.(和訳: 注意: 匿名アカウントはこのマシーンでのみ動作します。複数端末で使うには arkor login --oauth でサインアップしてください)が出ますが、匿名専用デプロイ、および /v1/auth/cli/config の取得を意図的にスキップする arkor login --anonymous の経路では、bare な Note: anonymous accounts work on this machine only. だけが出ます。失敗確実なコマンドへユーザーを誘導しないためです。arkor whoami も匿名 identity に対しては bare 版のみを stderr に出します。さらに stdout / stderr の両方が TTY のときに限るので、出力をリダイレクトしたとき(stdout が TTY でなくなる)や、stderr 出力をすべて警告扱いする CI ランナー(stderr が TTY でなくなる)では追加のテキストは出ません。あくまで UX のヒントであり、どの挙動もゲートしません。stdout 側の形(JSON.stringify(user, null, 2) で出される user オブジェクトの JSON と、org に所属していれば続けて 1 行の人間向け Orgs: <slug>, … 行)は note 追加前と変わりません。ただし Orgs: 行は JSON 本体の一部ではなく後ろに付くサマリ行なので、出力全体をそのまま jq のような厳密な JSON パーサーに通すのは避けてください。

arkor logout

pnpm exec arkor logout
~/.arkor/credentials.json を削除します。デフォルトでは確認プロンプトが出ます。

概要

arkor logout [options]

オプション

フラグ説明
-y, --yes確認プロンプトをスキップ。

振る舞い

  • 認証情報ファイルが存在しなければ、CLI は No credentials on file.(認証情報ファイルがありません)と出して終了。
  • ユーザーがプロンプトを断ると Aborted.(中止しました)と出して削除せずに終了。
  • arkor logout.arkor/state.json.arkor/build/ 成果物には触りません。完全に最初からやり直すには .arkor/ も手動で削除してください。

arkor whoami

pnpm exec arkor whoami
クラウド API の /v1/me から現在の identity を表示し、到達できる org slug も並べます。

概要

arkor whoami
フラグはありません。

出力

サインイン中なら user オブジェクトを JSON として整形表示し、レスポンスに org が含まれていれば Orgs: <slug>, <slug>, …(org 一覧)を 1 行で出します。~/.arkor/credentials.json が無いときは Not signed in. Run \arkor login` or `arkor login —anonymous`.(サインインしていません。arkor loginまたはarkor login —anonymous` を実行してください)と出して終了します。

終了コード

  • 0: サインイン中、identity を表示。
  • 0: 未サインイン、メッセージは情報用のみ。
  • 1: クラウド API が 426 Upgrade Required を返した。CLI はアップグレードのヒント(と検出したパッケージマネージャ用のアップグレードコマンド)を表示し、process.exitCode = 1 を立てて、arkor のシャットダウンフックの非推奨警告フラッシュが終了前に走るようにします。
  • 1: クラウド API が認証状態系の構造化 codeanonymous_token_single_device または anonymous_account_not_found)を返した。cli/main.ts のトップレベルハンドラがそれを stderr 上の実行可能なメッセージへ整形します。具体的な文言は トークンの有効期限 を参照。
  • 1: それ以外の非 2xx(一過性の 5xx、未マップの 4xx など)。以前は「Failed to fetch /v1/me (<status>). Token may be expired. を stdout に出して終了コード 0」でしたが、本リリースで撤廃しました。arkor whoamiCloudApiError を投げ、bin.tserr.message(例: cloud-api 503)だけを stderr に出してから非ゼロで終了します。スタックトレースは未知の Error 形(実質 SDK のバグ)に限り出すので、通常の HTTP 失敗はラッパーのログを汚しません。

認証情報の保存場所

両モードとも同じファイル ~/.arkor/credentials.json に書き、mode フィールドが "auth0""anon" でタグ付けされます。これにより CLI(と Studio サーバー)はどのパスを使うかわかります。レイアウト全体は プロジェクト構成 を参照。

トークンの有効期限

OAuth セッションでは、認証情報ファイルにアクセストークンと発行されたリフレッシュトークン、トークン交換が返した expiresAt タイムスタンプを記録します。リフレッシュトークンは保存していますが、CLI は まだ 期限切れアクセストークンの自動リフレッシュをしません。これはロードマップ上です。 実用上の意味は次のとおりです。
  • 期限切れまたは無効化されたトークンはクラウド API からの非 2xx として現れます。arkor whoami は汎用的な「Token may be expired」を出さなくなり、代わりに上流の code(あれば)を持った CloudApiError を投げ、cli/main.ts のトップレベルハンドラが既知 2 種の認証状態 code を実行可能なガイダンスへ整形します。整形前に main()/v1/auth/cli/config を best-effort で取得し、リカバリーヒントをデプロイ形態に揃えます。
    • code: "anonymous_token_single_device":
      • OAuth サポートのデプロイ: Anonymous credentials were rejected as single-device. Anonymous accounts only work on one machine. Sign up for an account that supports multiple devices: arkor login --oauth(終了コード 1)。
      • 匿名専用デプロイ: Anonymous credentials were rejected as single-device. Anonymous accounts only work on one machine. This deployment does not advertise OAuth, so the only recovery is to mint a new anonymous identity (your previous workspace data cannot be recovered): arkor login --anonymous(終了コード 1)。
    • code: "anonymous_account_not_found" も同様に分岐し、末尾は arkor login --oauth または arkor login --anonymous のいずれか。
    既知の code を持たないエラー(および CloudApiError 以外の例外)は main() から再 throw されます。bin.ts のトップレベル await main(...) は try/catch で囲まれており、エラーの形で挙動を分けます。CloudApiErrorerr.message(上流の error 本文、または本文が空のときの cloud-api <status> フォールバック)だけを出すので、通常の HTTP 失敗は 1 行で終わり、原因を切り分けやすくなります。それ以外の Errorerr.stack ?? err.message で出すので、本物の SDK バグはフレームが見えます。いずれの場合も process.exit(1) ではなく process.exitCode = 1 を立てるので、main()finally ブロックの非推奨警告フラッシュ + テレメトリーシャットダウンは終了前にちゃんと走ります。明示的に catch しているのは、Node のデフォルトの unhandled rejection ハンドラがバンドル後の minified なコードフレームを出すのを避け、サポート対象の Node バージョン全体で stderr の flush を確定させるためでもあります。
  • OAuth セッションの直し方は arkor login --oauth をもう一度走らせることです。フル PKCE フローを通って ~/.arkor/credentials.json を新トークンで上書きします。
匿名トークンはサーバー側に 90 日の TTL がありますが、CLI はまだ自動リフレッシュをしません。その配線は @arkor/cloud-api-clientgetToken() 側にあり、SDK ロードマップに残っています。今日時点で匿名セッションが失敗し始めたら arkor login --anonymous で新しいものを発行してください(新しい anonymousId が発行されるので、実質的には別ワークスペースになります)。

よくあるエラー

メッセージ場所意味対処
Pick one of --oauth / --anonymous, not both.--oauth--anonymous のどちらか一方だけ指定してください)arkor loginモードフラグを両方渡した。どちらか一方にする。
--oauth needs a browser callback that CI runners can't complete. Use --anonymous in CI.(CI ランナーが完了できないブラウザーコールバックを --oauth は必要とする。CI では --anonymous を使ってください)arkor login --oauthprocess.env.CI が立つ環境)PKCE はブラウザーからのループバックリダイレクトに依存し、CI ではこれを満たせない。CI では --anonymous を使う。ブラウザーに到達できるローカルのヘッドレスフロー(例: ... --no-browser | tee logs)では、その実行の間 CI を unset にする。
State mismatch — aborting to prevent CSRF(state の不一致のため CSRF 防止で中止しました)arkor login --oauthループバックコールバックに返ってきた state が CLI の生成したものと一致しない。たいていは前回 login の古いタブをブラウザーが開いたケース。arkor login --oauth を再実行し、新規に開いたタブでフローを完了。
Auth0 did not return a refresh token. Make sure the Application has 'offline_access' scope enabled.(Auth0 がリフレッシュトークンを返しませんでした。Application で offline_access スコープを有効にしてください)arkor login --oauthOAuth のトークン交換は成功したがレスポンスに refresh_token が無く、CLI がアクセストークンの寿命を超えてセッションを保てない。たいていデプロイ側の設定ミス。OAuth(Auth0)アプリケーションで offline_access スコープを有効化してから arkor login --oauth を再実行。
No credentials on file.(認証情報ファイルがありません)arkor logout~/.arkor/credentials.json が存在しない。削除対象なし。サインインしたいなら先に arkor login
Not signed in. Run \arkor login` or `arkor login —anonymous`.(サインインしていません。arkor loginまたはarkor login —anonymous` を実行してください)arkor whoami上と同じ条件を別コマンドから出している。同じ対処。
Anonymous credentials were rejected as single-device. …(末尾は arkor login --oauth または arkor login --anonymous、デプロイ形態次第)arkor whoami および認証付きの全コマンドクラウド API が code: "anonymous_token_single_device" で拒否した(userAuth の jti チェックからの HTTP 401、または rotate-jti の CAS からの HTTP 409)。認証情報ファイルが別端末にコピーされたか、別のローカルプロセスがこのトークンを recovery window 内でローテートし越えた、のいずれか。メッセージ末尾のコマンドに従う: OAuth サポートのデプロイなら arkor login --oauth、匿名専用デプロイなら arkor login --anonymous。どちらも 新規 identity で、過去の匿名作業は移行できない。CLI は 1 で終了。
Your anonymous credentials are no longer valid. …(末尾は arkor login --oauth または arkor login --anonymousarkor whoami および認証付きの全コマンドクラウド API が code: "anonymous_account_not_found" で拒否した(HTTP 401)。背後の anonymous_users 行が削除された(admin / cascade / 明示的な revoke)。上と同じく、メッセージ末尾のデプロイ依存コマンドに従う。前の匿名ワークスペースは取り戻せない。CLI は 1 で終了。
cloud-api <status>(1 行、スタックなし)arkor whoami および認証付きの全コマンド構造化された認証状態 code を持たない非 200 / 非 426 のクラウド API レスポンス(一過性の 5xx、未マップの 4xx など)。cli/main.tsCloudApiError をそのまま再 throw し、bin.ts がスタックの最上位で catch して err.message(上流の error 本文、または本文が空のときの cloud-api <status> フォールバック)だけを表示した後、process.exitCode = 1 をセットする。スタックトレースは未知の Error 形(実質 SDK のバグ)に限り出す。メッセージをそのまま確認し、トランスポート / サーバー障害なら再試行。OAuth アクセストークンの期限切れなら arkor login --oauth を再実行。匿名トークンの期限切れなら arkor login --anonymous を再実行(新しい anonymousId で別ワークスペースになる)。
426 Upgrade Required(アップグレードヒント付き)arkor whoami(および他のクラウド API 呼び出し)デプロイがより新しい SDK バージョンを要求している。CLI は検出したパッケージマネージャ用のアップグレードコマンドを表示し、process.exitCode = 1 を立てる。arkor パッケージをアップグレードして再実行。