After the daemon-unit step, the wizard now offers a second user unit
(`maestro-web.service`) that runs `maestro-registry` on 127.0.0.1:8888
so the web UI is reachable in a browser locally.
Decisions:
- The unit runs `maestro-registry` directly — the web bundle is already
embedded in that binary, so a separate `maestro-web` binary would be
pure cost. `Description=` and the unit filename make the user-facing
framing clear.
- `Wants=maestrod.service` + `After=` (not `Requires=`): the registry
process doesn't actually need the daemon to start; the web UI just
has nothing to show without one. Soft dependency expresses that.
- Default loopback bind is `127.0.0.1:8888` to make it obvious which
port is the local UI vs a separately deployed registry on `:8080`.
Wizard surface:
- New prompt (default *no*) after the daemon-systemd step.
- New flags: `--no-web`, `--web-bind <addr>`, `--web-exec-start <path>`.
- Skipped automatically when systemd is absent or `--no-systemd` is set.
- The re-run/update path mirrors the daemon flow: refresh the unit,
daemon-reload, restart instead of start.
- `maestro-registry` is only `cargo install`ed when the user opts in,
keeping the no-web install footprint unchanged.
docs/INSTALL.md gets the new flags + a full sample unit body.
The wizard now treats existing state as "we're updating, not installing":
- If `~/.config/maestrod/config.toml` exists, skip the configure prompt with
a clear notice. Sets `configured = true` so the systemd start logic still
makes sense.
- If the systemd user unit already exists, refresh the file in place, skip
the enable prompt (it's either already enabled or the user said no last
time), and ask to `restart` instead of `start` — so the new binary
actually takes effect.
Adds `SystemctlAction::Restart` and a test for it. Same `./install.sh` works
for both first install and subsequent updates; no `--update` flag.
Refs NAP-225.
`curl | sh` only works for public repos — gitea hides private repos with a
404 to unauthenticated clients. Lead with downloading `install.sh` via the
signed-in web UI (or `git show origin/main:install.sh`) and running it
locally. Note that the inner `cargo install --git` still uses whatever git
credentials the host already has, and document `MAESTRO_REPO_URL=ssh://...`
for SSH-only setups.
Refs NAP-225.
Single command for both first install and subsequent updates:
curl -sSf https://git.naps.pt/naps62/maestro/raw/branch/main/install.sh | sh
Builds `maestro-installer` into a temp `--root`, runs the wizard, cleans up —
so only `maestrod` and `maestro` persist in `~/.cargo/bin`. Re-running updates
in place via cargo install's overwrite semantics. Wizard flags pass through
with `sh -s --`. Docs updated to lead with the one-liner.
Refs NAP-225.
New `maestro-installer` crate exposing the `maestro-install` binary. Bootstrap
flow: `cargo install --git ... maestro-installer && maestro-install` runs
`cargo install` for `maestro-daemon` and `maestro-cli`, optionally drives
`maestrod configure`, and on systemd hosts writes a user unit at
`~/.config/systemd/user/maestrod.service` plus reload/enable/start. Pure
builders (cargo install args, systemctl args, unit body) live in the lib and
are unit-tested; main.rs is the prompt glue.
Refs NAP-225.
Removes Tailscale assumptions from the design. Operator configures bind
addresses and is responsible for reachability + perimeter (Wireguard,
private LAN, or any other mechanism); maestro does not police the network
or terminate TLS itself.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds .claude/linear.json for Linear-driven skills (Maestro project on
team Naps62) and the brainstorm design doc covering architecture, wire
protocol, session model, auth, and prototype scope boundary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>