Metadata-Version: 2.4
Name: maestro-tui
Version: 0.2.2
Summary: A terminal-native multi-agent command center
Project-URL: Homepage, https://github.com/jmbmunda/maestro
Project-URL: Repository, https://github.com/jmbmunda/maestro
Project-URL: Issues, https://github.com/jmbmunda/maestro/issues
Author-email: Jay Mark Munda <jbmunda@multisyscorp.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,claude,orchestration,terminal,textual,tui
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Terminals
Requires-Python: >=3.11
Requires-Dist: ptyprocess>=0.7.0
Requires-Dist: pyte>=0.8.2
Requires-Dist: textual>=0.86.0
Requires-Dist: tomli-w>=1.0.0
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Description-Content-Type: text/markdown

# maestro

A terminal-native multi-agent command center. Spawns AI/CLI agents in real PTYs
and shows them in switchable panes with a session timeline — all inside one TUI.

## Install

Maestro is a Python CLI (needs **Python 3.11+** and a `claude` on your PATH).
Install it on any device with [`pipx`](https://pipx.pypa.io) so it lands in its
own isolated venv with the `maestro` command on your PATH:

```bash
pipx install "git+https://github.com/jmbmunda/maestro.git"
```

Or run it once without installing, using [`uv`](https://docs.astral.sh/uv/):

```bash
uvx --from git+https://github.com/jmbmunda/maestro.git maestro
```

Update later with `pipx upgrade maestro`. Pin a release with `...@v0.1.0`.

### From source (development)

```bash
git clone https://github.com/jmbmunda/maestro.git && cd maestro
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
```

## Run

```bash
maestro
```

## Keys

Each pane is a **real terminal** (full ANSI: colors, cursor, alt-screen), so
`claude`, `vim`, `htop` etc. render correctly. Maestro has two modes:

**OUTSIDE** (default — manage panes):

- `Ctrl+S` — spawn a `claude` agent in a new pane
- `Ctrl+Shift+S` — spawn a `$SHELL` agent (terminal-dependent; see note)
- `Ctrl+W` — dismiss the focused pane (confirms first if it's still running)
- `r` — rename the focused pane (blank resets to the default `pane-N · claude`)
- `b` — broadcast one prompt to multiple panes at once (pick targets, type, Enter)
- `a` — quick agents: launch a pre-seeded role, or create/edit/delete templates
- `Ctrl+J` / `Ctrl+K` — focus next / previous pane
- `Ctrl+L` — cycle layout: split → grid → focused
- `Ctrl+B` — toggle the sessions status panel
- `Ctrl+A` — toggle the agents panel (off by default)
- `Ctrl+T` — toggle the timeline
- `/` — open the **skills launcher** (pick a skill → injects `/name` into the focused pane)
- `Enter` — step **INSIDE** the focused pane to interact with it
- `q` — quit (also `Ctrl+Q`, where the terminal doesn't grab it — the VSCode
  integrated terminal does)

**INSIDE** (drive one agent): every keystroke goes straight to that pane's
terminal — arrows, `Esc`, `Tab`, `Shift+Tab` (cycle Claude modes), `Option+Enter`
(newline), `Option+←/→` (word motion), `Ctrl-C`, everything. The one reserved key
is **`Ctrl+]`**, which steps back OUTSIDE.

> **Heads-up:** `Ctrl+]` is reliable everywhere (terminals send it as a single
> byte, `0x1d`). `Ctrl+Esc` also works as a fallback, but only in terminals that
> transmit it distinctly (kitty keyboard protocol / `modifyOtherKeys=2`). The
> footer reflects the mode — while INSIDE it shows just `Ctrl+] Exit pane`;
> OUTSIDE it shows the command list.

**Scroll back through a pane's history** — every pane has a real scrollbar: drag
the thumb, click the trough to page, or mouse-wheel over the pane (works INSIDE or
OUTSIDE, including finished panes). While OUTSIDE, `PageUp`/`PageDown` page the
focused pane. The border title shows `⇡N (scrolled)` while you're above the live
view; the pane keeps following new output while parked at the bottom and stays put
once you scroll up — typing INSIDE snaps you back to the live bottom. Up to ~2000
lines are kept per pane.

**Click a pane to focus + interact in one step** — clicking auto-enters that pane,
no separate `Enter` needed. Clicking a different pane while INSIDE another stays
INSIDE the new one. Clicking a finished pane drops you back OUTSIDE. In **focused**
layout, click a row in the `panes` strip to switch.

(Keyboard nav `Ctrl+J`/`Ctrl+K` still moves focus *without* auto-entering, so you
can chain commands like spawn → navigate → spawn → … without stepping in.) The background is transparent, so maestro inherits your terminal's
wallpaper/theme.

### Quick agents

Press **`a`** (OUTSIDE) for one-click specialized agents. A quick agent is a template
— a name + a starting prompt + an optional skill — that spawns a `claude` pane, names
it, injects the skill and prompt, and drops you inside. Ships with built-ins (Reviewer,
Tester, Security, Docs, Refactor) and is fully CRUD-able in-app: **Enter** launches the
highlighted one, **n** new, **e** edit, **d** delete. Templates live in a hand-editable
`~/.config/maestro/quick-agents.toml` (seeded on first run).

### Broadcast

Press **`b`** (OUTSIDE) to fan one prompt out to several sessions at once: a modal
lists the running panes (all checked by default — Space toggles), you type a prompt,
and Enter sends it to every checked pane. Great for "run the same task across N
agents" or kicking off a fleet. Uncheck any pane (e.g. a `$SHELL`) you don't want.

### Skills

Press **`/`** (OUTSIDE) to open the skills launcher — a filterable list of the skills
in `~/.claude/skills` (and a project's `.claude/skills`). Pick one and maestro types
`/name` into the focused pane and steps you inside, exactly as if you'd typed it in
Claude. (Typing `/name` yourself while INSIDE still works too.)

Maestro also watches each pane's output for Claude's skill markers and shows the
active skill as a `⚡<skill>` badge on the pane's border (best-effort — it keys off
Claude's output text).

### Status board

Maestro shows, at a glance, which sessions need you. Each pane gets a best-effort
status inferred from output timing:

- `▶` **working** — producing output right now
- `⏳` **waiting** — alive but quiet → *needs you* (a question, an approval, or just
  done with its turn); the pane border glows amber
- `○` **done** — exited cleanly · `✗` **failed** — exited non-zero

There's a dedicated **`sessions`** panel on the left listing every pane with its
status, your terminal's own title bar summarises it (e.g. `maestro   ▶2 ⏳1 ○1`), and
each pane border reflects it too. (Heuristic: maestro can't tell "waiting for approval"
from "waiting for your next message" — both show as `⏳ waiting`.) The focused pane
stands out with a **colored border** (green while you're INSIDE it) and full-brightness
text, while non-focused panes are dimmed. The `sessions` panel is **on by default**
(toggle with `Ctrl+B`); a second **`agents`** panel with the same rows is **off by
default** (toggle with `Ctrl+A`); the `timeline` event log is **off by default** (toggle
with `Ctrl+T`).

### Theme

Maestro defaults to the **`ansi-dark`** theme, which draws with your terminal's own
16-colour palette — so it adapts to whatever colour scheme your terminal uses. Press
`Ctrl+P` → "Change theme" to pick another (`ansi-light` for light terminals, or any
of Textual's built-ins like `gruvbox` / `dracula`). Your choice is remembered in
`.maestro/state.json`.

> **Note:** `Ctrl+Shift+S` relies on the terminal forwarding shift+ctrl combos; some
> terminals fold it into `Ctrl+S`. `claude` is the default spawn either way.
>
> `Ctrl+]` is the only key maestro reserves while INSIDE, so apps that use it
> (e.g. vim's tag-jump) won't see it.

## Layouts

- **split** — vertical stack; auto-promotes to grid once a 4th pane spawns
- **grid** — auto-shaped tiles (2×2, 2×3, 3×3, then a scrollable 3×N)
- **focused** — one large pane plus a left strip of status tiles for the rest

When an agent **exits cleanly** (`exit=0`) the pane is auto-dismissed — no
frozen-screen confusion. **Failed exits** (non-zero) stay sticky so you can read
what went wrong; press `Ctrl+W` to dismiss those.

## Layout

```
┌─timeline──────────────────────────────────────────┐
│ 16:18:30 spawn  pane-1 claude                      │
│ 16:18:42 spawn  pane-2 /bin/zsh -l                 │
└────────────────────────────────────────────────────┘
┌─panes──┐ ┌─● pane-1 · claude · INSIDE — Ctrl+] to exit┐
│ ● 1 cla│ │                                            │
│ ○ 2 sh │ │   (live terminal — claude renders here)    │
│ ◄      │ │                                            │
└────────┘ └────────────────────────────────────────────┘
```

(The `panes` strip only appears in **focused** layout. A pane's border turns
heavy/green while you're INSIDE it.)

## Where things live

- `maestro/app.py` — Textual app, key bindings, focus-toggle, spawn/dismiss/focus
- `maestro/panes.py` — `Pane` model + `PaneManager` state machine (Textual-agnostic)
- `maestro/layouts.py` — split / grid / focused renderers + the focus tiles strip
- `maestro/terminal.py` — pyte-backed `Emulator`, `TerminalView`, query responder, key encoder
- `maestro/agent.py` — PTY-backed subprocess wrapper (`ptyprocess`); raw bytes + resize
- `maestro/events.py` — append-only JSONL event log (`.maestro/session.jsonl`)

`.maestro/state.json` persists your layout + timeline-visibility choices across
restarts. Agent sessions themselves are not resumed.

## Tests

```bash
pip install -e '.[test]'
pytest
```

## Next steps

- Provider adapters beyond `claude` / `$SHELL` (`codex`, `gemini`, `gh copilot`)
- Claude Code skill passthrough (toggle `~/.claude/skills` per pane)
- Prompt library + per-agent system prompts
- Inter-agent message bus for "review on modify" workflows
- Terminal niceties: mouse reporting, bracketed paste, configurable INSIDE-exit key
