maestro-tui 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- maestro_tui-0.1.0/.github/workflows/release.yml +47 -0
- maestro_tui-0.1.0/.gitignore +8 -0
- maestro_tui-0.1.0/LICENSE +21 -0
- maestro_tui-0.1.0/PKG-INFO +220 -0
- maestro_tui-0.1.0/README.md +190 -0
- maestro_tui-0.1.0/docs/ROADMAP.md +85 -0
- maestro_tui-0.1.0/docs/superpowers/specs/2026-05-27-ansi-terminal-rendering-design.md +204 -0
- maestro_tui-0.1.0/docs/superpowers/specs/2026-05-27-broadcast-input-design.md +89 -0
- maestro_tui-0.1.0/docs/superpowers/specs/2026-05-27-multi-agent-panes-design.md +337 -0
- maestro_tui-0.1.0/docs/superpowers/specs/2026-05-27-quick-agents-design.md +127 -0
- maestro_tui-0.1.0/docs/superpowers/specs/2026-05-27-skill-passthrough-design.md +123 -0
- maestro_tui-0.1.0/maestro/__init__.py +1 -0
- maestro_tui-0.1.0/maestro/agent.py +100 -0
- maestro_tui-0.1.0/maestro/app.py +1118 -0
- maestro_tui-0.1.0/maestro/events.py +47 -0
- maestro_tui-0.1.0/maestro/layouts.py +161 -0
- maestro_tui-0.1.0/maestro/panes.py +254 -0
- maestro_tui-0.1.0/maestro/quick_agents.py +144 -0
- maestro_tui-0.1.0/maestro/skills.py +131 -0
- maestro_tui-0.1.0/maestro/terminal.py +241 -0
- maestro_tui-0.1.0/pyproject.toml +52 -0
- maestro_tui-0.1.0/tests/test_app.py +626 -0
- maestro_tui-0.1.0/tests/test_panes.py +171 -0
- maestro_tui-0.1.0/tests/test_quick_agents.py +66 -0
- maestro_tui-0.1.0/tests/test_skills.py +111 -0
- maestro_tui-0.1.0/tests/test_terminal.py +139 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when you push a version tag (e.g. v0.1.0).
|
|
4
|
+
# Uses PyPI Trusted Publishing (OIDC) — no API token stored in the repo.
|
|
5
|
+
# One-time setup on PyPI: project Settings → Publishing → add a GitHub
|
|
6
|
+
# trusted publisher with owner=jmbmunda, repo=maestro, workflow=release.yml,
|
|
7
|
+
# environment=pypi.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags:
|
|
12
|
+
- "v*"
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- name: Build sdist and wheel
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade build
|
|
25
|
+
python -m build
|
|
26
|
+
- name: Check metadata
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade twine
|
|
29
|
+
twine check dist/*
|
|
30
|
+
- uses: actions/upload-artifact@v4
|
|
31
|
+
with:
|
|
32
|
+
name: dist
|
|
33
|
+
path: dist/
|
|
34
|
+
|
|
35
|
+
publish:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment: pypi
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write # required for Trusted Publishing
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/download-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
- name: Publish to PyPI
|
|
47
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jay Mark Munda
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: maestro-tui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A terminal-native multi-agent command center
|
|
5
|
+
Project-URL: Homepage, https://github.com/jmbmunda/maestro
|
|
6
|
+
Project-URL: Repository, https://github.com/jmbmunda/maestro
|
|
7
|
+
Project-URL: Issues, https://github.com/jmbmunda/maestro/issues
|
|
8
|
+
Author-email: Jay Mark Munda <jbmunda@multisyscorp.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,claude,orchestration,terminal,textual,tui
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: POSIX
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Classifier: Topic :: Terminals
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: ptyprocess>=0.7.0
|
|
23
|
+
Requires-Dist: pyte>=0.8.2
|
|
24
|
+
Requires-Dist: textual>=0.86.0
|
|
25
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# maestro
|
|
32
|
+
|
|
33
|
+
A terminal-native multi-agent command center. Spawns AI/CLI agents in real PTYs
|
|
34
|
+
and shows them in switchable panes with a session timeline — all inside one TUI.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
Maestro is a Python CLI (needs **Python 3.11+** and a `claude` on your PATH).
|
|
39
|
+
Install it on any device with [`pipx`](https://pipx.pypa.io) so it lands in its
|
|
40
|
+
own isolated venv with the `maestro` command on your PATH:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pipx install "git+https://github.com/jmbmunda/maestro.git"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or run it once without installing, using [`uv`](https://docs.astral.sh/uv/):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uvx --from git+https://github.com/jmbmunda/maestro.git maestro
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Update later with `pipx upgrade maestro`. Pin a release with `...@v0.1.0`.
|
|
53
|
+
|
|
54
|
+
### From source (development)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/jmbmunda/maestro.git && cd maestro
|
|
58
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
59
|
+
pip install -e .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Run
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
maestro
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Keys
|
|
69
|
+
|
|
70
|
+
Each pane is a **real terminal** (full ANSI: colors, cursor, alt-screen), so
|
|
71
|
+
`claude`, `vim`, `htop` etc. render correctly. Maestro has two modes:
|
|
72
|
+
|
|
73
|
+
**OUTSIDE** (default — manage panes):
|
|
74
|
+
|
|
75
|
+
- `Ctrl+S` — spawn a `claude` agent in a new pane
|
|
76
|
+
- `Ctrl+Shift+S` — spawn a `$SHELL` agent (terminal-dependent; see note)
|
|
77
|
+
- `Ctrl+W` — dismiss the focused pane (confirms first if it's still running)
|
|
78
|
+
- `r` — rename the focused pane (blank resets to the default `pane-N · claude`)
|
|
79
|
+
- `b` — broadcast one prompt to multiple panes at once (pick targets, type, Enter)
|
|
80
|
+
- `a` — quick agents: launch a pre-seeded role, or create/edit/delete templates
|
|
81
|
+
- `Ctrl+J` / `Ctrl+K` — focus next / previous pane
|
|
82
|
+
- `Ctrl+L` — cycle layout: split → grid → focused
|
|
83
|
+
- `Ctrl+B` — toggle the sessions status panel
|
|
84
|
+
- `Ctrl+T` — toggle the timeline
|
|
85
|
+
- `/` — open the **skills launcher** (pick a skill → injects `/name` into the focused pane)
|
|
86
|
+
- `Enter` — step **INSIDE** the focused pane to interact with it
|
|
87
|
+
- `q` — quit (also `Ctrl+Q`, where the terminal doesn't grab it — the VSCode
|
|
88
|
+
integrated terminal does)
|
|
89
|
+
|
|
90
|
+
**INSIDE** (drive one agent): every keystroke goes straight to that pane's
|
|
91
|
+
terminal — arrows, `Esc`, `Tab`, `Ctrl-C`, everything. The one reserved key is
|
|
92
|
+
**`Ctrl+Esc`**, which steps back OUTSIDE.
|
|
93
|
+
|
|
94
|
+
> **Heads-up:** `Ctrl+Esc` only fires in terminals that transmit it distinctly
|
|
95
|
+
> (kitty keyboard protocol / `modifyOtherKeys=2`). If your terminal doesn't, the
|
|
96
|
+
> binding won't trigger and there's no built-in fallback exit — kill maestro from
|
|
97
|
+
> another terminal (`pkill -f maestro`) and report it so we can add a fallback. The footer reflects the mode — while INSIDE
|
|
98
|
+
it shows just `Ctrl+] Exit pane`; OUTSIDE it shows the command list.
|
|
99
|
+
|
|
100
|
+
**Click a pane to focus + interact in one step** — clicking auto-enters that pane,
|
|
101
|
+
no separate `Enter` needed. Clicking a different pane while INSIDE another stays
|
|
102
|
+
INSIDE the new one. Clicking a finished pane drops you back OUTSIDE. In **focused**
|
|
103
|
+
layout, click a row in the `panes` strip to switch.
|
|
104
|
+
|
|
105
|
+
(Keyboard nav `Ctrl+J`/`Ctrl+K` still moves focus *without* auto-entering, so you
|
|
106
|
+
can chain commands like spawn → navigate → spawn → … without stepping in.) The background is transparent, so maestro inherits your terminal's
|
|
107
|
+
wallpaper/theme.
|
|
108
|
+
|
|
109
|
+
### Quick agents
|
|
110
|
+
|
|
111
|
+
Press **`a`** (OUTSIDE) for one-click specialized agents. A quick agent is a template
|
|
112
|
+
— a name + a starting prompt + an optional skill — that spawns a `claude` pane, names
|
|
113
|
+
it, injects the skill and prompt, and drops you inside. Ships with built-ins (Reviewer,
|
|
114
|
+
Tester, Security, Docs, Refactor) and is fully CRUD-able in-app: **Enter** launches the
|
|
115
|
+
highlighted one, **n** new, **e** edit, **d** delete. Templates live in a hand-editable
|
|
116
|
+
`~/.config/maestro/quick-agents.toml` (seeded on first run).
|
|
117
|
+
|
|
118
|
+
### Broadcast
|
|
119
|
+
|
|
120
|
+
Press **`b`** (OUTSIDE) to fan one prompt out to several sessions at once: a modal
|
|
121
|
+
lists the running panes (all checked by default — Space toggles), you type a prompt,
|
|
122
|
+
and Enter sends it to every checked pane. Great for "run the same task across N
|
|
123
|
+
agents" or kicking off a fleet. Uncheck any pane (e.g. a `$SHELL`) you don't want.
|
|
124
|
+
|
|
125
|
+
### Skills
|
|
126
|
+
|
|
127
|
+
Press **`/`** (OUTSIDE) to open the skills launcher — a filterable list of the skills
|
|
128
|
+
in `~/.claude/skills` (and a project's `.claude/skills`). Pick one and maestro types
|
|
129
|
+
`/name` into the focused pane and steps you inside, exactly as if you'd typed it in
|
|
130
|
+
Claude. (Typing `/name` yourself while INSIDE still works too.)
|
|
131
|
+
|
|
132
|
+
Maestro also watches each pane's output for Claude's skill markers and shows the
|
|
133
|
+
active skill as a `⚡<skill>` badge on the pane's border (best-effort — it keys off
|
|
134
|
+
Claude's output text).
|
|
135
|
+
|
|
136
|
+
### Status board
|
|
137
|
+
|
|
138
|
+
Maestro shows, at a glance, which sessions need you. Each pane gets a best-effort
|
|
139
|
+
status inferred from output timing:
|
|
140
|
+
|
|
141
|
+
- `▶` **working** — producing output right now
|
|
142
|
+
- `⏳` **waiting** — alive but quiet → *needs you* (a question, an approval, or just
|
|
143
|
+
done with its turn); the pane border glows amber
|
|
144
|
+
- `○` **done** — exited cleanly · `✗` **failed** — exited non-zero
|
|
145
|
+
|
|
146
|
+
There's a dedicated **`sessions`** panel at the top listing every pane with its
|
|
147
|
+
status, the header summarises it (e.g. `maestro ▶2 ⏳1 ○1`), and each pane border
|
|
148
|
+
reflects it too. (Heuristic: maestro can't tell "waiting for approval" from "waiting
|
|
149
|
+
for your next message" — both show as `⏳ waiting`.) The focused pane stands out with a
|
|
150
|
+
**colored border** (green while you're INSIDE it) and full-brightness text, while
|
|
151
|
+
non-focused panes are dimmed. The `sessions` panel is **on by default** (toggle with
|
|
152
|
+
`Ctrl+B`); the `timeline` event log is **off by default** (toggle with `Ctrl+T`).
|
|
153
|
+
|
|
154
|
+
### Theme
|
|
155
|
+
|
|
156
|
+
Maestro defaults to the **`ansi-dark`** theme, which draws with your terminal's own
|
|
157
|
+
16-colour palette — so it adapts to whatever colour scheme your terminal uses. Press
|
|
158
|
+
`Ctrl+P` → "Change theme" to pick another (`ansi-light` for light terminals, or any
|
|
159
|
+
of Textual's built-ins like `gruvbox` / `dracula`). Your choice is remembered in
|
|
160
|
+
`.maestro/state.json`.
|
|
161
|
+
|
|
162
|
+
> **Note:** `Ctrl+Shift+S` relies on the terminal forwarding shift+ctrl combos; some
|
|
163
|
+
> terminals fold it into `Ctrl+S`. `claude` is the default spawn either way.
|
|
164
|
+
>
|
|
165
|
+
> `Ctrl+]` is the only key maestro reserves while INSIDE, so apps that use it
|
|
166
|
+
> (e.g. vim's tag-jump) won't see it.
|
|
167
|
+
|
|
168
|
+
## Layouts
|
|
169
|
+
|
|
170
|
+
- **split** — vertical stack; auto-promotes to grid once a 4th pane spawns
|
|
171
|
+
- **grid** — auto-shaped tiles (2×2, 2×3, 3×3, then a scrollable 3×N)
|
|
172
|
+
- **focused** — one large pane plus a left strip of status tiles for the rest
|
|
173
|
+
|
|
174
|
+
When an agent **exits cleanly** (`exit=0`) the pane is auto-dismissed — no
|
|
175
|
+
frozen-screen confusion. **Failed exits** (non-zero) stay sticky so you can read
|
|
176
|
+
what went wrong; press `Ctrl+W` to dismiss those.
|
|
177
|
+
|
|
178
|
+
## Layout
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
┌─timeline──────────────────────────────────────────┐
|
|
182
|
+
│ 16:18:30 spawn pane-1 claude │
|
|
183
|
+
│ 16:18:42 spawn pane-2 /bin/zsh -l │
|
|
184
|
+
└────────────────────────────────────────────────────┘
|
|
185
|
+
┌─panes──┐ ┌─● pane-1 · claude · INSIDE — Ctrl+Esc to exit┐
|
|
186
|
+
│ ● 1 cla│ │ │
|
|
187
|
+
│ ○ 2 sh │ │ (live terminal — claude renders here) │
|
|
188
|
+
│ ◄ │ │ │
|
|
189
|
+
└────────┘ └────────────────────────────────────────────┘
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
(The `panes` strip only appears in **focused** layout. A pane's border turns
|
|
193
|
+
heavy/green while you're INSIDE it.)
|
|
194
|
+
|
|
195
|
+
## Where things live
|
|
196
|
+
|
|
197
|
+
- `maestro/app.py` — Textual app, key bindings, focus-toggle, spawn/dismiss/focus
|
|
198
|
+
- `maestro/panes.py` — `Pane` model + `PaneManager` state machine (Textual-agnostic)
|
|
199
|
+
- `maestro/layouts.py` — split / grid / focused renderers + the focus tiles strip
|
|
200
|
+
- `maestro/terminal.py` — pyte-backed `Emulator`, `TerminalView`, query responder, key encoder
|
|
201
|
+
- `maestro/agent.py` — PTY-backed subprocess wrapper (`ptyprocess`); raw bytes + resize
|
|
202
|
+
- `maestro/events.py` — append-only JSONL event log (`.maestro/session.jsonl`)
|
|
203
|
+
|
|
204
|
+
`.maestro/state.json` persists your layout + timeline-visibility choices across
|
|
205
|
+
restarts. Agent sessions themselves are not resumed.
|
|
206
|
+
|
|
207
|
+
## Tests
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
pip install -e '.[test]'
|
|
211
|
+
pytest
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Next steps
|
|
215
|
+
|
|
216
|
+
- Provider adapters beyond `claude` / `$SHELL` (`codex`, `gemini`, `gh copilot`)
|
|
217
|
+
- Claude Code skill passthrough (toggle `~/.claude/skills` per pane)
|
|
218
|
+
- Prompt library + per-agent system prompts
|
|
219
|
+
- Inter-agent message bus for "review on modify" workflows
|
|
220
|
+
- Terminal niceties: mouse reporting, bracketed paste, configurable INSIDE-exit key
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# maestro
|
|
2
|
+
|
|
3
|
+
A terminal-native multi-agent command center. Spawns AI/CLI agents in real PTYs
|
|
4
|
+
and shows them in switchable panes with a session timeline — all inside one TUI.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
Maestro is a Python CLI (needs **Python 3.11+** and a `claude` on your PATH).
|
|
9
|
+
Install it on any device with [`pipx`](https://pipx.pypa.io) so it lands in its
|
|
10
|
+
own isolated venv with the `maestro` command on your PATH:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pipx install "git+https://github.com/jmbmunda/maestro.git"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Or run it once without installing, using [`uv`](https://docs.astral.sh/uv/):
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uvx --from git+https://github.com/jmbmunda/maestro.git maestro
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Update later with `pipx upgrade maestro`. Pin a release with `...@v0.1.0`.
|
|
23
|
+
|
|
24
|
+
### From source (development)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/jmbmunda/maestro.git && cd maestro
|
|
28
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
29
|
+
pip install -e .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Run
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
maestro
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Keys
|
|
39
|
+
|
|
40
|
+
Each pane is a **real terminal** (full ANSI: colors, cursor, alt-screen), so
|
|
41
|
+
`claude`, `vim`, `htop` etc. render correctly. Maestro has two modes:
|
|
42
|
+
|
|
43
|
+
**OUTSIDE** (default — manage panes):
|
|
44
|
+
|
|
45
|
+
- `Ctrl+S` — spawn a `claude` agent in a new pane
|
|
46
|
+
- `Ctrl+Shift+S` — spawn a `$SHELL` agent (terminal-dependent; see note)
|
|
47
|
+
- `Ctrl+W` — dismiss the focused pane (confirms first if it's still running)
|
|
48
|
+
- `r` — rename the focused pane (blank resets to the default `pane-N · claude`)
|
|
49
|
+
- `b` — broadcast one prompt to multiple panes at once (pick targets, type, Enter)
|
|
50
|
+
- `a` — quick agents: launch a pre-seeded role, or create/edit/delete templates
|
|
51
|
+
- `Ctrl+J` / `Ctrl+K` — focus next / previous pane
|
|
52
|
+
- `Ctrl+L` — cycle layout: split → grid → focused
|
|
53
|
+
- `Ctrl+B` — toggle the sessions status panel
|
|
54
|
+
- `Ctrl+T` — toggle the timeline
|
|
55
|
+
- `/` — open the **skills launcher** (pick a skill → injects `/name` into the focused pane)
|
|
56
|
+
- `Enter` — step **INSIDE** the focused pane to interact with it
|
|
57
|
+
- `q` — quit (also `Ctrl+Q`, where the terminal doesn't grab it — the VSCode
|
|
58
|
+
integrated terminal does)
|
|
59
|
+
|
|
60
|
+
**INSIDE** (drive one agent): every keystroke goes straight to that pane's
|
|
61
|
+
terminal — arrows, `Esc`, `Tab`, `Ctrl-C`, everything. The one reserved key is
|
|
62
|
+
**`Ctrl+Esc`**, which steps back OUTSIDE.
|
|
63
|
+
|
|
64
|
+
> **Heads-up:** `Ctrl+Esc` only fires in terminals that transmit it distinctly
|
|
65
|
+
> (kitty keyboard protocol / `modifyOtherKeys=2`). If your terminal doesn't, the
|
|
66
|
+
> binding won't trigger and there's no built-in fallback exit — kill maestro from
|
|
67
|
+
> another terminal (`pkill -f maestro`) and report it so we can add a fallback. The footer reflects the mode — while INSIDE
|
|
68
|
+
it shows just `Ctrl+] Exit pane`; OUTSIDE it shows the command list.
|
|
69
|
+
|
|
70
|
+
**Click a pane to focus + interact in one step** — clicking auto-enters that pane,
|
|
71
|
+
no separate `Enter` needed. Clicking a different pane while INSIDE another stays
|
|
72
|
+
INSIDE the new one. Clicking a finished pane drops you back OUTSIDE. In **focused**
|
|
73
|
+
layout, click a row in the `panes` strip to switch.
|
|
74
|
+
|
|
75
|
+
(Keyboard nav `Ctrl+J`/`Ctrl+K` still moves focus *without* auto-entering, so you
|
|
76
|
+
can chain commands like spawn → navigate → spawn → … without stepping in.) The background is transparent, so maestro inherits your terminal's
|
|
77
|
+
wallpaper/theme.
|
|
78
|
+
|
|
79
|
+
### Quick agents
|
|
80
|
+
|
|
81
|
+
Press **`a`** (OUTSIDE) for one-click specialized agents. A quick agent is a template
|
|
82
|
+
— a name + a starting prompt + an optional skill — that spawns a `claude` pane, names
|
|
83
|
+
it, injects the skill and prompt, and drops you inside. Ships with built-ins (Reviewer,
|
|
84
|
+
Tester, Security, Docs, Refactor) and is fully CRUD-able in-app: **Enter** launches the
|
|
85
|
+
highlighted one, **n** new, **e** edit, **d** delete. Templates live in a hand-editable
|
|
86
|
+
`~/.config/maestro/quick-agents.toml` (seeded on first run).
|
|
87
|
+
|
|
88
|
+
### Broadcast
|
|
89
|
+
|
|
90
|
+
Press **`b`** (OUTSIDE) to fan one prompt out to several sessions at once: a modal
|
|
91
|
+
lists the running panes (all checked by default — Space toggles), you type a prompt,
|
|
92
|
+
and Enter sends it to every checked pane. Great for "run the same task across N
|
|
93
|
+
agents" or kicking off a fleet. Uncheck any pane (e.g. a `$SHELL`) you don't want.
|
|
94
|
+
|
|
95
|
+
### Skills
|
|
96
|
+
|
|
97
|
+
Press **`/`** (OUTSIDE) to open the skills launcher — a filterable list of the skills
|
|
98
|
+
in `~/.claude/skills` (and a project's `.claude/skills`). Pick one and maestro types
|
|
99
|
+
`/name` into the focused pane and steps you inside, exactly as if you'd typed it in
|
|
100
|
+
Claude. (Typing `/name` yourself while INSIDE still works too.)
|
|
101
|
+
|
|
102
|
+
Maestro also watches each pane's output for Claude's skill markers and shows the
|
|
103
|
+
active skill as a `⚡<skill>` badge on the pane's border (best-effort — it keys off
|
|
104
|
+
Claude's output text).
|
|
105
|
+
|
|
106
|
+
### Status board
|
|
107
|
+
|
|
108
|
+
Maestro shows, at a glance, which sessions need you. Each pane gets a best-effort
|
|
109
|
+
status inferred from output timing:
|
|
110
|
+
|
|
111
|
+
- `▶` **working** — producing output right now
|
|
112
|
+
- `⏳` **waiting** — alive but quiet → *needs you* (a question, an approval, or just
|
|
113
|
+
done with its turn); the pane border glows amber
|
|
114
|
+
- `○` **done** — exited cleanly · `✗` **failed** — exited non-zero
|
|
115
|
+
|
|
116
|
+
There's a dedicated **`sessions`** panel at the top listing every pane with its
|
|
117
|
+
status, the header summarises it (e.g. `maestro ▶2 ⏳1 ○1`), and each pane border
|
|
118
|
+
reflects it too. (Heuristic: maestro can't tell "waiting for approval" from "waiting
|
|
119
|
+
for your next message" — both show as `⏳ waiting`.) The focused pane stands out with a
|
|
120
|
+
**colored border** (green while you're INSIDE it) and full-brightness text, while
|
|
121
|
+
non-focused panes are dimmed. The `sessions` panel is **on by default** (toggle with
|
|
122
|
+
`Ctrl+B`); the `timeline` event log is **off by default** (toggle with `Ctrl+T`).
|
|
123
|
+
|
|
124
|
+
### Theme
|
|
125
|
+
|
|
126
|
+
Maestro defaults to the **`ansi-dark`** theme, which draws with your terminal's own
|
|
127
|
+
16-colour palette — so it adapts to whatever colour scheme your terminal uses. Press
|
|
128
|
+
`Ctrl+P` → "Change theme" to pick another (`ansi-light` for light terminals, or any
|
|
129
|
+
of Textual's built-ins like `gruvbox` / `dracula`). Your choice is remembered in
|
|
130
|
+
`.maestro/state.json`.
|
|
131
|
+
|
|
132
|
+
> **Note:** `Ctrl+Shift+S` relies on the terminal forwarding shift+ctrl combos; some
|
|
133
|
+
> terminals fold it into `Ctrl+S`. `claude` is the default spawn either way.
|
|
134
|
+
>
|
|
135
|
+
> `Ctrl+]` is the only key maestro reserves while INSIDE, so apps that use it
|
|
136
|
+
> (e.g. vim's tag-jump) won't see it.
|
|
137
|
+
|
|
138
|
+
## Layouts
|
|
139
|
+
|
|
140
|
+
- **split** — vertical stack; auto-promotes to grid once a 4th pane spawns
|
|
141
|
+
- **grid** — auto-shaped tiles (2×2, 2×3, 3×3, then a scrollable 3×N)
|
|
142
|
+
- **focused** — one large pane plus a left strip of status tiles for the rest
|
|
143
|
+
|
|
144
|
+
When an agent **exits cleanly** (`exit=0`) the pane is auto-dismissed — no
|
|
145
|
+
frozen-screen confusion. **Failed exits** (non-zero) stay sticky so you can read
|
|
146
|
+
what went wrong; press `Ctrl+W` to dismiss those.
|
|
147
|
+
|
|
148
|
+
## Layout
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
┌─timeline──────────────────────────────────────────┐
|
|
152
|
+
│ 16:18:30 spawn pane-1 claude │
|
|
153
|
+
│ 16:18:42 spawn pane-2 /bin/zsh -l │
|
|
154
|
+
└────────────────────────────────────────────────────┘
|
|
155
|
+
┌─panes──┐ ┌─● pane-1 · claude · INSIDE — Ctrl+Esc to exit┐
|
|
156
|
+
│ ● 1 cla│ │ │
|
|
157
|
+
│ ○ 2 sh │ │ (live terminal — claude renders here) │
|
|
158
|
+
│ ◄ │ │ │
|
|
159
|
+
└────────┘ └────────────────────────────────────────────┘
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
(The `panes` strip only appears in **focused** layout. A pane's border turns
|
|
163
|
+
heavy/green while you're INSIDE it.)
|
|
164
|
+
|
|
165
|
+
## Where things live
|
|
166
|
+
|
|
167
|
+
- `maestro/app.py` — Textual app, key bindings, focus-toggle, spawn/dismiss/focus
|
|
168
|
+
- `maestro/panes.py` — `Pane` model + `PaneManager` state machine (Textual-agnostic)
|
|
169
|
+
- `maestro/layouts.py` — split / grid / focused renderers + the focus tiles strip
|
|
170
|
+
- `maestro/terminal.py` — pyte-backed `Emulator`, `TerminalView`, query responder, key encoder
|
|
171
|
+
- `maestro/agent.py` — PTY-backed subprocess wrapper (`ptyprocess`); raw bytes + resize
|
|
172
|
+
- `maestro/events.py` — append-only JSONL event log (`.maestro/session.jsonl`)
|
|
173
|
+
|
|
174
|
+
`.maestro/state.json` persists your layout + timeline-visibility choices across
|
|
175
|
+
restarts. Agent sessions themselves are not resumed.
|
|
176
|
+
|
|
177
|
+
## Tests
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pip install -e '.[test]'
|
|
181
|
+
pytest
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Next steps
|
|
185
|
+
|
|
186
|
+
- Provider adapters beyond `claude` / `$SHELL` (`codex`, `gemini`, `gh copilot`)
|
|
187
|
+
- Claude Code skill passthrough (toggle `~/.claude/skills` per pane)
|
|
188
|
+
- Prompt library + per-agent system prompts
|
|
189
|
+
- Inter-agent message bus for "review on modify" workflows
|
|
190
|
+
- Terminal niceties: mouse reporting, bracketed paste, configurable INSIDE-exit key
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Maestro — Feature Roadmap
|
|
2
|
+
|
|
3
|
+
Living list of shipped features and suggested next ones. Vision: **"PromptOps in a
|
|
4
|
+
terminal, simpler"** — orchestrate multiple Claude Code sessions in parallel inside one
|
|
5
|
+
TUI. (See `docs/superpowers/specs/` for per-feature design specs.)
|
|
6
|
+
|
|
7
|
+
Last updated: 2026-05-27
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ✅ Shipped
|
|
12
|
+
|
|
13
|
+
| Feature | How | Spec |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Multi-agent panes | split / grid / focused layouts, `Ctrl+L`; sticky completed | `2026-05-27-multi-agent-panes-design.md` |
|
|
16
|
+
| Full ANSI terminal rendering | pyte emulator per pane; `claude`/`vim`/`htop` render | `2026-05-27-ansi-terminal-rendering-design.md` |
|
|
17
|
+
| Focus-toggle interaction | `Enter` to interact, `Ctrl+Esc` to exit; click auto-enters | — |
|
|
18
|
+
| Per-session status board | `▶` working / `⏳` waiting / `○` done / `✗` failed; `sessions` panel + header summary | — |
|
|
19
|
+
| Skills launcher | `/` opens picker, injects `/name`; active-skill `⚡` badge | `2026-05-27-skill-passthrough-design.md` |
|
|
20
|
+
| Broadcast input | `b` fans one prompt out to selected panes | `2026-05-27-broadcast-input-design.md` |
|
|
21
|
+
| Quick agents | `a` launch/CRUD role templates (Reviewer, Tester, …); spawn + inject | `2026-05-27-quick-agents-design.md` |
|
|
22
|
+
| Pane rename | `r` (blank resets to default) | — |
|
|
23
|
+
| Quit | `q` (also `Ctrl+Q` where the terminal allows) | — |
|
|
24
|
+
| Toggles | `Ctrl+B` sessions panel, `Ctrl+T` timeline | — |
|
|
25
|
+
| Terminal-adaptive theme | defaults to `ansi-dark`; `Ctrl+P` to change; persists | — |
|
|
26
|
+
| Clean-exit auto-dismiss | exit 0 auto-closes; failures stay sticky | — |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 🌟 Suggested next — unique (lean into parallel orchestration)
|
|
31
|
+
|
|
32
|
+
1. **Per-pane working directory / git worktree** ⭐ *top pick*
|
|
33
|
+
Spawn a pane in a different repo or a fresh `git worktree`, so N agents work N
|
|
34
|
+
branches without colliding. Makes parallel *coding* agents actually safe.
|
|
35
|
+
|
|
36
|
+
2. **Desktop notification on waiting/exit**
|
|
37
|
+
Status detection already exists — fire an OS notification so you can background
|
|
38
|
+
maestro and get pulled back when a session needs you.
|
|
39
|
+
|
|
40
|
+
3. **Inter-agent handoff**
|
|
41
|
+
Pipe one pane's output (or a selected block) into another's input: "coder finishes →
|
|
42
|
+
send summary to reviewer." PromptOps' "agents that hand off work" pillar.
|
|
43
|
+
|
|
44
|
+
4. **Agent teams / squads**
|
|
45
|
+
One keypress spawns a *named group* of Quick Agents together (e.g. "Ship squad" =
|
|
46
|
+
Coder + Reviewer + Tester), optionally each in its own worktree. Builds on Quick
|
|
47
|
+
Agents (single) + per-pane worktree (#1). This is the "spawn a coordinated team"
|
|
48
|
+
idea — distinct from launching one Quick Agent.
|
|
49
|
+
|
|
50
|
+
## 🔧 Suggested next — quality of life
|
|
51
|
+
|
|
52
|
+
4. **Session save/restore** — relaunch and re-spawn the same panes (names, cwd, layout).
|
|
53
|
+
Quick-agent + pane names exist today but don't persist; this is the bigger version.
|
|
54
|
+
5. **Scrollback / copy mode** — scroll a pane's history and copy text. pyte's
|
|
55
|
+
`HistoryScreen` already keeps it; just no viewer/selection yet.
|
|
56
|
+
6. **Zoom a pane** — temporarily maximize the focused pane and back (tmux `prefix-z`),
|
|
57
|
+
independent of layout.
|
|
58
|
+
7. **Reorder panes** — move a pane within the grid so related sessions sit together.
|
|
59
|
+
8. **Transcript export** — dump a pane's scrollback to `.maestro/transcripts/pane-N.txt`.
|
|
60
|
+
9. **Config file** (`~/.config/maestro/config.toml`) — default theme/layout, the
|
|
61
|
+
`WAITING_AFTER` threshold, custom agent types, keybindings.
|
|
62
|
+
10. **Bell passthrough** — flash a pane's border when its program emits `\a`.
|
|
63
|
+
|
|
64
|
+
## 🧩 Suggested next — bigger / ecosystem
|
|
65
|
+
|
|
66
|
+
11. **Provider adapters** — `codex`, `gemini`, `gh copilot`, plus a custom "any command"
|
|
67
|
+
type. The `AGENT_TYPES` seam already exists in `maestro/panes.py`.
|
|
68
|
+
12. **Prompt library** — saved, variable-fillable prompts injected into a pane
|
|
69
|
+
(`/prompt deploy-checklist`).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Recommended order
|
|
74
|
+
|
|
75
|
+
**Per-pane cwd/worktree (#1)** → **desktop notifications (#2)** → **session
|
|
76
|
+
save/restore (#4)**. Highest value-to-effort first; per-pane worktree unlocks safe
|
|
77
|
+
parallel coding, which is the core PromptOps use case.
|
|
78
|
+
|
|
79
|
+
## Known limitations (accepted, by design)
|
|
80
|
+
|
|
81
|
+
- Status detection is heuristic (output timing / Claude's output strings) — can't tell
|
|
82
|
+
"waiting for approval" from "waiting for your next message".
|
|
83
|
+
- Keyboard-only inside panes — no mouse reporting, best-effort paste, no image protocols.
|
|
84
|
+
- `Ctrl+Esc` exit needs a terminal that transmits it (kitty protocol / `modifyOtherKeys`).
|
|
85
|
+
- Sessions/pane names are not persisted across restarts (until #5 lands).
|