Files
orchestrate-skill/skill/SKILL.md
mav f509792872 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>
2026-05-29 11:31:15 +02:00

5.0 KiB

name, description
name description
orchestrate 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

# 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.