This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/web
naps62-yoloandClaude Opus 4.8 2999e888a8 refactor(maestro): multi-mount ConnectionPool; route web through layout tree
Rework the pool from single-active to a mounted-set model: several connections
can be visible at once (one per leaf), sessions no longer shown are parked
(still streaming) and bounded by an LRU buffer that never evicts visible panes.
Keep activate/parkActive/active() as compat shims and an onFocusChange/
onRequestClose surface; the HUD keeps working via active() -> focused().

main.ts now derives the single-pane view from a one-leaf layout tree via
setVisible/setFocus instead of calling activate directly — no behaviour change,
but the multi-mount path is now exercised end to end.

Refs #29 (epic #37).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:19:09 +00:00
..

maestro-web

Browser UI for Maestro. Connects to the registry HTTP/WS API for the catalog and to individual daemons (via direct WebSocket) for terminal I/O.

Framework choice: vanilla TypeScript

No frontend framework. The UI is small enough that the cost of pulling in Preact / Solid / Leptos doesn't pay back. xterm.js does all the heavy rendering; everything else is a session tree and a spawn form, both trivial in plain DOM.

This decision is non-architectural — swap in a framework later without touching the registry or daemon if needed.

Layout

src/
  main.ts        # entry point, hash-route dispatch
  api.ts         # registry HTTP API client
  events.ts      # `/api/events` WebSocket subscriber
  catalog.ts     # session tree view (groups by metadata.label)
  attach.ts      # xterm.js + daemon WS attach view
  spawn.ts       # spawn-session modal
  theme.ts       # dark/light theme toggle + persistence
  types.ts       # mirror of `maestro-protocol` JSON shapes
  styles.css     # design-system tokens + component styles
  mock.ts        # DEV-only review fixture (see Design)

Design

The visual system (OKLCH token palette, monospace-first typography, dark+light theming, motion, components) is documented in ../DESIGN.md; the tokens live in the :root block of src/styles.css. Strategic intent (register, brand, principles) is in ../PRODUCT.md. Theme follows the OS by default and can be pinned via the header toggle (persisted in localStorage).

mock.ts is a DEV-only fixture (stripped from production builds): visit the dev server with ?mock to seed a representative catalog without a running registry, ?mock&spawn to open the spawn modal, and ?theme=light|dark to pin a theme.

Routing is hash-based:

  • #/ → catalog
  • #/attach/<session-id> → terminal

This keeps the registry's static handler dumb (no SPA fallback needed). Concurrent attaches: open the same #/attach/<id> URL in another tab.

Dev

pnpm install
pnpm dev      # http://localhost:5173, proxies /api → http://127.0.0.1:8080
pnpm build    # → dist/, embedded into the registry binary at cargo build time

The Vite dev server proxies /api and the events WebSocket to a maestro-registry. Default is http://127.0.0.1:8080; point it elsewhere by exporting MAESTRO_REGISTRY before pnpm dev:

MAESTRO_REGISTRY=https://maestro-registry.example.com pnpm dev
# Daemon-facing URL also works — `wss://...` is rewritten to `https://...`
# and a trailing `/daemon` is stripped.
MAESTRO_REGISTRY=wss://maestro-registry.example.com/daemon pnpm dev

Direct daemon WS connections (for attach) bypass the proxy and use the URL returned by GET /api/sessions/:id/connect-info.

Production

pnpm build writes the bundle to web/dist/. The Rust registry crate embeds that directory via rust-embed at compile time and serves it from /. See crates/maestro-registry/src/web_assets.rs.