Handbooks
ガイド

Studio — Web UI

ツールチェーン全体をブラウザのタブ 1 つで。ライブログとワンクリックのロールバック付き。設計上、localhost 専用です。

handbook studio                 # → http://127.0.0.1:4860
handbook studio --port 5000     # or: pnpm studio --port 5000

CLI と同じコードパス、同じ設定解決、ディスク上の同じ成果物 — 操作方法が違うだけです。

ビルドステップはゼロです。 UI は、CSS をインライン化した手書きの HTML ファイル 1 枚と 素の JS でできています。バンドラーもフレームワークもなく、CDN から取得するものもありません。 瞬時にロードされ、ネットワークケーブルを抜いても動作します。

できること

領域何をするか
リポジトリソースツリー + 作業ディレクトリを URL セーフな名前で登録する
生成フルパラメータセット、SSE でライブ配信されるログ、実行途中でのキャンセル
ハンドブックブラウザレンダリング済みハンドブックをその場で読む
影響グラフあるステージがどのファイルを所有し、何が呼び込んできて、何を呼び出すか
ソースビューア任意のカードの背後にある実ファイルを、引用された行で開く
プランリクエストを入力し、読み取り専用エージェントの作業を眺め、プランを読む
適用 / ロールバックドライラン、適用、すべてのバックアップの一覧、ワンクリックのロールバック
再同期生きているツリーに対してハンドブックを前へ進める — ケースディレクトリの組み立ては不要
履歴リポジトリごとの変遷: 各実行が何を、いつ変えたか

ジョブ

生成、プランニング、再同期は、Server-Sent Events で配信されるログをキャプチャした バックグラウンドジョブ として実行されます。

  • 1 リポジトリにつき同時に 1 ジョブ。 パイプラインの成果物は、同じ作業ディレクトリへの 並行書き込みに対して安全ではありません。2 つ目の開始は明確なメッセージ付きで拒否されます。
  • キャンセル可能。 すべてのジョブは AbortController を持ち、そのシグナルは実行中の LLM リクエストにまで届きます。キャンセルとはキャンセルのことであり、「ログの表示をやめる」 ことではありません。
  • ステータス: runningsucceeded | failed | cancelled。完全なログが保持される ため、終了後に何が起きたかを読むことができます。

設定

Studio は 他のすべてのコマンドと同じレイヤー から設定を解決します — フラグ、環境、 .env カスケード、handbook.config.yaml、デフォルト:

handbook studio --model gpt-4o --base-url https://my-proxy/v1 --port 5000
handbook --env prod studio

UI から開始された生成ジョブは、CLI が見るのと同じ設定ファイルレイヤーを見ます。そのため detailnarrateLangreadWorkers などはすべて YAML から機能します。

セキュリティモデル

Studio は ローカルツール です。外部公開向けに堅牢化されておらず、そのふりもしません。

  • デフォルトで 127.0.0.1 にバインドします。
  • CSRF ガードはソケットではなく Host リクエストヘッダーをチェックします。 ループ バックのホスト名だけが通過します。
  • POSTapplication/json を要求します。 これは古典的なクロスオリジン HTML フォーム攻撃をブロックします。
  • リポジトリ名はファイルシステムに触れる前に ^[A-Za-z0-9][A-Za-z0-9._-]*$ で検証され、 パスは realpath で正規化されます。
  • ソースとハンドブックのファイル配信は、登録されたルートにサンドボックス化されています。

コンテナ内で

pnpm run docker:studio    # docker compose up --build studio

公開されたポートに到達できるようにするには、コンテナは 0.0.0.0 にバインドしなければ なりません(docker-compose.ymlHANDBOOK_STUDIO_HOST=0.0.0.0)。

動作するのは http://localhost:4860 だけです

LAN の IP でもコンテナ名でもありません。ホストからブラウズすれば依然として Host: localhost:4860 が 送られて通過します。LAN の IP やコンテナのホスト名を指名するリクエストは、設計どおり 403 で 拒否されます。リモートアクセスは、意図的に未実装のままにされた別個の機能です — 明示的な許可リストが 必要になるでしょう — この防御の欠陥ではありません。

状態

~/.handbook-studio/
  studio.json        the repository registry (schema-validated on read)
  work/<name>/       auto-created work dirs for repos that did not bring their own

--state-dir で移動できます。それ以外のすべて — ハンドブックの成果物、変遷の履歴 — は 各リポジトリ自身の作業ディレクトリにあるので、状態ディレクトリを削除して失われるのは レジストリだけで、重要なものは何も失われません。

スクリプトから叩く

UI は単なるクライアントです。HTTP API はスクリプトに使えるほど安定しています:

curl -s http://localhost:4860/api/repos | jq

curl -s -X POST http://localhost:4860/api/repos \
  -H 'content-type: application/json' \
  -d '{"name":"api","sourceRoot":"/Users/me/code/api","workDir":"/Users/me/work/api"}'

curl -s -X POST http://localhost:4860/api/repos/api \
  -H 'content-type: application/json' \
  -d '{"action":"analyze"}'

curl -N http://localhost:4860/api/jobs/<job-id>    # SSE log stream

完全なルート一覧はパッケージの READMEに あります。

このページの内容