mailbox

star 0

Use when sending tasks to other AI providers (codex/gemini), reading task results, or listing inbox. The mailbox is the preferred provider-to-provider path and avoids async-guardrail issues.

2FLing By 2FLing schedule Updated 6/8/2026

name: mailbox description: Use when sending tasks to other AI providers (codex/gemini), reading task results, or listing inbox. The mailbox is the preferred provider-to-provider path and avoids async-guardrail issues.

Mailbox

Send and receive tasks via the CCB Redis mailbox protocol. The mailbox-watcher handles recipient notification automatically — you never need a separate wake-up command.

Non-Negotiable Rules

  • Use node ~/.claude/scripts/mailbox schema [task_type] when unsure; it is the live contract.
  • Build JSON with Bash heredocs (cat > /tmp/mailbox-task.json <<'JSON') and pass "$(cat /tmp/mailbox-task.json)" to the CLI. Do not inline large JSON in shell arguments.
  • Use the mailbox CLI, not raw Redis writes to ccb:task:* / ccb:inbox:*.
  • Incoming task notifications must be answered by claiming and completing/failing the same task id. Do not use mailbox send as a reply unless creating a brand-new follow-up task.
  • Keep envelope fields top-level. Put run linkage in allowed fields like inputs, base_context, or implementation_notes; do not use stale fields such as reply_to or nested body.run_id.

Commands

Command Usage What it does
/mailbox send <to> <objective> Send a task Build envelope, validate, dispatch
/mailbox wait <task-id> [timeout] Wait for result Block until done, return result (subagent-friendly)
/mailbox read <task-id> Get result Fetch result, clear inbox
/mailbox peek <task-id> Check status Read without side effects
/mailbox list <provider> List inbox Show queued tasks
node ~/.claude/scripts/mailbox schema [task_type] Show schema Print required fields, enums, and task-type extras

How It Works

Sender                    Redis                     Recipient
  │                         │                          │
  ├─ mailbox send ─────────►│ task → inbox             │
  │                         │                          │
  │                         │   mailbox-watcher polls   │
  │                         │   detects new task        │
  │                         │                          │
  │                         │ ◄── tmux notification ──►│
  │                         │                          │
  │                         │         claim + execute   │
  │                         │                          │
  │                         │ ◄── mailbox done ────────┤
  │                         │ result → sender inbox     │
  │                         │                          │
  ├─ mailbox wait ─────────►│ polls until done          │
  │◄─ result ──────────────┤│                          │

Key: the mailbox-watcher (background process) handles notifying the recipient via tmux. You do NOT need a separate wake-up command.

Subdirectory sends are supported: the CLI resolves upward to the nearest .ccb root before starting the watcher, so sending from repo/subproject still wakes the mounted provider pane registered at repo/.ccb. If a task remains queued, check the watcher log's work_dir before resending.

Subagent Pattern (Primary Use Case)

When a subagent needs to dispatch work to Codex and get results back:

# 1. Build the task with a single-quoted heredoc so quotes/newlines stay valid JSON.
cat > /tmp/mailbox-task.json <<'JSON'
{
  "task_type": "investigate",
  "objective": "One clear WHAT outcome",
  "why": "Why this matters",
  "deliverable": "findings",
  "evidence": "Required for investigate/fix_bug; include concrete logs or observations",
  "acceptance_criteria": [
    {"id":"AC-1","requirement":"Return usable findings","verification_method":"Result JSON includes findings"}
  ],
  "scope_in": ["/path/or/context"],
  "scope_out": [],
  "authority_flags": {
    "can_create_files": false,
    "can_delete_files": false,
    "can_modify_deps": false,
    "can_edit_dirty_files": false
  }
}
JSON

# 2. Send task (mailbox-watcher notifies Codex automatically).
TASK_ID=$(node __YAO_HOME__/.claude/scripts/mailbox send codex "$(cat /tmp/mailbox-task.json)" | jq -r '.id')

# 3. Wait for result (blocks until Codex completes, auto-cleans inbox).
RESULT=$(node __YAO_HOME__/.claude/scripts/mailbox wait "$TASK_ID" 300)

# 4. Process result.
echo "$RESULT" | jq '.result'

That's it. Two commands. No extra wake-up step. The watcher handles notification, wait handles getting the result.

What NOT to do

Anti-pattern Why it's wrong
Direct Codex wake-up through an async provider command Triggers async guardrail, kills your turn, dumps CCB noise to main session
Legacy dedicated Codex wake-up command Unnecessary — mailbox-watcher already notifies Codex via tmux
Polling with repeated mailbox peek calls Wastes context window — use mailbox wait instead (single blocking call)
Calling mailbox read from subagent Use mailbox wait — it reads AND cleans up in one call

Recipient / Worker Pattern

When a mailbox-watcher notification says a queued task is for Claude, complete that original task instead of sending a new one:

node ~/.claude/scripts/mailbox claim <task-id>
cat > /tmp/mailbox-result.json <<'JSON'
{
  "changedFiles": [],
  "diffSummary": "...",
  "commands": [],
  "notes": []
}
JSON
CCB_CALLER=claude node ~/.claude/scripts/mailbox done <task-id> "$(cat /tmp/mailbox-result.json)"

Use CCB_CALLER=claude node ~/.claude/scripts/mailbox fail <task-id> "$(cat /tmp/mailbox-error.json)" if execution fails. Never answer an inbound task with mailbox send; that creates a brand-new task and leaves the original task running.

Main Session Pattern

From the main (Supervisor) session, the mailbox-watcher sends a tmux notification when results arrive. Then:

# Read result (clears from inbox)
node ~/.claude/scripts/mailbox read <task-id>

Send Flow

When /mailbox send <to> <objective> is invoked:

  1. Build the envelope from context — fill all 8 required fields:
{
  "task_type": "implement|investigate|fix_bug|review|refactor|test|document",
  "objective": "<WHAT not HOW — from args>",
  "why": "<business/technical reason>",
  "deliverable": "code_change|findings|root_cause|test_only|recommendation|documentation",
  "acceptance_criteria": [
    { "id": "AC-1", "requirement": "...", "verification_method": "..." }
  ],
  "scope_in": ["<files/dirs>"],
  "scope_out": ["<files/dirs>"],
  "authority_flags": {
    "can_create_files": false,
    "can_delete_files": false,
    "can_modify_deps": false,
    "can_edit_dirty_files": false
  }
}
  1. Write to temp file with a Bash heredoc (avoids shell escaping and avoids relying on the Write tool):
cat > /tmp/mailbox-task.json <<'JSON'
{
  "task_type": "document",
  "objective": "WHAT outcome",
  "why": "Why this matters",
  "deliverable": "documentation",
  "acceptance_criteria": [
    {"id":"AC-1","requirement":"Task is valid","verification_method":"mailbox send accepts it"}
  ],
  "scope_in": ["/path/or/context"],
  "scope_out": [],
  "authority_flags": {
    "can_create_files": false,
    "can_delete_files": false,
    "can_modify_deps": false,
    "can_edit_dirty_files": false
  }
}
JSON
node ~/.claude/scripts/mailbox send <to> "$(cat /tmp/mailbox-task.json)"
  1. Report task ID from output. Do NOT send any wake-up message.

Required Fields Quick Reference

Field Type Notes
task_type enum implement, investigate, fix_bug, review, refactor, test, document
objective string WHAT not HOW. No code snippets or line numbers
why string Business or technical reason
deliverable enum code_change, findings, root_cause, test_only, recommendation, documentation
acceptance_criteria array Each needs id, requirement, verification_method — all three required
scope_in string[] Non-empty array of file paths/dirs
scope_out string[] Array (can be empty)
authority_flags object All 4 boolean flags required

Task-Type Specific Requirements

task_type Extra required field
fix_bug evidence (error messages, logs)
investigate evidence (observations, logs, reproduction context)
review inputs (comparison target)

Optional Fields

repo_root, workdir, base_context, workspace_state, relevant_files_or_symbols, evidence, constraints, inputs, timebox, implementation_notes, verification_commands, blocker_policy (ask_supervisor|skip_and_note|fail_fast), batch_context

Wait

mailbox wait blocks until a task reaches terminal state (done or failed), then returns the result and auto-cleans the sender's inbox.

# Default timeout: 300s, polls every 3s
node ~/.claude/scripts/mailbox wait <task-id>

# Custom timeout
node ~/.claude/scripts/mailbox wait <task-id> 120

Returns JSON: { "id", "status" ("done"|"failed"|"timeout"), "result", "error" }

Peek / List

# Peek without side effects
node ~/.claude/scripts/mailbox peek <task-id>

# List inbox
node ~/.claude/scripts/mailbox list <provider>

Common Mistakes

Mistake Fix
command not found: mailbox Use full path: node ~/.claude/scripts/mailbox
JSON escaping errors in shell Use a single-quoted Bash heredoc: cat > /tmp/mailbox-task.json <<'JSON', then pass "$(cat /tmp/mailbox-task.json)"
acceptance_criteria missing verification_method Every AC item needs all 3 fields: id, requirement, verification_method
unknown field: task_id Don't include task_id — the system generates id automatically
Passing inline JSON with nested quotes Always use the temp file approach
Calling extra wake-up commands for the recipient Don't — mailbox-watcher handles notification automatically
Subagent calling mailbox read Use mailbox wait instead — blocks, returns, and cleans in one call
Inbound task answered with mailbox send Claim and complete/fail the same task id with `CCB_CALLER=claude ... done
Raw Redis task docs with reply_to / body.run_id Use the CLI top-level envelope; put linkage under allowed fields like inputs
Install via CLI
npx skills add https://github.com/2FLing/claude-migration --skill mailbox
Repository Details
star Stars 0
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator