maestro-cli/src/config.rs was two pass-throughs, a newtype error, a two-field projection of MaestroConfigFile, and one four-line or_else with a single caller. `resolve_daemon_url` moves onto MaestroConfigFile, next to the schema it reads, and the module goes; its tests move with it. `[web].dev_proxy_target` is deleted end to end — schema, env var, normalisation, three tests, README line, and the startup warning that admitted the server ignores it. MaestroConfigFile::save had no callers outside its own tests. Deleting it also removes every skip_serializing_if, the five is_empty impls, and the Serialize derives that existed only to make its output tidy. BroadcastTuning was a struct that was never instantiated: all three uses were `::DEFAULT.field` in const position and there is no [broadcast] section. Now two plain consts. $MAESTRO_CONFIG was honoured twice, by resolve_config_path and by clap's `env =`. Every binary already gets it through clap, so resolve_config_path and CONFIG_PATH_ENV go and the TUI falls back to default_config_path like everything else. Also collapses three layers of 1:1 forwarding: the umbrella's cli_dispatch shim, and four near-identical 8-line functions in cli/dispatch.rs that differed only in which run_* they called. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2.3 KiB
maestro-web
Standalone HTTP server that hosts the Maestro browser UI and reverse-proxies
to a co-located maestrod.
browser ──HTTP──▶ maestro-web (:8080) ──HTTP/WS──▶ maestrod (:7070)
│
└── / serves the embedded SPA (web/dist)
/api/... proxied unmodified
/api/attach/:id, /api/events proxied as WebSocket
Trust model
maestro-web does not authenticate anyone. Whoever can reach the bind address
can use it. Pick the bind accordingly:
| Bind | Reach | Use when |
|---|---|---|
127.0.0.1:8080 |
Local users on this host | Default. Same as tmux. |
<wg-ip>:8080 |
Devices on your WireGuard mesh | Phone/tablet over VPN. |
<lan-ip>:8080 |
Devices on your trusted LAN | Home / lab networks. |
| Public IP | Don't | — add real auth first. |
Config
The binary reads ~/.config/maestro/config.toml. The [web] section:
[web]
bind_addr = "127.0.0.1:8080" # default
daemon_url = "http://127.0.0.1:7070" # default
Env-var overrides (all optional):
MAESTRO_WEB_BIND_ADDRMAESTRO_WEB_DAEMON_URLMAESTRO_WEB_DEV_PROXY_TARGETMAESTRO_CONFIG— override the unified config-file path.
Build
The SPA bundle lives in ../../web and is embedded into the binary at compile
time via include_dir!. Build the frontend first:
pnpm -C web install
pnpm -C web build
cargo build -p maestro-web --release
Or, from the repo root:
just web
A fresh checkout compiles even without pnpm build (an empty web/dist
exists in-tree); the binary just serves a placeholder until the bundle is
built.
Run
target/release/maestro-web
Then point a browser at http://127.0.0.1:8080/.
Development workflow for the frontend
Use Vite directly so you get HMR. From web/:
pnpm dev
Vite serves on :5173 and proxies /api/* straight to maestrod at
127.0.0.1:7070 (override with MAESTRO_DAEMON_URL=...). You don't need to
rebuild the Rust binary while iterating on the frontend.