Removes the retained-worktree store end to end: the daemon's state-dir store, GET/DELETE /api/worktrees, `maestro worktrees list|reclaim`, the TUI overlay behind `w`, and the web `#/worktrees` view and header link. The kill guard stays. A forced kill and a dirty natural exit now leave the worktree on disk untouched instead of parking it in a store, so removing one is an ordinary `git worktree remove`. A pristine tree is still removed on exit. DELETE /api/sessions/:id always answers 204. The header's debug button also goes; Ctrl+Shift+D and `?hud` still toggle the HUD. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4.2 KiB
Maestro
A terminal-session orchestrator for one machine. One daemon per host owns every interactive shell or agent (Claude Code, opencode, plain bash) running on it; clients — CLI, TUI, browser — attach over a plain HTTP + WebSocket API. tmux for persistence, WebSocket for transport.
Architecture
maestro daemon tmux wrapper + session API on 127.0.0.1:7070
├── GET/POST /api/sessions list / spawn
├── DELETE /api/sessions/:id kill
├── GET /api/info hostname, version, home dir, spawn presets
├── GET /api/dirs directory listing (spawn autocomplete)
├── GET /api/recent-dirs spawn history
├── GET /api/gitroot enclosing repo of a path
├── WS /api/events Snapshot + session deltas
└── WS /api/attach/:id raw PTY bytes
maestro list/spawn/attach/kill CLI client
maestro tui ratatui client
maestro-web serves the SPA, reverse-proxies /api/* to the daemon
No authentication layer, no registry, no peer-to-peer. Whoever can reach the
daemon's bind address can drive every session on the host — same trust model as
tmux itself. The operator picks the perimeter: 127.0.0.1 for local-only, a
WireGuard/LAN address to share with their own devices, never a public IP.
Every config field has a default, so ~/.config/maestro/config.toml is
optional.
Where the work is
Linear project Maestro under team Naps62.
.claude/linear.json wires /yolo and /work to this project — they pick from
"available now" (status backlog/pending, not blocked).
Repo layout
Cargo workspace. NAP-245 unified the per-binary crates behind a single
crates/maestro/ umbrella that ships the maestro binary with feature gates
(cli / daemon / tui, default = all three).
crates/
├── maestro/ # umbrella binary `maestro` (cli + daemon + tui, feature-gated) (NAP-245)
├── maestro-protocol/ # shared wire types (NAP-211)
├── maestro-config/ # shared on-disk config schema (NAP-233)
├── maestro-cli/ # `maestro list/spawn/attach/kill` dispatch (NAP-216)
├── maestro-daemon/ # `maestro daemon` — tmux wrapper + HTTP/WS API (NAP-212, NAP-214)
├── maestro-web/ # standalone `maestro-web` browser UI (NAP-241, NAP-249)
├── maestro-tui/ # `maestro tui` — ratatui session manager (NAP-275 epic)
├── maestro-installer/ # `maestro-install` wizard: cargo install + systemd (NAP-225)
└── maestro-e2e/ # cross-process integration tests (NAP-217)
web/ # browser SPA (NAP-218)
flake.nix # Nix flake: packages, checks, dev shell, `nix run .#dev`
nix/ # Home Manager module (`services.maestro`)
See docs/INSTALL.md for end-user install instructions.
docs/WORKTREES.md is the contract for session worktrees — placement,
collisions, what blocks a kill, and what --force leaves behind. Read it
before changing anything that creates or removes one.
docs/SIDEBAR.md is the contract for session cards in the web and TUI
sidebars — line layout, activity colours, duration format, state precedence.
Read it before changing sidebar rendering.
nix run .#dev (or just dev) brings up the whole local stack under
process-compose: a debug daemon on 127.0.0.1:7071, then Vite on :5173 once the
daemon answers /api/info. The SPA proxies /api/* back to the daemon, so only
the UI is exposed on the network. The dev port is deliberately not the daemon's
own default 7070 (devDaemonPort in flake.nix), so the stack never fights a
real daemon on the same host.
Conventions
- TDD by default. Failing test first, then minimal impl. Commit test + impl together.
- Frequent commits. One logical unit per commit; don't pile work up.
- Conventional commits with
maestroscope. Example:feat(maestro): add Hello message round-trip test. cargo fmt+cargo clippy --all-targets -- -D warningsbefore every commit.- Integration tests use real
tmuxandgit. Don't mock them. Isolate via temp$HOMEandTMUX_TMPDIR.