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
Miguel PalhasandClaude Sonnet 5 d4c72577b9 feat(maestro): swap web session-list/pane focus keys to Tab/Esc
Tab now moves the keyboard from the session list to the pane (was
Escape); Escape moves it back from the pane to the list, intercepted via
xterm's attachCustomKeyEventHandler so it never reaches the shell/app.
Matches the TUI's `tab`/`esc` pair; Ctrl+Q was ruled out since browsers
reserve it and never deliver it to page JS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 17:58:28 +01:00
..

maestro-web

Browser UI for Maestro. Talks to a single local daemon over its /api/* HTTP/WS surface — session catalog, spawn/kill, and 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 daemon if needed.

Layout

src/
  main.ts        # entry point, hash-route dispatch
  api.ts         # daemon HTTP API client
  events.ts      # `/api/events` WebSocket subscriber
   catalog.ts     # session tree view (groups by working directory)
   attach.ts      # xterm.js + attach WS view
   multiview.ts   # tabs + split panes
   spawnForm.ts   # shared spawn form (preset tiles, project picker, worktree)
   spawnModal.ts  # dialog chrome around the spawn form
  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 daemon, ?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 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:7070
pnpm build    # → dist/, embedded into the maestro-web binary at cargo build time

The Vite dev server proxies /api and the WebSockets to a local daemon. Default is http://127.0.0.1:7070; point it elsewhere by exporting MAESTRO_DAEMON_URL before pnpm dev:

MAESTRO_DAEMON_URL=http://laptop.lan:7070 pnpm dev

Production

pnpm build writes the bundle to web/dist/. The maestro-web crate embeds that directory at compile time and serves it from /, reverse-proxying /api/* to the daemon. See crates/maestro-web/src/static_bundle.rs.