メインコンテンツへ

astar CLI

astar は backend の Tool Router に対する薄いターミナルクライアントです。ローカルにロジックはほとんど無く、ほぼすべてのサブコマンドはそのまま backend に転送され、backend 側でレンダリングされます。

実パッケージ一覧

cli/
├── main.go                # サブコマンドの switch はここだけ
├── internal/
│   ├── agentbinary/         # astar-agent バイナリの解決
│   ├── auth/                 # SA トークン・device flow OAuth
│   ├── client/                # backend API クライアント
│   ├── doctor/                # 接続診断
│   ├── output/                 # --format/--fields レンダリング
│   └── updater/                # 自己更新
└── skills/astar/              # Claude Code / Codex 向け同梱 skill

internal/commands/ のような verb 別パッケージ分割は存在しません。main.go の switch がサブコマンドの全体です。

パッケージ役割
agentbinaryastar mount / astar unmount が exec 委譲する先の astar-agent バイナリを解決する。自分と同じディレクトリを優先し、次に $PATH を探す。astar doctor のバイナリ有無報告にも使われる
authService Account トークンと device flow OAuth(deviceflow.go)による認証、認証情報の保存
clientbackend API へのリクエスト送信。env → header 変換(後述)もここ
doctorastar doctor の接続診断ロジック
output--format(json/table/tsv)・--fields--output(ダウンロード先)のクライアント側レンダリング
updaterastar update の自己更新(ダウンロード・検証・置換)

何ができるか

ローカル実装(main.go の switch にある verb だけ): login / logout / update / use(ワークスペース切り替え) / doctor / mount / unmount / --version / 出力レンダリングフラグ。

それ以外は全部 backend に生転送されます。POST /api/v1/cliAstarCliController.ktcore/mcp/api/controller/)が受け取り、AI エージェントと同じ AstarToolRouter を通します。コマンドは <group> <subcommand> [--arg value ...] の形式で、help / <group> help で一覧を取得できます。

新しいサーバー側コマンドを追加するときは backend の router(Kotlin)に足すmain.go に新しい switch case を足さないこと。この switch は上記のクライアント専用 verb のためだけに存在し、ここに server-side tool 用の case を足すと router のゲーティングを迂回し、backend 側と重複したロジックになる。

破壊的操作のセマンティクス(SEC-002)— ここは「直さない」

  • 裸の delete はローカルで確認を挟まず即コミットされる(Unix の rm と同じ意味論)。確認ヘビーな UI に慣れていると意外に見えるが、意図的な設計。
  • CanonicalVerbs.DESTRUCTIVE_VERBS(backend の core/mcp/infrastructure/annotation/CanonicalVerbs.kt)と alwaysConfirmToolGate / AgentOrchestrator / AgentToolLoopPhase)はすべて backend 側にあり、CLI にクライアント側の確認ロジックは存在しない。
  • --dry-run でプレビューのみ、--confirm false でその呼び出し限定のプレビューデフォルト動作に戻せる。

認証・ヘッダ

  • 主認証は SA トークン、Authorization: Bearer のみ。CLI は X-Tenant-Id を送らず、テナントはトークンから backend 側で解決される。
  • go-agent が AI Member セッション用に CLI をスポーンするときだけ、env → header パターンでアンビエントコンテキストを渡す(internal/client/client.go):
    • ASTAR_CLI_SESSION_TICKET(env) → X-Cli-Session-Ticket(header)
    • ASTAR_CURRENT_WORKSPACE_ID(env) → X-Astar-Ambient-Workspace-Id(header)

    新しいヘッドレス/アンビエントコンテキストを追加する場合も、この env-in → header-out パターンに合わせること。新しい ad-hoc フラグや設定ファイルを発明しない。

Claude Code / Codex 向け同梱 skill

cli/skills/astar/SKILL.md.claude / SKILL.md.codex / CLAUDE.md.fragment があり、cli/scripts/install-cli.shastar 本体と一緒にダウンロードして、ユーザーのローカル Claude Code / Codex の skill ディレクトリに配置します。これにより、事務員が「案件」「証拠説明書」などの話題を出したときにローカルの AI エージェントが astar コマンドの有無・接続状態を確認し、使い方を案内できるようになります。

backend との関係 — core/mcp であって core/cliexec ではない

astar CLI の実体は core/mcp モジュールです。AstarCliControllerPOST /api/v1/cli)が AstarToolRouter を呼び出し、AI エージェントが使うのと同じツール群を CLI からも実行できるようにしています。

紛らわしいですが、core/cliexecastar CLI とは別物です。名前が似ていて実際に混同しやすいので明記します。core/cliexec が扱うのは「ローカル CLI プロバイダ(Claude Code / Codex)セッション」——顧客の go-agent が AI Member のためにスポーンする claude / codex サブプロセスと、そのプロセスからの承認要求・ask_user 呼び出しを backend にブリッジする仕組みです(CliBridgeRequestDispatcherCliSessionRegistry)。フローはこうです。

CLI subprocess (claude / codex)
  │ MCP tool 呼び出し (astar__request_approval / astar__ask_user)
  ▼
Go-Agent stdio MCP bridge
  │ WebSocket 経由で CliSessionMcpRequestMessage を転送
  ▼
AgentWebSocketHandler → core/cliexec (CliSessionRegistry / CliBridgeRequestDispatcher)

astar バイナリのユーザーが打つコマンドはこの経路を一切通りません。core/cliexecCliSession は「AI Member としてローカルで動く Claude Code/Codex の 1 会話」を指し、astar CLI の「ターミナルから backend の tool router を叩く 1 リクエスト」とは無関係です。

ビルド

cd cli && go test ./...
  • cli-ci.ymlgo test ./... に加えて、Auth0 の値を ldflags で焼き込んだリリースビルドを実行する(-X astar-cli/internal/auth.Auth0Domain/ClientID/Audience、値は cli/Makefile 経由で infrastructure/deploy.env から)。
  • 新しいビルドパス(2 本目のバイナリターゲットなど)を追加する場合も同じ ldflags セットを注入すること。省略すると Auth0 設定なしでビルドされてしまう。

参照ソース

  • cli/CLAUDE.md
  • cli/ 実コード(main.go / internal/*
  • backend/.../core/mcp/api/controller/AstarCliController.kt
  • backend/.../core/cliexec/(domain/model/CliSession.kt, domain/service/CliBridgeRequestDispatcher.kt, api/controller/CliSessionController.kt)