Skip to content
ivancernjaPublic

About

Run parallel coding agents in isolated git worktrees, from one terminal app

Resources

Stars

8 stars

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

Repository files navigation

maestro

Run parallel coding agents in isolated git worktrees, from one terminal app.

ci license rust

maestro

Higher quality version

maestro lets you run several coding agents at the same time without them getting in each other's way. It gives each one its own git worktree and branch, keeps them all in a sidebar, and shows the selected agent's terminal beside it. The terminal is a real one, so you type to the agent directly.

You can leave an agent working and come back to it. The agents run in detached tmux sessions, so they keep going after you quit maestro and are still there when you open it again.

Install

cargo install --git https://github.com/ivancernja/maestro

Or build it from a clone:

git clone https://github.com/ivancernja/maestro
cd maestro
cargo build --release
ln -s "$PWD/target/release/maestro" ~/.local/bin/maestro
Needs For
tmux, git required, a workspace is a tmux session in a worktree
an agent CLI any of claude, codex, opencode, gemini, copilot, crush, grok, omp, pi
ss (iproute2) the listening ports panel
lazygit reviewing changes with g

Repositories are found under ~/Work, ~/code, ~/src, ~/dev, ~/projects and similar directories without configuration, three levels deep. If none of those exist, maestro looks two levels deep in your home directory instead. If it finds nothing either way, the picker says so and points at MAESTRO_REPO_ROOT, which replaces the search and takes several paths separated by colons.

maestro runs on any Linux system that has tmux and git. It picks up a few extras on Omarchy, described below, and works without them everywhere else.

Keys

Run maestro. In normal mode the keys below drive the app, and the main pane shows the agent you have selected.

Key Action
j k move, and switch the main pane to that agent
click, scroll select a workspace with the mouse
⏎ i insert mode, every key goes to the agent
n new workspace
g lazygit over the worktree
s e $SHELL or $EDITOR in the worktree
p listening ports
L merge into the base branch and retire the workspace
R relaunch an agent that has exited
d remove the workspace, worktree and branch
r refresh now
esc dismiss an error
q quit, agents keep running

While you are typing to an agent, three keys still belong to maestro.

Key Action
alt+n new workspace
alt+j alt+k switch agent and keep typing
ctrl+q leave insert mode, or close an open tool

Creating a workspace

n asks for the repository, the branch, the agent, and the task.

new workspace

The branch field is pre-filled with a composer's name that is not already used in that repository. ⏎ accepts it, tab picks a different one, and typing replaces it. The worktree is created next to the repository as ../<repo>--<branch>.

The task is optional. If you give one, maestro passes it to the agent on startup with whatever prompt flag that agent takes, so it begins working right away. If you leave it empty, the agent opens at its prompt.

Status

Status comes from whether an agent's screen changed since the last poll. A moving spinner is work, a still screen is not.

Mark Meaning
● working
◆ went quiet while you were looking elsewhere
○ quiet, and you have seen it
✗ the agent exited, R restarts it

status marks

◆ is the only state that needs you, so it is the only one that sends a desktop notification. Selecting the workspace clears the mark. If the agent was already selected when it went quiet, it is not marked, because you were looking at it.

Neither state distinguishes "waiting for your approval" from "finished", since both leave a still screen. That would need per-agent transcript reading.

Review and land

g opens lazygit over the worktree, for reading the diff and committing. L merges the branch into the branch it was created from, then removes the workspace.

Because the merge happens in the repository you work in, maestro checks the preconditions first and says which one failed. The worktree has to be clean, the branch has to be ahead of its base, and the main checkout has to be on that base and clean. If any check fails it does nothing.

Listening ports

p shows what is listening, read from ss and /proc.

listening ports

Dev servers are listed first and marked. maestro reads the command line rather than the process name, so a Next server shows as next and encore run as encore rather than both showing as node.

Each row shows the git root the process was started in and how long it has been running. The pid and full command line of the selected row appear under the list.

x stops one. It asks first and names the port, then sends SIGTERM and escalates to SIGKILL if that is ignored. Only your own sockets appear, because ss withholds the pid for everyone else's.

Configuration

Variable Default
MAESTRO_REPO_ROOT discovered, colon separated for several roots
MAESTRO_STATE ~/.local/state/maestro
MAESTRO_SESSION_PREFIX mst-
MAESTRO_THEME_FILE the active theme's colors.toml

How it works

  • tmux hosts the agents and is never shown. Each workspace is a detached session, and maestro attaches to the selected one inside a pty sized to the main pane, rendered by tui-term. That is why agents survive quitting, and why keystrokes reach them unmodified.
  • Panes are addressed by absolute tmux id, because a base-index of 1 makes numeric targets like :0.0 fail to resolve.
  • Worktrees follow the ../<repo>--<branch> convention, the same layout Omarchy's ga shell helper uses, so worktrees made either way are interchangeable.

Omarchy

maestro does not require Omarchy, but it uses it when it is there.

Colors come from the theme you have active. maestro asks omarchy-theme-color --all for the palette, which is the same resolver the config templates, tmux and the terminal escape sequences use, so it ends up with the theme's real accent, selection and status colors rather than an approximation of them. It watches the theme file, so omarchy theme set shows up in a running maestro within a second and there is nothing to restart.

Two smaller things: notifications go through omarchy-notification-send, so they get the same styling as the rest of the desktop, and the agent picker opens on whatever omarchy default agent is set to. Worktrees also use the same ../<repo>--<branch> layout as Omarchy's ga shell helper, so worktrees made either way are interchangeable.

Off Omarchy, colors are ANSI names, which means they follow whatever palette your terminal already uses. Notifications fall back to notify-send, and the agent picker starts on the first agent it finds installed.

Uninstall

cargo uninstall maestro          # or remove the symlink you made
rm -rf ~/.local/state/maestro    # the workspace registry

Workspaces themselves outlive the binary. Remove them with d before uninstalling, or clean up by hand:

tmux ls | grep '^mst-' | cut -d: -f1 | xargs -r -n1 tmux kill-session -t
git -C <repo> worktree list      # then `worktree remove` and `branch -d`

Development

cargo build
cargo test        # prompt composition and shell quoting
./test/run        # 72 tests driving the real binary inside tmux

test/run starts maestro inside tmux and checks what the panes actually render. MAESTRO_AGENT_CMD replaces the agent with a stand-in process, so running the suite does not use a real agent.

License

MIT, see LICENSE.

About

Run parallel coding agents in isolated git worktrees, from one terminal app

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages