Add orchestrate skill: main-actor pattern + mav-agent/mav-tmux wrappers

One bot owns the chat and delegates coding to persistent tmux sub-agents,
using a .done file marker for a reliable handoff (status/wait/result).
Includes README + install.sh for one-command setup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mav
2026-05-29 11:31:15 +02:00
commit f509792872
5 changed files with 348 additions and 0 deletions

106
skill/SKILL.md Normal file
View File

@@ -0,0 +1,106 @@
---
name: orchestrate
description: >-
The main-actor pattern for bot teammates. Use when YOU are a bot wired to a
chat (Telegram, etc.) and a request needs real coding/build work. You stay the
ONLY voice in chat and never block — you delegate the heavy work to persistent
tmux sub-agents (mav-agent), poll their done-marker, and report results back.
Trigger when: a chat request implies a long-running build/code task, when you
feel tempted to do heavy work inline and risk freezing the conversation, or
when the user asks to "spawn an agent", "run this in the background", or
"delegate" something.
---
# Orchestrate — one voice talks, hands stay clean
You are the **main actor**: the single process that owns the chat. Your job is to
read messages, decide, reply, and **delegate** anything heavy. You must never
block the conversation on a long build. Coding/builds happen in **sub-agents**
that live in their own tmux windows and persist across turns — even if your own
session gets compacted or restarted.
## The rule
- **You** = the only thing that touches the chat. Fast turns, never blocks.
- **Sub-agents** = do the actual coding/building in tmux. They outlive your turn.
- Never run a long task inline. Spawn it, then poll the marker, then report.
## Tools
Two thin wrappers around a persistent tmux session named `mav`:
- `mav-agent` — spawn/observe named claude or codex sub-agents (one tmux window each).
- `mav-tmux` — run a one-off shell command in the shared session and capture output.
### mav-agent
```
mav-agent run <name> <task> spawn a claude sub-agent (model: opus)
mav-agent run <name> --codex <task> spawn a codex sub-agent
mav-agent status <name> running | done (exit N) | none
mav-agent wait <name> [timeout_s] block until done (marker-based), prints tail
mav-agent result <name> print the agent's full final stdout
mav-agent read <name> live snapshot of the agent's pane
mav-agent list all agent windows + their status
mav-agent kill <name> kill an agent window
```
### The clean handoff (why this is reliable)
Every `run` wraps the agent so that when the CLI exits it writes:
- `/tmp/mav-agent/<name>.out` — full stdout/stderr stream
- `/tmp/mav-agent/<name>.done` — exit code (written ONLY when finished)
`status` / `wait` poll the `.done` marker — **no prompt-sniffing, no guessing**.
Marker present ⇒ work is finished. Absent + window alive ⇒ still running.
This is the gotcha that breaks naive setups: without a real done-signal the main
actor either reports too early or hangs forever. The marker fixes both.
## Playbook (the loop you run every time)
1. **Acknowledge fast.** Reply in chat that you're on it. Don't make the user wait
on a silent turn.
2. **Spawn.** `mav-agent run <name> "<self-contained task with full context>"`.
The sub-agent does NOT share your memory — put everything it needs in the task.
3. **Don't block your turn.** For short work, `mav-agent wait <name> 60`. For long
work, end your turn; on the next wake check `mav-agent status <name>`.
4. **On done:** `mav-agent result <name>`, summarize, reply in chat. Check the
exit code — non-zero means it failed; read `result` and decide a fix or retry.
5. **Clean up** finished windows with `mav-agent kill <name>` so `list` stays readable.
## Conventions
- **Name agents by job**, not sequence: `auth-fix`, `icon-gen`, `db-migrate`.
- **Self-contained tasks.** Sub-agents start cold — no chat history, no your-memory.
Spell out the repo path, the goal, and the done-condition in the task string.
- **One job per agent.** Parallel jobs ⇒ parallel names; they run concurrently.
- **Claude vs codex:** claude (`opus`) for reasoning/multi-file work; `--codex` for
fast scoped edits. Both honor the same status/wait/result handoff.
- **Long-lived processes** (servers, watchers, `npm run dev`) go in `mav-tmux run`,
not an agent — they're meant to keep running, not finish.
## Anti-patterns
- ❌ Doing the build inline in your own turn — freezes the chat, dies on compaction.
- ❌ Polling `read` and eyeballing for a shell prompt — flaky. Use `status`/`wait`.
- ❌ Terse tasks like `"fix the bug"` — the agent has none of your context. Be explicit.
- ❌ Leaving dozens of dead windows around — `kill` them after you read the result.
## Quick example
```bash
# chat: "regenerate the app icons in /Users/m1/proj at 3 sizes"
mav-agent run icon-gen "In /Users/m1/proj, regenerate app icons at 1x/2x/3x \
from assets/icon.svg into assets/icons/. Use the existing gen script if present. \
Print the output paths when done."
mav-agent status icon-gen # -> running
# ... end turn, or wait ...
mav-agent wait icon-gen 120 # -> [done] exit 0 + tail
mav-agent result icon-gen # -> full log to summarize back to chat
mav-agent kill icon-gen
```
That's the whole pattern: one voice in chat, real work in persistent agents, a
file marker for the handoff. Any bot wired to a chat can adopt it by following
this loop.