Control UI(ブラウザ)

Control UI は Gateway が配信する小さな Vite + Lit シングルページアプリケーションです。

  • デフォルト: http://<host>:18789/
  • プレフィックスの変更: gateway.controlUi.basePath を設定(例: /openclaw

Gateway WebSocket と同じポートで直接通信します。

ローカルでのアクセス

Gateway が同じコンピューターで動作している場合:

ページが読み込めない場合は、まず Gateway を起動してください: openclaw gateway

認証は WebSocket ハンドシェイク時に以下で提供されます:

  • connect.params.auth.token
  • connect.params.auth.password ダッシュボードの設定パネルは、現在のブラウザタブセッションと選択された Gateway URL 用にトークンを保持します。パスワードは永続化されません。 オンボーディングウィザードはデフォルトで Gateway トークンを生成するため、初回接続時にここに貼り付けてください。

デバイスペアリング(初回接続)

新しいブラウザやデバイスから Control UI に接続する場合、gateway.auth.allowTailscale: true で同じ Tailnet 上にいる場合でも、Gateway はワンタイムペアリング承認を要求します。これは不正アクセスを防ぐためのセキュリティ対策です。

表示される内容: 「disconnected (1008): pairing required」

デバイスを承認する方法:

# 保留中のリクエストを一覧表示
openclaw devices list

# リクエスト ID で承認
openclaw devices approve <requestId>

承認されると、そのデバイスは記憶され、openclaw devices revoke --device <id> --role <role> で取り消さない限り再承認は不要です。デバイス CLI でトークンのローテーションと取り消しについて参照してください。

補足:

  • ローカル接続(127.0.0.1)は自動承認されます。
  • リモート接続(LAN、Tailnet など)は明示的な承認が必要です。
  • ブラウザプロファイルごとに一意のデバイス ID が生成されるため、ブラウザの切り替えやブラウザデータのクリアは再ペアリングが必要です。

言語サポート

Control UI は初回ロード時にブラウザのロケールに基づいて自動的にローカライズでき、Access カードの言語ピッカーで後から変更することもできます。

  • 対応ロケール: enzh-CNzh-TWpt-BRdees
  • 英語以外の翻訳はブラウザで遅延ロードされます。
  • 選択したロケールはブラウザストレージに保存され、以降のアクセスで再利用されます。
  • 翻訳キーが不足している場合は英語にフォールバックします。

現在の機能

  • Gateway WS 経由でモデルとチャット(chat.historychat.sendchat.abortchat.inject
  • ツールコール + ライブツール出力カードのチャットストリーミング(エージェントイベント)
  • チャンネル: WhatsApp/Telegram/Discord/Slack + プラグインチャンネル(Mattermost 等)のステータス + QR ログイン + チャンネルごとの設定(channels.statusweb.login.*config.patch
  • インスタンス: プレゼンスリスト + リフレッシュ(system-presence
  • セッション: リスト + セッションごとの thinking/fast/verbose/reasoning オーバーライド(sessions.listsessions.patch
  • Cron ジョブ: リスト/追加/編集/実行/有効化/無効化 + 実行履歴(cron.*
  • スキル: ステータス、有効化/無効化、インストール、API キー更新(skills.*
  • ノード: リスト + ケーパビリティ(node.list
  • Exec 承認: Gateway またはノードの許可リスト + exec host=gateway/node の ask ポリシーの編集(exec.approvals.*
  • 設定: ~/.openclaw/openclaw.json の表示/編集(config.getconfig.set
  • 設定: バリデーション付きの適用 + 再起動(config.apply)と最後のアクティブセッションのウェイク
  • 設定の書き込みには base-hash ガードが含まれ、同時編集の上書きを防止
  • 設定のスキーマ + フォームレンダリング(config.schema、プラグイン + チャンネルスキーマを含む)。Raw JSON エディターも利用可能
  • デバッグ: status/health/models のスナップショット + イベントログ + 手動 RPC 呼び出し(statushealthmodels.list
  • ログ: フィルター/エクスポート付きの Gateway ファイルログのライブテール(logs.tail
  • アップデート: パッケージ/git アップデートの実行 + 再起動(update.run)と再起動レポート

Cron ジョブパネルの補足:

  • 分離ジョブの場合、配信はデフォルトでサマリーのアナウンスです。内部のみの実行にしたい場合は none に切り替えられます。
  • announce を選択するとチャンネル/ターゲットフィールドが表示されます。
  • Webhook モードは delivery.mode = "webhook"delivery.to に有効な HTTP(S) Webhook URL を設定して使用します。
  • メインセッションジョブの場合、webhook と none の配信モードが利用可能です。
  • 高度な編集コントロールには、実行後削除、エージェントオーバーライドのクリア、cron の exact/stagger オプション、 エージェントのモデル/thinking オーバーライド、ベストエフォート配信トグルがあります。
  • フォームのバリデーションはフィールドレベルのインラインエラー付き。無効な値は修正されるまで保存ボタンを無効にします。
  • cron.webhookToken を設定すると専用のベアラートークンが送信されます。省略した場合、Webhook は認証ヘッダーなしで送信されます。
  • 非推奨フォールバック: notify: true で保存されたレガシージョブは移行まで cron.webhook を引き続き使用できます。

チャット動作

  • chat.sendノンブロッキング: { runId, status: "started" } で即座に確認応答し、レスポンスは chat イベント経由でストリーミング。
  • 同じ idempotencyKey で再送信すると、実行中は { status: "in_flight" }、完了後は { status: "ok" } を返します。
  • chat.history のレスポンスは UI の安全性のためサイズが制限されています。トランスクリプトエントリが大きすぎる場合、Gateway はテキストフィールドの切り詰め、重いメタデータブロックの省略、サイズ超過メッセージのプレースホルダー置換([chat.history omitted: message too large])を行うことがあります。
  • chat.inject はセッションのトランスクリプトにアシスタントノートを追加し、UI 更新のみの chat イベントをブロードキャスト(エージェント実行なし、チャンネル配信なし)。
  • 停止:
    • Stop をクリック(chat.abort を呼び出し)
    • /stop を入力(または単独の中止フレーズ: stopstop actionstop runstop openclawplease stop)してアウトオブバンドで中止
    • chat.abort{ sessionKey } をサポート(runId なし)してそのセッションの全アクティブ実行を中止
  • 中止時の部分保持:
    • 実行が中止された場合、部分的なアシスタントテキストは UI に表示可能
    • バッファリングされた出力がある場合、Gateway は中止された部分的なアシスタントテキストをトランスクリプト履歴に永続化
    • 永続化されたエントリには中止メタデータが含まれ、トランスクリプト利用者は中止による部分出力と通常の完了出力を区別可能

Tailnet アクセス(推奨)

統合 Tailscale Serve(推奨)

Gateway をループバックのままにし、Tailscale Serve で HTTPS プロキシします。

openclaw gateway --tailscale serve

アクセス:

  • https://<magicdns>/(または設定した gateway.controlUi.basePath

デフォルトでは、gateway.auth.allowTailscaletrue の場合、Control UI/WebSocket Serve リクエストは Tailscale ID ヘッダー(tailscale-user-login)で認証できます。OpenClaw は x-forwarded-for アドレスを tailscale whois で解決し、ヘッダーと照合して ID を検証します。リクエストが Tailscale の x-forwarded-* ヘッダー付きでループバックに到達した場合のみ受け入れます。Serve トラフィックでもトークン/パスワードを要求する場合は gateway.auth.allowTailscale: false(または gateway.auth.mode: "password" を強制)に設定してください。 トークンなしの Serve 認証は Gateway ホストが信頼されていることを前提とします。信頼できないローカルコードがそのホストで実行される可能性がある場合は、トークン/パスワード認証を要求してください。

Tailnet バインド + トークン

openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"

アクセス:

  • http://<tailscale-ip>:18789/(または設定した gateway.controlUi.basePath

UI 設定にトークンを貼り付けてください(connect.params.auth.token として送信されます)。

非セキュア HTTP

ダッシュボードをプレーン HTTP(http://<lan-ip>http://<tailscale-ip>)で開いた場合、 ブラウザは非セキュアコンテキストで動作し、WebCrypto がブロックされます。デフォルトでは、 OpenClaw はデバイス ID のない Control UI 接続をブロックします。

推奨対処: HTTPS(Tailscale Serve)を使用するか、ローカルで UI を開きます。

  • https://<magicdns>/(Serve)
  • http://127.0.0.1:18789/(Gateway ホスト上)

非セキュア認証トグルの動作:

{
  gateway: {
    controlUi: { allowInsecureAuth: true },
    bind: "tailnet",
    auth: { mode: "token", token: "replace-me" },
  },
}

allowInsecureAuth はローカル互換性トグルです:

  • 非セキュア HTTP コンテキストで localhost の Control UI セッションがデバイス ID なしで続行することを許可します。
  • ペアリングチェックはバイパスしません。
  • リモート(非 localhost)のデバイス ID 要件は緩和しません。

緊急用のみ:

{
  gateway: {
    controlUi: { dangerouslyDisableDeviceAuth: true },
    bind: "tailnet",
    auth: { mode: "token", token: "replace-me" },
  },
}

dangerouslyDisableDeviceAuth は Control UI のデバイス ID チェックを無効にします。これは重大なセキュリティの低下です。緊急使用後は速やかに元に戻してください。

Tailscale で HTTPS セットアップのガイダンスを参照してください。

UI のビルド

Gateway は dist/control-ui から静的ファイルを配信します。以下でビルドします。

pnpm ui:build # 初回実行時に UI の依存関係を自動インストール

絶対ベースパスの指定(固定アセット URL が必要な場合):

OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build

ローカル開発(別の開発サーバー):

pnpm ui:dev # 初回実行時に UI の依存関係を自動インストール

その後、UI を Gateway WS URL(例: ws://127.0.0.1:18789)に向けてください。

デバッグ/テスト: 開発サーバー + リモート Gateway

Control UI は静的ファイルです。WebSocket のターゲットは設定可能で、HTTP オリジンとは異なるものにできます。Vite 開発サーバーをローカルで実行し、Gateway は別の場所で動作させたい場合に便利です。

  1. UI 開発サーバーを起動: pnpm ui:dev
  2. 以下のような URL を開きます:
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789

オプションのワンタイム認証(必要な場合):

http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>

補足:

  • gatewayUrl はロード後に localStorage に保存され、URL から削除されます。
  • token は URL フラグメントからインポートされ、現在のブラウザタブセッションと選択された Gateway URL 用に sessionStorage に保存され、URL から除去されます。localStorage には保存されません。
  • password はメモリ内のみで保持されます。
  • gatewayUrl が設定されている場合、UI は設定や環境変数の認証情報にフォールバックしません。 token(または password)を明示的に提供してください。明示的な認証情報がない場合はエラーになります。
  • Gateway が TLS の後ろにある場合(Tailscale Serve、HTTPS プロキシなど)は wss:// を使用してください。
  • gatewayUrl はクリックジャッキングを防ぐため、トップレベルウィンドウでのみ受け入れられます(埋め込み不可)。
  • 非ループバックの Control UI デプロイメントでは gateway.controlUi.allowedOrigins を明示的に設定する必要があります(完全なオリジン)。リモート開発環境も同様です。
  • gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true は Host ヘッダーオリジンフォールバックモードを有効にしますが、危険なセキュリティモードです。

例:

{
  gateway: {
    controlUi: {
      allowedOrigins: ["http://localhost:5173"],
    },
  },
}

リモートアクセスのセットアップ詳細: リモートアクセス