Skip to content

ブラウザー UI

Cornus サーバーが管理するワークロードと Compose プロジェクト用のローカルブラウザー UI です。cornus web で起動します。このガイドは UI 自体が何をするかを説明します。フラグと構文のリファレンスはコマンドページにあります。

仕組み

cornus web は、組み込みの SolidJS アプリケーションとクライアント側のバックエンドフォーフロントエンド (BFF) を起動します。UI では、ワークロードのライフサイクルと詳細、Compose プロジェクトと depends_on グラフ、クライアントローカルマウント、トンネルと転送、要求が通過する両側のイングレス設定、設定ファイル、ストリーミングログ、ファイルブラウザーと対話型 exec ターミナルを並べるワークスペース、そしてサーバー組み込みのオブザーバビリティストアを可視化するメトリクスダッシュボードを確認できます。BFF はクライアント向けにワークロード統計ストリームも公開します。

Compose の構造、ローカルファイルのソース、稼働中のバックグラウンドエージェントセッションは、サーバーの平坦化されたワークロード API には含まれないため、BFF はクライアント上で動作します。他のクライアントコマンドと同じように、選択中の接続プロファイルを使用します。プロジェクトビューでは、コマンドに渡した Compose ファイルを使用します。ファイルが見つからず明示指定もない場合、サーバーのワークロードビューは引き続き利用できますが、プロジェクトビューは空になります。

UI には認証がありません。既定のモードではループバックでのみ待ち受けます。--addr には localhost またはループバック IP リテラルを指定する必要があり、ワイルドカードアドレスや非ループバックアドレスは、--allow-non-loopback を指定しない限り拒否されます。--publish-in-conduit を使うと、リスナーは一切バインドせず、ループバックにある SOCKS5 conduit を通じてのみ到達できます。そのため、どちらの方法でも認証なしの境界は変わりません。

プロジェクトに書かれていないディレクトリを閲覧する

ファイルエクスプローラーのローカルルートは Compose プロジェクトから導出されます。プロジェクトディレクトリと、その外側に解決されるバインドマウント元です。よくある場合はこれで足りますが、それ以外は対象外です。スクラッチディレクトリ、隣のチェックアウト、データドライブは、あなたには普通に見えていてもエクスプローラーからは見えません。そのためだけに不要なバインドマウントを宣言するのは、良い頼み方ではありません。

--local-root はそれらを直接指定します。

sh
cornus web --local-root ~/scratch --local-root notes=~/wiki:ro

値は [LABEL=]DIR[:ro] です。ラベルはソース切り替えに表示される名前で、既定はディレクトリのベース名です。:ro はルートを読み取り専用にし、これは書き込みエンドポイントでの実際の拒否であって、単なる表示ではありません。ディレクトリは存在している必要があります。コマンドの起動時に絶対パスへ解決して確認するので、最初の一覧表示になって初めて失敗することはありません。

宣言したルートにも他のルートと同じ封じ込めが適用されます。パスはルートを基準に解決され、そこから外へ出ることはできません。ファイルシステムのルートとカーネルの擬似ファイルシステムはそもそも拒否されます (どのソースをなぜ拒否したかは切り替え側に表示されます)。

Compose プロジェクトがまったくなくても動作します。compose ファイルのないディレクトリで cornus web --local-root DIR を実行すると、そのディレクトリを対象にしたエクスプローラーが、サーバーのワークロードビューと並んで使えます。ここで指定したルートは切り替え内でバインドマウント元より上位に並ぶため、プロジェクトがない場合は最初の --local-root が既定になります。

--publish-in-conduit と併用した場合、パスはあなたの作業ディレクトリで解決され、絶対パスとしてバックグラウンドエージェントへ送られます。エージェント自身の作業ディレクトリは別の場所で固定されているからです。

ホスト外へのバインド

ブラウザーが cornus web を実行しているマシンにない場合もあります。CLI を踏み台ホストで動かしている、ポートを別のインターフェイスから転送する devcontainer で動かしている、あるいは同じ LAN のタブレットからワークステーションへ到達したい、といった場合です。--allow-non-loopback はそうした用途のために、ワイルドカードまたは非ループバックの --addr を許可します。

sh
cornus web --addr 0.0.0.0:8080 --allow-non-loopback --allow-host box.lan

何を差し出すことになるのかを理解してください。UI とその MCP エンドポイントには認証がなく、接続プロファイルに対する exec、常設ターミナル、ファイル書き込みを公開します。つまり、そのポートへ到達できる人は誰でもそのすべてを得ます。SSH トンネル (ssh -L 8080:127.0.0.1:8080 host) や --publish-in-conduit を優先してください。どちらもリスナーをループバックのみに保ちます。このフラグは、ポートの手前にあるネットワークをすでに信頼している場合に使い、可能であればワイルドカードではなく --addr で対象を明示してください。

--allow-host は、このオリジンが応答する Host ヘッダーの値を指定し、DNS rebinding ガードを有効なまま保ちます。ブラウザーに入力する LAN IP やホスト名を渡してください (複数ある場合はフラグを繰り返します)。それ以外の名前で届いた要求は 421 Misdirected Request で拒否され、受け入れるために必要なフラグを示します。--allow-non-loopback を指定して --allow-host を一つも指定しない場合、そもそも知らされていない名前に対してガードを適用できないため、ガードは完全に無効化され、起動時に無効である旨を警告します。

--allow-non-loopback--allow-host--publish-in-conduit とは併用できません。--publish-in-conduit はローカルリスナーをバインドせず、公開された UI は --publish-name に応答します。

UI とワークロードに共通する一つのブラウザープロキシ設定

SOCKS5 conduit を通じて Cornus サーバーのワークロードへ到達する場合、つまりブラウザーのプロキシを cornus socks5 (または cornus config set-context --conduit-mode socks5) に設定し、*.cornus.internal 名を解決する場合、cornus web UI は別の http://127.0.0.1:<port> にあり、ブラウザー側に別の設定が必要です。--publish-in-conduit はこの分断をなくします。

sh
cornus web --publish-in-conduit

この指定は UI のバックエンドをバックグラウンドエージェントへ渡します。エージェントはプロセス内リスナーでバックエンドを提供し、共有 conduit の cornus.internal (service-host 接尾辞の apex) に公開します。UI はワークロードへ到達するのとまったく同じプロキシを通じ、http://cornus.internal/ で応答します。両方に対してブラウザーのプロキシ設定は一つです。ローカルポートはバインドされないため、新たに公開されるものはありません。UI はプロキシが到達できる場所からだけ到達できます。

ここでワークロードセッションの conduit 設定を繰り返す必要はありません。UI は、その接続についてバックグラウンドエージェントがすでに実行している共有 SOCKS5 conduit へ、その conduit がどの設定で起動されたかによらず参加します。参加できる conduit がない場合にのみ、自身が解決した設定にフォールバックします。「設定は一つ」という約束が実際に成り立つのはこのためです。以前は、わずかに異なる設定を解決した cornus web2 つ目のプロキシを起動し、最初のプロキシと一つのバインドアドレスで競合していました。これは多くの場合、プロファイルが conduit 経由のイングレスを有効にしているのに、このコマンドにはそのためのフラグがないことが原因でした。

公開名は参加した conduit に従います。--socks5-service-host-suffix.demo.internal にしている場合、UI は独自の名前空間ではなくワークロードの隣、http://demo.internal/ で応答します。--publish-name を指定すれば従来どおりそれが優先されます。

コマンドはフォアグラウンドで動作し続け、終了時 (または kill 時) に名前を取り下げます。エージェントが再起動すると、自動的に再公開します。

注意:

  • ブラウザーはプロキシ経由で remote DNS (SOCKS5h) を使う必要があります。cornus.internal がローカルではなくプロキシで解決されるようにするためです。これは既存の *.cornus.internal ワークロード名と同じ要件です。
  • 公開名では http:// だけを提供します (https:// ではありません)。
  • ワークロードセッションも socks5 conduit を使う必要があります。既定のポート転送モードで動作している場合でも、UI と完全なデプロイメント名によるワークロードの解決はできますが、Compose の短い名前 (例: demo-web としてデプロイされたサービスに対する web.cornus.internal) は解決できません。この alias を登録するのは socks5 モードのワークロードセッションだけです。
  • ここでの --conduit は conduit を選ぶものではなく、設定を固定するものです。アドレスや接尾辞を指定する (--conduit socks5://.shared:1080--conduit socks5://?suffix=.demo.internal) と「この設定をそのまま使う」という意味になり、意図的に 2 つ目の独立したプロキシを立てたり、複数ある中から選んだりする方法になります。素の --conduit socks5CORNUS_CONDUIT、プロファイルは設定を指定しないため、フラグなしの場合と同じく参加します。
  • その接続について共有 conduit が複数実行されている場合、UI は最も多く共有されているものへ参加し、その旨を報告します。起動時に表示されるバナー行が、実際に参加したアドレスを示します。

agent クライアント向け MCP エンドポイント

同じサーバーは /.cornus/mcpMCP (Model Context Protocol) サーバーも同居させます。これにより Zed の Agent パネル、Claude Desktop などの agent クライアントは、UI と同じクライアント側機能を操作できます。ワークロードの一覧表示と操作、依存関係グラフとマウントの読み取り、ログの tail、単発コマンドの実行、許可リストにある Compose/env/設定ファイルの読み書きができます。既定で有効です。無効にするには --no-mcp を渡します。

MCP ツールは UI の BFF とまったく同じロジックを使う薄いアダプターなので、二つのインターフェースがずれることはありません。ストリーミングは UI 専用です。対話型ターミナルとライブのログ/統計ストリームは MCP の要求/応答モデルに合わないため、MCP では範囲を制限した logs_tail (直近 N 行) と単発の exec_run (取得した stdout/stderr/終了状態) を提供します。

逆方向の例外が一つあります。project_apply はロードされたプロジェクトを再デプロイし (cornus compose ... up -d 相当なので、標準の Compose 収束処理とバックグラウンドエージェントの動作が正本です) 、これに対応する UI はありません。UI は CLI を置き換えるものではなく寄り添うものなので、再デプロイは既に開いているターミナルで行うべきものです。MCP を操作する agent にはそのターミナルがありません。

agent はサーバーのフライトレコードも利用できます。これは「現在何が真か」ではなく、事後に「何が問題だったか」へ答えるものです。CLI と同じ since/kind/unfinished フィルターを持つ activity_read ツールと、cornus://activity/unfinished リソース、つまりサーバーと caretaker が開始したまま完了しなかった処理の集合を提供します。リソース形式が有用です。クライアントはファイルのように添付できるため、動作不良のデプロイメントについて尋ねられた agent は、直前のサーバーが処理途中で停止したことを最初から把握できます。どちらにもレコードとともに liveInstance が含まれます。これがないと、サービス中プロセス自身の未終了ライフタイムがクラッシュのように見えます。追跡 (cornus activity --follow) はログストリームと同じ理由で CLI 専用です。

MCP は UI の脅威モデルをそのまま継承します。同じループバック/認証なしの境界と、同じ DNS rebinding Host ガードを使います。--allow-non-loopback で境界を広げた場合も同様で、そのときは UI と並んで exec_runfile_write もネットワークへ公開されます。--publish-in-conduit では MCP エンドポイントも UI と同じ SOCKS5 conduit に公開され、UI と同様に conduit の利用者へ file_writeexec_run が公開されます。そこで影響範囲を狭めたい場合は --no-mcp を使ってください。

多くの MCP クライアントは HTTP URL に接続するのではなく、stdio でコマンドを起動します。その場合は cornus web --mcp-stdio を実行してください。同じツール群を stdin/stdout 上で提供し、HTTP リスナーはバインドしません。ブラウザー UI と同じ接続プロファイルと Compose フラグを再利用します。診断は stderr へ送るため、stdout 上の JSON-RPC ストリームを壊しません。たとえばクライアントには次のように登録します。

json
{
  "command": "cornus",
  "args": ["web", "--mcp-stdio", "-f", "compose.yaml"]
}

メトリクスダッシュボード

Metrics 画面は、サーバーの組み込みオブザーバビリティストアが記録した内容をグラフにします。ワークロード側の計装も UI 側の設定も不要ですが、ストアそのものは必要です。サーバーを --obs 付きで起動してください。

sh
cornus serve --obs

ストアがない場合、オブザーバビリティ関連のルートはすべて 501 を返します。画面はそれをエラーとして報告するのではなく、必要なフラグを示して説明します。

ページ見出しの横にある Scope の切り替えで、ダッシュボードの対象を選びます。Workloads (CPU、メモリ、メモリ上限、ネットワーク I/O、ディスク I/O、プロセス数) または Server (cornus プロセス自身の CPU、メモリ、Go ヒープ、goroutine 数、スレッド数、ファイルディスクリプター数、ネットワーク I/O、および累積のビルド数とデプロイ数) です。

1 行のフィルターがそれを絞り込みます。

コントロール効果
Range直近 15 分 / 1 時間 / 6 時間 / 24 時間。ステップと更新間隔は範囲に追随するため、24 時間のウィンドウが 15 秒ごとに読み直されることはありません。
Workloadワークロードのパネルを 1 つのデプロイに絞り込みます。Workloads スコープでのみ表示されます。

各パネルは現在値と、系列ごとの折れ線 (レプリカ別、CPU モード別、I/O 方向別)、および同じ系列を最新値 / 最小 / 最大 / 平均として読む Table 切り替えを備えます。したがって、ホバーしなければ読めない値はありません。グラフにホバーするか、フォーカスして矢印キーを押すと十字線が動き、その時点のすべての系列の値を読み上げます。

累積カウンター (container_cpu_timecontainer_network_iocontainer_disk_ioprocess_cpu_timecornus_server_network_io) はブラウザー側で毎秒あたりのレートに微分され、値の減少は負のトラフィックではなくカウンターのリセットとして扱われます。

そのデプロイバックエンドに取得元がないメトリクスファミリーは、常に空のチャートとして描かれるのではなくダッシュボードから除外されます。Kubernetes ではネットワーク I/O、ディスク I/O、プロセス数、累積 CPU が、それ以外のバックエンドでは瞬間的な CPU が該当します。サーバーは cornus observe status でそれらを示し (metrics.unsupported)、フィルターの下の一行がどのパネルがなぜないのかを説明するので、パネルがないこと自体は説明可能なままです。バックエンドが報告できるのにまだ何も届いていないメトリクスはパネルを保ち、「まだ何も報告していない」と表示されます。これはストア自身の応答と同じ内容です。

1 つのパネルが描画する系列は最大 8 本です。これはパレットで確実に区別できる色数であり、表示しなかった本数はパネル上に明示されます。残りを見るには、1 つのワークロードに絞り込むか、テーブルを読んでください。

スコープは URL に載ります (/metrics?workload=shop-web&range=6h)。そのため特定のビューをリンクとして共有でき、未知の値は画面を空にするのではなく既定値に戻されます。

同じデータをコマンドラインから

このダッシュボードは cornus observe metrics と同じストアに問い合わせます。こちらは任意の PromQL を受け付け、ワークロード自身がエクスポートしたメトリクスにも到達できます。ダッシュボードが扱うのは、Cornus が自動的に記録する範囲です。

見ている場所にそのままグラフを

同じパネルは、それが説明している対象のすぐ隣にも表示されます。「これは今忙しいのか」という日常的な問いのために、ダッシュボードまで移動する必要はありません。

  • Overview の各プロジェクトセクションとワークロードセクションは、2 枚のパネルからなるストリップを持ちます。その見出しの下にあるものすべての CPU とメモリを、直近 1 時間ぶん表示します。プロジェクトのストリップが対象とするのは、そのプロジェクトのデプロイだけです。All metrics → を押すと、同じ対象に絞り込まれた状態でダッシュボードが開きます。
  • ワークロード自身のページには Metrics セクションがあり (ページは Instances、Spec、Metrics、Logs を順に並べます)、そのデプロイだけを対象としたワークロードパネル一式と、専用の範囲コントロールを備えます。

ストリップが表示されるのは、サーバーにストアがあるときだけです。--obs なしの場合、Overview は見出しごとに説明ボックスが増えたりせず、これまでと変わりません。

これらのビューの CPU パネルは、2 つのバックエンド表記 (ホストバックエンドの container_cpu_time と Kubernetes の container_cpu_usage) を 1 つのグラフに統合します。同じ量を同じ単位で表しているからです。フル機能のダッシュボードでは両者を別パネルのまま保ち、空のパネルがどのバックエンドのものかを明示します。

停止済みのデプロイも、それまでの区間のグラフを表示します。ワークロードが「今」どうなっているかはステータスバッジの役割であり、グラフの役割は「何をしていたか」です。

Overview のイングレス設定

Overview には、サマリーカードとプロジェクトごとのセクションの間に Ingress セクションがあります。イングレスホストへの要求は 2 つの独立した設定を通過するため、このセクションはその両方を示します。サーバー側の設定はクライアント側の設定ではなく、どちらか一方からもう一方を推測することはできません。

Front door はサーバーが広告する内容です (GET /.cornus/v1/info)。

意味
Mode実際のイングレスコントローラーがイングレスを実現している場合は cluster。サーバーが自身の Host / パステーブルでワークロードにルーティングする場合は emulated で、これはホストバックエンドの動作です。
Base domainCORNUS_INGRESS_DOMAIN。Compose ブロックがホストを指定していないとき、デプロイに与えられるホストを予測できます。
ClassCORNUS_INGRESS_CLASS。このサーバーが作成するすべての Ingress に付与されます。
Listenemulated なフロントドアがバインドされているアドレス (CORNUS_INGRESS_LISTEN)。未設定の場合、イングレストンネル経由でのみ到達できます。emulated なフロントドアのときだけ表示されます。
Controllernative passthrough がポートフォワードする、クラスター内のコントローラー Service。"none discovered" は、クライアントが自前のイングレスエミュレーションにフォールバックする理由です。

This client は、自分の conduit がイングレスをどう実現しているか (--ingress-conduit の設定) で、バックグラウンドエージェントから読み取られます。

意味
Modenative はクラスターのコントローラーへ直接トンネルし、ルーティングと TLS はコントローラーが行います。emulate は conduit 経由で到達するクライアント側のリバースプロキシを動かします。
Domainイングレスホストを導出する接尾辞。"conduit default" は conduit 自身のサービスホスト接尾辞を意味します。
Controllernative モードでの passthrough 先。
Trustemulate モードでブラウザーが受け入れる必要があるもの。ホストごとの証明書と、フォールバック CA (通常はこのセッション用に conduit が生成したもの) です。ブラウザーの TLS エラーを具体的な対処に変えるのがこの行です。native モードでは何も表示されません。実際のコントローラーが自身の証明書を提示するからです。

フロントドアを広告していないサーバーも、イングレスをルーティングしていないクライアントも、セクションが消えるのではなく、そのことを明示します。設定をまったく読み取れなかったクライアントも同様です。バックグラウンドエージェントが動作していなければ問い合わせる相手がいないため、このセクションは「none」ではなく「unknown」と報告します。

どちらの設定についても、イングレスを参照してください。

ワークスペース

ワークスペースは、2 種類のペインを 1 つに収めたタイル型の画面です。ペインは、ローカルマウントと稼働中コンテナを 1 つの名前空間として横断するファイルブラウザーか、ワークロード上の対話型ターミナルのいずれかです。タイルの分割、タブとしての重ね合わせ、並べ替えは、中身が何であっても同じように行えます。レイアウトは再読み込みしても保持されます。

開いた直後は、マウント一覧を表示するファイルブラウザーが 1 つだけです。稼働中のワークロードの中にいるときは、ターミナルで開く (prefix t) が、いま表示しているディレクトリでシェルを開きます。画面に出ているフォルダーであって、その中で選択している行ではありません。ペインの配置は、他の新規ペインと同じくタイルを指し示して決めます。ターミナルは行に対して何かをするものではなく立つ場所なので、このコマンドだけは 開く新規ペイン がどちらも読み取る選択を無視します。このコマンドは常に一覧に並び、実行できないときはその理由を示します。マウント一覧ではワークロードがまだ定まっておらず、ローカルフォルダーには接続先のコンテナがなく、停止中のワークロードはその名前を挙げて理由とします。

開くは、選択した行を専用のペインに表示します。テキストファイルならエディター、画像ならビューアー、フォルダーならもう 1 つの一覧です。この 3 つはすべて 1 つのコマンドです。パレットは開く対象の行を示し、その行がフォルダーのときは末尾にスラッシュを付けます (Open "logs/"…)。プレフィックスなしの Ctrl+Enter (Mac では Cmd+Enter) で実行でき、ファイルの場合は行での Enter、ダブルクリック、ファイル名のクリックでも実行できます。

どの経路でも、ペインをどこに置くかをタイル上の配置ターゲットを光らせて尋ねます。Space でいま操作しているタイルのタブとして、矢印キー (または hjkl) でその隣に分割して配置し、Esc で取りやめます。フォルダーでの素の Enter は、これまでどおりその場で中に入ります。修飾キーが「ここではなく、これから指し示す場所に」を表します。開くはマウントの中では常に一覧に並び、実行できないときはその理由を示します。何も選択していない、複数行を選択している、エディターにもビューアーにも表示できないファイルである、のいずれかです。

いつも同じ答えを返しているなら、一度だけそう伝えておけます。設定 → ワークスペース → 新しいペインの配置で、配置先を尋ねる (既定)、常に左右に並べる常にタブとして開く のいずれかを選べます。後ろの 2 つは、いま挙げた答えのどちらかを固定するものです。ペインを作るコマンドはプロンプトを省いて直ちに配置します。どちらを選んでも到達できる配置が増えたり減ったりすることはありません。この設定はプロンプト自身が提示する答えのどれを採るかを決めるだけです。ペインを分割はこの設定の対象外です。作る配置はコマンド名がすでに述べており、尋ねるのはどの辺かだけだからです。

ワークスペースは画面より大きい

ペインの配置が決めるのは「どこに置くか」です。「何を犠牲にするか」はそれとは別の問いで、答えは「渡せる場所がなくなった時点で、もう何も犠牲にしない」です。

まだ余裕があるうちは、分割はごく普通の分割です。ペインは半分になり、ワークスペースは画面に収まったままです。半分にすると幅が 40rem を、あるいは高さが 20rem を下回る場合 — 一覧やターミナルが読むに値しなくなるおおよその境目です — には、分割は場所を奪うのをやめ、場所を作りはじめます。分割は場所を奪うのをやめて場所を作りはじめ、画面はいまや画面より広い (あるいは高い) ワークスペースを覗く窓になります。

そこで起きることは、3 段階からなる 1 つの規則です。まず分割した軸に沿ってワークスペースが黄金比倍されます。次に、すでに開いているものすべてがその3 分の 2 を分け合い、それまでの比率をそのまま保ちます。そして新しいペインが残りの 3 分の 1 を受け取ります。したがってペイン同士の関係は変わらず、すべてが同じわずかな倍率で広がって場所を空けます。新しいペインの大きさは、たまたま分割したペインではなくワークスペースが決めます。その 3 分の 1 が 40rem の下限を下回る場合は、新しいペインは下限の大きさになります。広がった辺に面しているペインだけがそれに合わせて伸び、それ以外はすべて元の位置と大きさのままです。

ペインを移動も同じ基準で測られます。基準になるのは移動先の隣になるタイルです。余裕のあるペインの横に落とせばその場所を分け合うだけで、半分にすると下限を下回る場合にだけ、ワークスペースが広がって場所を作ります。

2 つの下限が異なるのは、ペインも画面も正方形ではないからです。40rem は列がそろった一覧、あるいは 80 桁のターミナルにあたり、20rem はターミナルのおよそ 18 行にあたります。両方の軸に同じ値を求めれば、普通のディスプレイが到底与えられないほどの高さを要求することになります。

つまりワークスペースは、余地を使い切るまでは普通のタイル型ウィンドウマネージャーと同じように振る舞い、使い切ってはじめてスクロールしはじめます。2560px のディスプレイなら最初の分割はどれも半分ずつになります。1080p なら左右分割は半分ずつ、上下分割も 1 回目は半分ずつで、2 回目から広がります。1280px のノート PC なら左右分割は最初から広がります。その半分がもとより幅の下限を下回っているからです。

そのためワークスペースはスクロールし、しかもあなたに追従します。ペインにフォーカスを移すと、そのタイルが完全に見えるだけの最小限のスクロールで視界に入ります。左側に開いたペインも、レイアウト全体が飛び跳ねて見えることなく画面に現れます。ペインを選ぶ (prefix s) では視界も一緒に歩きます。矢印キーでタイルからタイルへ移るたび、強調されているタイルが見えるようにワークスペースがパンし、Enter を押すまでフォーカスはもとの場所に留まります。Esc で抜ければ視界は歩きはじめた位置にそのまま戻るので、見回すことには何の代償もありません。

Tab はこの歩きのもう 1 つの経路です。矢印キーがタイルからタイルへ進むのに対して、Tab はペインからペインへ進みます。すべてのペインを、リストに並ぶ順、すなわち番号が数える順にたどり、末尾で先頭へ回り込みます。Shift+Tab なら逆向きです。したがってタイルが重ねて持つ タブ もそのまま通り抜けます。これはどの方向キーにもできない移動です。重なったタブは画面上の同じ場所を共有しているので、両者を区別できる矢印は存在しないからです。何も調べずに Tab を好きなだけ押してもよいですし、番号がすでに分かっているならその数字キーを押してもかまいません。

設定 → ワークスペース → ペインチューザーのミニマップ を有効にすると、チューザーはリストの上にワークスペース全体を描きます。ペインごとに 1 つの矩形からなる図で、形も比率も実際のワークスペースのままです。歩いている矩形は強調表示され、フォーカスを持つペインは塗りつぶされた番号を身につけ、アクセント色の枠がワークスペースのどれだけが画面に映っているか、そしてどこなのかを示します。画面数個分の幅を持つワークスペースでは、それを伝える場所はこの枠だけです。矩形をクリックすればそのペインへ移動します。行をクリックするのと同じです。

タブを複数持つタイルには、そのタブの数だけ番号が付きます。どれも画面上の同じ場所を共有しているからです。そして番号は 1 つずつが独立したクリック対象です。背面のタブを指し示して選べる方法はこれだけです。番号は矩形のなかで折り返すので、背の高いタイルは 1 行とお詫びではなく何行もの番号を収めます。行も尽きたときにはじめて残りが省略記号に置き換わるので、セルがタイルの持つタブの数を実際より少なく見せることはありません。残る番号はそのタイルが今表示しているタブの周辺のものなので、Tab でペインを歩いても、動く番号はつねに目に見えています。

既定では無効です。これが役に立つのはワークスペースがディスプレイより大きくなってからで、画面に収まっているレイアウトなら、タイルはすでに目の前にあり、その絵は見えているものの絵でしかないからです。有効にすると、マップはタイルが 2 つ以上あるときに現れ、枠は画面の外に何かがあるときにだけ現れます。

ペインチューザーをピン留めすると、それはモードであることをやめます。パネルの右上隅にあるピン — 押すまでは薄く表示されています — は、チューザーを画面の脇のサイドバーに常設します。そこでは、頼まれたかどうかにかかわらずすべてのペインが並び、いま自分がいるペインに印が付き、行をクリックすればそのペインへ移動します。何も覆いません。ワークスペースはサイドバーの下をくぐるのではなく、その幅を明け渡すので、タイルは残った領域に並べ直されます。prefix s はこれまでとまったく同じようにタイルを歩きます。歩みはすでにそこにあるパネルに報告され、その間だけタイトルと強調表示を借り、Enter か Esc で歩みが終わってもパネルは残ります。

チューザーは読む向きの先頭側に出ます。左から右に読む言語なら左、右から左に読む言語なら右で、ピン留めしていてもいなくても同じです。そのためピン留めは、パネルを画面の反対側へ移すのではなく、外側へずらす操作になります。設定 → ワークスペース → サイドバーの位置 はサイドバーについてだけこれを上書きします。自動 は言語に従い、 は文字どおりです。

コンテナ内での転送がどう行われるかは、デプロイバックエンドによって決まります。 ホストバックエンド (Docker、containerd、ベアホスト) では、稼働中コンテナ内のあらゆるパスを直接読み書きします。kubernetes では経路が 2 つあり、エクスプローラーはその間で使い分けます。

  • ワークロードが宣言したボリューム内のパスは、その caretaker sidecar を経由します。caretaker に与えられるのはそれらのボリュームだけです。これが優先される経路です。アプリケーションイメージには何も要求せず、実際の errno を報告し、1 つのボリューム内の 2 つのパス間のコピーは Pod の外に出ません。
  • それ以外のパス、つまりコンテナイメージの中にあるものは、コンテナ内で実行する tar を経由します。これは kubectl cp が使うのと同じ仕組みです。caretaker が共有していないマウント名前空間へ到達する方法はこれしかありません。

知っておく価値のある帰結として、tar の経路にはアプリケーションイメージ内に tar が必要です。distroless イメージにはそれがないため、そこではイメージ層のパスを閲覧はできても (一覧表示は exec であり、これは常に動作します) 転送はできず、拒否時にその旨が示されます。ボリューム上のパスはそうしたイメージでも引き続き動作します。その経路はイメージに一切触れないからです。caretaker がまだ接続していない Pod も似た拒否を返しますが、理由は異なります。メッセージは両者を区別し、後者は Pod が起動すれば自然に解消します。

コピーと移動はサイドバーを使いません。 prefix s はチューザー自身の問いなので常設の場所がふさわしいのですが、ほかのペインにコピーほかのペインに移動 は答えを求める問いです。ですからこれらは画面の反対側に専用のカードを開き、サイドバーはそのままにしておきます。カードは行き先の一覧だけを持ちます。ミニマップも、フォーカスの位置を示す印も、稼働状況のステータスバッジもありません。転送先は名前と種類、そしてどの行が灰色になっているかで選ぶものであり、転送はフォーカスを動かさないからです。workingneeds you の状態にあるペインは、これまでどおりタブの上でそれを伝えます。タブはそのためにあるからです。しかしファイルの送り先を並べた一覧では、そこへ送ることへの警告のように読めてしまいます。ピン留めしていないときの見た目はこれまでどおりです。

ピンが現れるのは、サイドバーを置く余裕がある場合だけです。幅が 960px 以上のウィンドウで、指ではなくマウスで操作されていることが条件です。スマートフォンやタブレットでは設定がどうであれチューザーは浮かんだままなので、机の上から同期されてきた設定のせいで小さな画面が 1 列を失うことはありません。

自分で視界を動かすには、トラックパッドかスクロールバーを使います。タッチ画面では 2 本指でドラッグします。1 本指はその下にあるものに属しているからです。一覧はスクロールし、ターミナルもスクロールし、タブバーは横に滑り、仕切りはサイズを変えます。2 本指はほかのどれもが欲しがらないジェスチャーなので、ターミナルの真ん中からでも、どこからでもワークスペースをパンできます。設定 → ワークスペース → ペインのズーム が有効なら、ピンチによるズームもそのまま使えます。指の間隔を保ったまま動かせばパン、広げればズームです。

隣のペインとの間で大きさを変えるコマンドが 2 組あり、割り当ては tmux と同じです。prefix Alt+←/→幅を狭く/広くprefix Alt+↑/↓高さを低く/高くします。マウスなら仕切りを Alt を押しながらドラッグします。通常のドラッグは仕切りの両側のペインで場所をやりとりし、Alt を押しながらのドラッグは片方だけを変え、その差分はワークスペースが引き受けます。

配置が偏ってしまったとき — 片側だけ 3 段深く分割され、もう片側には何もない、といった状態 — には、Even horizontal (prefix H) がすべてのペインを等幅の 1 行に並べ直します。ペインもタブも実行中のシェルもそのままで、変わるのはその周りの並びだけです。画面を均等に割った幅が 40rem の下限を下回る場合は、行はその下限で組まれ、代わりにワークスペースが広がります。ですから「均等」が「8 枚のペインが画面の 8 分の 1 ずつ」を意味することはありません。

ワークスペースの右辺と下辺そのものも仕切りです。ほかの仕切りは 2 つのペインの間にあって場所をやりとりしますが、この 2 つは向こう側に何もないため、ドラッグするとワークスペース自体の大きさが変わります。大きくなるのはその辺に接しているペインだけで、分割によってワークスペースが広がるときとまったく同じ規則です。2 列内側のペインは動きません。これらは画面の縁ではなくワークスペースの縁にあるので、いちど表示領域の外まで引き出したら、引き戻すにはそこまでスクロールして戻る必要があります。

設定 → ワークスペース → 新しいペインの大きさでこの挙動を切り替えられます。ペインを分割する は従来の tmux の挙動です。タイリングは常に画面に収まり、新しいペインを作るたびに、どれだけ小さくなろうと、いたペインが半分になり、スクロールは決して起きません。既定は ワークスペースを広げる です。

作業ディレクトリは保証ではなく希望です

これは exec の作業ディレクトリとして送られ、docker、containerd、ベアホスト、Incus の各バックエンドはこれを尊重します。Kubernetes は作業ディレクトリを表現できません (PodExecOptions にそのフィールドがありません)。そのため Kubernetes 上のワークロードで開いたターミナルは、イメージが定める場所から始まります。

ターミナルのシェル探索

ワークロードでターミナルを開くとき、シェルは推測されるのではなく発見されます。BFF は実行中のコンテナ内でプローブを走らせ、そのイメージが実際に持っている最良の対話シェルに接続します。したがって bash を含むイメージでは bash が、busybox しかないイメージでもシェルが得られます。

候補は次の順に試され、最初に見つかったものが採用されます。

  1. ワークロード自身の entrypoint: または command: が指すシェル (それがシェルである場合)。イメージ作成者が選んだものであり、存在の裏付けが既にある唯一の候補です。
  2. ワークロードの x-cornus-shells: リスト (Compose の拡張を参照)。
  3. 選択中の接続プロファイルshells: リスト。
  4. ブラウザー自身のリスト (設定 -> ターミナル -> シェル候補)。

リストは置き換えではなく連結されます。より具体的な指定元は自分のエントリーを前方へ押し上げるだけで、フォールバックを取り除きません。各エントリーは分割済みの引数リストではなくコマンド文字列です。/bin/busybox sh は 1 エントリーであり、Compose が command: を分割するのと同じ方法で分割されます。

ブラウザーの既定リストは順に /bin/zsh/usr/bin/zsh/bin/bash/usr/bin/bash/bin/dash/usr/bin/dash/bin/ash/usr/bin/ash/bin/sh/usr/bin/sh/busybox/sh/bin/busybox sh/usr/bin/busybox sh です。

候補が 1 つも存在しない場合 (distroless や scratch のイメージ) は、汎用の接続エラーで失敗する代わりに、ペインがその旨を伝えて実行するコマンドを尋ねます。ペインは落ち着いたシェルを記憶するので、開き直したり再読み込みしたりしても再びプローブすることはありません。

プローブはイメージが持っていない候補 1 つにつき exec の往復 1 回ぶんのコストがかかり、最初に起動したものでとまります。起動したシェルがすべての候補について一度に報告するからです。結果はワークロードごとに 30 秒間キャッシュされます。

プロファイルの shells: フィールドは、ワークロード内で実行されるバイナリを指名するため、セキュリティ上の機微なフィールドとして扱われます。プロジェクトごとの cornus-context.yaml がこれを供給できるのは --trust-context-file を付けたときだけで、自動検出されたファイルからは取り除かれます。

ファイル編集

エディターが扱えるのは、解決済みの Compose ファイル、env ファイル、クライアント設定ファイルだけです。任意のパスやパストラバーサル表現は拒否されます。

Compose ファイルを編集しても再デプロイは行われません。変更を反映したくなったら自分で cornus compose up -d を実行してください。UI に適用ボタンはありません。UI は CLI に寄り添うものであって、CLI への二つ目の入口ではないからです。(agent クライアントはこの操作を project_apply MCP ツールとして利用できます。)

関連項目: cornus webcornus composeネットワークと conduitオブザーバビリティ接続設定リファレンス

Released under the Apache-2.0 License.