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/CLAUDE.md
T
Miguel Palhas 9dad3e6472
ci / web (push) Successful in 22s
ci / flake (push) Successful in 4m47s
ci / rust (push) Successful in 5m59s
Merge remote-tracking branch 'origin/main' into animato
# Conflicts:
#	crates/maestro-daemon/Cargo.toml
#	crates/maestro-daemon/src/local_api.rs
#	crates/maestro/Cargo.toml
2026-09-02 18:37:53 +01:00

4.6 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 + SPA on 127.0.0.1:7070
  ├── GET      /                    browser SPA, embedded (feature `web`)
  ├── GET/POST /api/sessions        list / spawn
  ├── DELETE   /api/sessions/:id    kill
  ├── POST     /api/sessions/:id/input  type text into a session
  ├── POST     /api/sessions/:id/prompt an agent reports its first prompt (#131)
  ├── 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/send  CLI client
maestro tui                         ratatui client
browser                             loads the SPA from the daemon, same port

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 / web, default = all four).

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 + SPA (NAP-212, NAP-214)
├── 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), embedded by the daemon's `web` feature
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.

docs/RESTART.md is the contract for what clients do when the daemon restarts or is upgraded under them — the build stamp on /api/info, the status indicator's states, the blocking overlay, grace and poll timings. Read it before changing reconnect behaviour on either client.

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 maestro scope. Example: feat(maestro): add Hello message round-trip test.
  • cargo fmt + cargo clippy --all-targets -- -D warnings before every commit.
  • Integration tests use real tmux and git. Don't mock them. Isolate via temp $HOME and TMUX_TMPDIR.