This file documents the agent system in multiclaude for contributors working on agent-related code or extending the system.
multiclaude operates on a physics-inspired principle: multiple autonomous agents create apparent chaos, but CI serves as a ratchet that converts chaos into permanent forward progress.
Agent Activity (Chaotic) CI Gate (Ratchet) Main Branch (Progress)
┌─────────────────────────┐ ┌─────────────┐ ┌─────────────────────┐
│ Worker A: auth feature │──PR──▶│ │ │ │
│ Worker B: auth feature │──PR──▶│ CI Passes? │──merge──▶ │ ████████████████ │
│ Worker C: bugfix #42 │──PR──▶│ │ │ (irreversible) │
└─────────────────────────┘ └─────────────┘ └─────────────────────┘
▲ │
│ │ fail
└────────────────────────────────┘
(retry or spawn fixup)
Key implications for agent design:
- Redundant work is acceptable and expected
- Failed attempts are not wasted - they eliminate paths
- Any PR that passes CI represents valid forward progress
- The merge-queue agent is the critical "ratchet mechanism"
Role: Orchestration and coordination Worktree: Main repository (no isolated branch) Lifecycle: Persistent (runs as long as repo is tracked)
The supervisor monitors all other agents and nudges them toward progress. It:
- Receives automatic notifications when workers complete
- Sends guidance to stuck agents via inter-agent messaging
- Reports status when humans ask "what's everyone up to?"
- Never directly merges or modifies PRs (that's merge-queue's job)
Key constraint: The supervisor coordinates but doesn't execute. It communicates through multiclaude message send rather than taking direct action on PRs.
Role: The ratchet mechanism - converts passing PRs into permanent progress Worktree: Main repository Lifecycle: Persistent
This is the most complex agent with multiple responsibilities:
| Responsibility | Commands Used |
|---|---|
| Monitor PRs | gh pr list --label multiclaude |
| Check CI | gh run list --branch main, gh pr checks <n> |
| Verify reviews | gh pr view <n> --json reviews,reviewRequests |
| Merge PRs | gh pr merge <n> --squash |
| Spawn fix workers | multiclaude worker create "Fix CI for PR #N" |
| Handle emergencies | Enter "emergency fix mode" when main is broken |
Critical behaviors:
- Never merges PRs with unaddressed review feedback
- Enters emergency mode and halts all merges when main branch CI fails
- Tracks PRs needing human input with
needs-human-inputlabel - Can close unsalvageable PRs but must preserve learnings in issues
Role: Execute specific tasks and create PRs
Worktree: Isolated branch (work/<worker-name>)
Lifecycle: Ephemeral (cleaned up after completion)
Workers are the "muscle" of the system. They:
- Receive a task assignment at spawn time
- Work in isolation on their own branch
- Create PRs with detailed summaries (so other agents can continue if needed)
- Signal completion with
multiclaude agent complete - Can ask supervisor for help via messaging
Completion flow:
Worker creates PR → Worker runs `multiclaude agent complete`
↓
Daemon marks agent for cleanup
↓
Daemon notifies supervisor + merge-queue
↓
Health check cleans up worktree + window
Role: User's persistent interactive session
Worktree: Own branch (workspace/<name>)
Lifecycle: Persistent (user's home base)
The workspace is unique - it's the only agent that:
- Receives direct human input
- Is NOT part of the automated nudge/wake cycle
- Can spawn workers on behalf of the user
- Persists conversation history across sessions
Role: Code review and quality gate Worktree: PR branch (ephemeral) Lifecycle: Ephemeral (spawned by merge-queue)
Review agents are spawned by merge-queue to evaluate PRs before merge. They:
- Post blocking (
[BLOCKING]) or non-blocking suggestions as PR comments - Report summary to merge-queue for merge decision
- Default to non-blocking suggestions unless security/correctness issues
Role: Monitors and manages PRs in fork mode Worktree: Main repository Lifecycle: Persistent (used when working with forks)
The PR Shepherd is similar to the merge-queue but designed for fork workflows where you contribute to upstream repositories. It:
- Monitors PRs created by workers
- Tracks PR status on the upstream repository
- Helps coordinate rebases and conflict resolution
Agents communicate via filesystem-based messaging in ~/.multiclaude/messages/<repo>/<agent>/.
pending → delivered → read → acked
| Status | Meaning |
|---|---|
pending |
Written to disk, not yet sent to agent |
delivered |
Sent to agent's tmux window |
read |
Agent has seen it (implicit) |
acked |
Agent explicitly acknowledged |
# From any agent:
multiclaude message send <target> "<message>"
multiclaude message list
multiclaude message read <id>
multiclaude message ack <id>Note: The old agent send-message, agent list-messages, agent read-message, and agent ack-message commands are still available as aliases for backward compatibility.
Messages are JSON files in ~/.multiclaude/messages/<repo>/<agent>/<msg-id>.json:
{
"id": "msg-abc123",
"from": "worker-clever-fox",
"to": "supervisor",
"timestamp": "2024-01-15T10:30:00Z",
"body": "I need clarification on the auth requirements",
"status": "pending"
}The daemon routes messages every 2 minutes via SendKeysLiteralWithEnter() - this atomically sends text + Enter to avoid race conditions (see pkg/tmux/client.go:319).
Each agent has access to multiclaude-specific slash commands via CLAUDE_CONFIG_DIR. These are automatically set up when agents spawn.
| Command | Description |
|---|---|
/refresh |
Sync worktree with main branch (fetch, rebase) |
/status |
Show system status, git status, and pending messages |
/workers |
List active workers for the repository |
/messages |
Check and manage inter-agent messages |
Slash commands are embedded in internal/prompts/commands/ and deployed per-agent:
~/.multiclaude/claude-config/<repo>/<agent>/
└── commands/
├── refresh.md
├── status.md
├── workers.md
└── messages.md
The daemon sets CLAUDE_CONFIG_DIR when starting Claude, which tells Claude Code where to find the custom commands.
- Create
internal/prompts/commands/<name>.mdwith instructions - Add to
AvailableCommandsincommands.go - Rebuild:
go build ./cmd/multiclaude
Default prompts are embedded at compile time via //go:embed:
// internal/prompts/prompts.go
//go:embed supervisor.md
var defaultSupervisorPrompt stringRepositories can customize agent behavior by creating markdown files in .multiclaude/agents/:
| Agent Type | Definition File |
|---|---|
| worker | .multiclaude/agents/worker.md |
| merge-queue | .multiclaude/agents/merge-queue.md |
| review | .multiclaude/agents/review.md |
Precedence order:
<repo>/.multiclaude/agents/<agent>.md(checked into repo, highest priority)~/.multiclaude/repos/<repo>/agents/<agent>.md(local overrides)- Built-in templates (fallback)
Note: Supervisor and workspace agents use embedded prompts only and cannot be customized via this system.
Deprecated: The old system using SUPERVISOR.md, WORKER.md, REVIEWER.md, etc. directly in .multiclaude/ is deprecated. Migrate your custom prompts to the new .multiclaude/agents/ directory structure.
# List agent definitions for the current repo
multiclaude agents list
# Reset definitions to built-in defaults
multiclaude agents reset
# Spawn a custom agent from a prompt file
multiclaude agents spawn --name my-agent --class worker --prompt-file ./custom.mdTo customize how workers operate for your project:
-
First, ensure the default templates are copied to your local definitions:
multiclaude agents reset
-
Edit the worker definition:
$EDITOR ~/.multiclaude/repos/my-repo/agents/worker.md
-
Add project-specific instructions at the end:
## Project-Specific Guidelines ### Commit Conventions - Use conventional commits: feat:, fix:, docs:, refactor:, test: - Reference issue numbers in commit messages ### Code Style - Follow the patterns in existing code - Run `make lint` before creating PRs - All new public functions need docstrings ### Testing Requirements - Add tests for all new functionality - Ensure `make test` passes before marking complete
-
To share with your team, move the customization to the repo:
mkdir -p .multiclaude/agents cp ~/.multiclaude/repos/my-repo/agents/worker.md .multiclaude/agents/ git add .multiclaude/agents/worker.md git commit -m "docs: Add worker agent conventions"
Final Prompt = Default Prompt + CLI Documentation + Custom Prompt
CLI docs are auto-generated via go generate ./pkg/config.
CLI: multiclaude worker create "task description"
↓
1. Generate unique name (adjective-animal pattern)
2. Create git worktree at ~/.multiclaude/wts/<repo>/<name>
3. Create tmux window in session mc-<repo>
4. Write prompt file with task embedded
5. Start Claude with --append-system-prompt-file
6. Register agent in state.json
7. Start output capture via pipe-pane
Agent runs: multiclaude agent complete
↓
1. Agent marked with ReadyForCleanup=true in state
2. Daemon notifies supervisor + merge-queue
3. Health check (every 2 min) finds marked agents
4. Kill tmux window
5. Remove from state.json
6. Delete worktree
7. Clean up messages directory
The daemon runs health checks every 2 minutes with self-healing behavior:
- Check if tmux session exists for each repo
- If tmux session is missing, attempt restoration before cleanup:
- Recreate the tmux session
- Restart supervisor, merge-queue, and any tracked agents
- Only mark agents for cleanup if restoration fails
- For each agent, verify tmux window exists
- Clean up any agents with
ReadyForCleanup=true - Prune orphaned worktrees (disk but not in git)
- Prune orphaned message directories
This self-healing makes the daemon resilient to tmux server restarts, manual session kills, or other unexpected session losses.
All agent state lives in ~/.multiclaude/state.json:
{
"repos": {
"my-repo": {
"github_url": "https://github.com/owner/repo",
"tmux_session": "mc-my-repo",
"agents": {
"supervisor": {
"type": "supervisor",
"worktree_path": "/path/to/repo",
"tmux_window": "supervisor",
"session_id": "uuid-v4",
"pid": 12345,
"created_at": "2024-01-15T10:00:00Z"
},
"clever-fox": {
"type": "worker",
"worktree_path": "~/.multiclaude/wts/my-repo/clever-fox",
"task": "Implement auth feature",
"ready_for_cleanup": false
}
}
}
}
}State updates use atomic write pattern: write to .tmp, then rename().
The daemon periodically "nudges" agents to keep them active:
| Agent Type | Nudge Message |
|---|---|
| supervisor | "Status check: Review worker progress and check merge queue." |
| merge-queue | "Status check: Review open PRs and check CI status." |
| worker | "Status check: Update on your progress?" |
| review | "Status check: Update on your review progress?" |
| workspace | Not nudged (user-driven only) |
Nudges are sent every 2 minutes, but agents are skipped if nudged within the last 2 minutes.
Agent-related tests are in:
internal/messages/messages_test.go- Message systeminternal/state/state_test.go- State managementinternal/prompts/prompts_test.go- Prompt loading
E2E tests require tmux and use MULTICLAUDE_TEST_MODE=1 to skip actual Claude startup:
# Run integration tests
go test ./test/...
# Test specific recovery scenarios
go test ./test/ -run TestDaemonCrashRecoverytest/recovery_test.go covers:
- Corrupted state file recovery
- Orphaned tmux session cleanup
- Orphaned worktree cleanup
- Stale socket cleanup
- Orphaned message directory cleanup
- Daemon crash recovery
- Concurrent state access
-
Define the type in
internal/state/state.go:const AgentTypeMyAgent AgentType = "my-agent"
-
Create the prompt template at
internal/templates/agent-templates/my-agent.md- Note: Only supervisor and workspace prompts are embedded directly in
internal/prompts/ - Other agent types (worker, merge-queue, review) use templates that can be customized
- Note: Only supervisor and workspace prompts are embedded directly in
-
Add the template to
internal/templates/templates.gofor embedding -
Add prompt loading in
GetDefaultPrompt()if needed (for embedded prompts only) -
Add wake message in
daemon.go:wakeAgents()if needed -
Add CLI commands if the agent needs special handling
-
Write tests for the new agent's behavior