marver 0.0.14

A TUI workspace for AI agent sessions: tmux orchestration, git worktree management, and repo control in one place.
Documentation
# marver

A TUI workspace for AI agent sessions — tmux orchestration, git worktree
management, and repo control in one place.

Start a task, describe it, and marver opens a tmux session with an agent already
working in its own worktree. Inspired by k9s, cmux, and Warp.

> **Status: early development.** Every subsystem exists and the loop closes —
> describe a task, an agent runs it, review the diff, commit — but nothing has
> been used in anger yet. The published crate is still a name reservation.

```
marver                  open the interface, starting a daemon if none is running
marver status           report whether a daemon is running, and what it holds
marver restart          stop the running daemon and start this version
marver upgrade          install the newest published marver
marver daemon           run the scheduler and hook receiver in the foreground
marver scan [root]      list the git repos it can see
marver --version        print the version (-v, -V)
marver --help           print usage (-h)
```

Every command takes `--data-dir` for where the database, socket, and log live,
`--scan-root` for the directory searched for repos, and `--cap` for how many
agents may run at once. The interface and the daemon find each other through
those paths, so a `--data-dir` given to one must be given to the other.

Just run `marver`. If no daemon is listening it starts one, detached, the way a
tmux client starts the server it needs — and that daemon keeps running after you
close the interface. It owns the queue: it creates a worktree per repo, opens a
tmux session, starts Claude Code with hooks pointing back at itself, and notifies
you when a task finishes or gets stuck. Its output goes to `daemon.log` beside
the database.

Run `marver daemon` yourself to watch it in the foreground or to put it under a
supervisor. Starting a second one is refused rather than allowed to displace the
first.

## Keys

Two rules hold everywhere:

- **`esc` leaves the screen you are on.** On the task list there is nothing
  underneath, so leaving is quitting.
- **`x` discards.** A task on the list, a diff in review. It is never `c`, which
  means commit.

The footer of every screen shows its own keys; the whole set is below.

### Task list

| Key | |
|---|---|
| `j` `k` · `` `` | move |
| `g` `G` · `Home` `End` | first, last |
| `` | open the agent's terminal |
| `v` | review the diff |
| `n` | new task |
| `x` | cancel the task |
| `s` | cycle order — newest, oldest, by repo |
| `a` | show finished tasks too |
| `r` | refresh now |
| `esc` `q` | quit |

### New task

| Key | |
|---|---|
| `tab` | next field: title → prompt → repos |
| `space` | select a repo |
| `j` `k` | move through repos |
| `` | queue it — from the title or the repo list |
| `ctrl-s` | queue it from anywhere, including inside the prompt |
| `esc` | discard |

`↵` inserts a newline in the prompt rather than queueing. A prompt is what the
agent is told to do and is routinely several paragraphs, so the only way to type
a newline is worth more there than the shortcut; `ctrl-s` is how you submit
without leaving the field.

### Agent terminal

Every key goes to the agent, which is the point of the screen, so leaving takes a
chord.

| Key | |
|---|---|
| `ctrl-q` | back to the list |
| `ctrl-esc` | back to the list, where the terminal can say it — see below |
| `` | sent to the agent, and returns a blocked or reviewed task to `running` |

`esc` is not a way out here: it is how Claude is interrupted, and the agent needs
it. `ctrl-esc` is the binding this screen would like to have, but a terminal can
only report it under the kitty keyboard protocol, which marver does not enable —
turning it on changes how every key is reported, and this screen forwards every
key through a hand-built encoding table. In Terminal.app and iTerm2 it will not
arrive at all. **`ctrl-q` is the one that always works**, in every terminal,
because raw mode clears `IXON` and so nothing upstream takes it for flow control.

### Review

| Key | |
|---|---|
| `j` `k` · `` `` | move between files |
| `space` `s` | stage or unstage the file |
| `a` | stage everything |
| `tab` | switch between the staged and working-tree diff |
| `ctrl-d` `ctrl-u` | scroll the diff |
| `c` | commit — type a message, `` to confirm, `esc` to cancel |
| `x` | reject — type instructions to the agent, `` to send |
| `r` | refresh |
| `esc` `q` | back |

Rejecting types your instructions into the agent's live session and returns the
task to `running`. Instructions containing control characters are refused:
`send-keys -l` stops tmux reading them, but the agent still sees the bytes, and
`\r` would submit half a sentence while `\x03` would interrupt the very turn
being asked for.

## Upgrading

```
marver upgrade              # cargo install marver --force
marver upgrade --restart    # and swap the daemon too
```

`marver upgrade` drives cargo, because that is how the crate is distributed. If
you installed marver some other way it says so rather than guessing, and you
upgrade it however you installed it.

Installing a new marver does not replace a daemon that is already running: it
keeps executing the old binary, and since it still holds the socket, nothing
starts a replacement. This is deliberate — that daemon is supervising live
agents, and restarting it underneath them would fail every task it was watching.

`marver status` reports both versions and says so when they differ, and
`marver restart` does the swap when you are ready:

```
marver restart
```

It refuses while any task is `running` or `blocked`, because that is the one
thing a restart can cost. `marver hook` always exits 0 — marver being down must
never interfere with an agent — so a hook arriving while nothing is listening is
simply lost, and the task is left `running` behind an agent that has already
finished. Wait for those tasks to reach `awaiting-review`, or accept it with
`marver restart --force`.

Nothing restarts the daemon on your behalf. It is supervising live agents, and
the moment to interrupt that belongs to whoever knows what they are in the
middle of. Agents already running in tmux survive a restart either way.

See [ARCHITECTURE.md](ARCHITECTURE.md) for the design and the reasoning behind
it.

## Requirements

`tmux` 3.x, `git`, and Claude Code.

## Name

A *marver* is the polished steel table a glassblower rolls hot glass across —
shaping the piece and controlling its temperature between trips to the furnace.
It is the surface where work takes form.

## License

MIT OR Apache-2.0, at your option.