Run hcom Agents
Write and run hcom scripts that launch, coordinate, and manage multiple AI coding agents.
Mandatory preflight
Before using any reference script or launching a headless agent:
- Verify the CLI and target tool are installed.
- Run
hcom status and confirm hooks are installed for every backend you plan to use (claude, codex, gemini, opencode).
- If hooks are missing, run
hcom hooks add <tool>, restart that tool, then re-run hcom status.
- If
hcom hooks add <tool> fails or hcom status still does not show installed hooks, stop. Capture hcom status output and do not proceed to launch scripts.
- After launching any headless agent, wait for a ready signal before sending messages. For Codex this usually means
hcom events --wait 30 --idle "$codex_name"; for other tools, use the same check when launch/binding looks uncertain.
- If one agent's startup prompt sends to another agent, launch the recipient first. Examples: reviewer before worker, judge before contestants, Codex engineer before Claude architect.
Decision tree
- User wants to write a new hcom script → Use the Script Template below
- User wants a specific pattern (review loop, ensemble, etc.) → Read
references/patterns/tested-patterns.md
- User wants Claude + Codex together → Read
references/patterns/cross-tool.md
- User wants advanced patterns (reflexion, MoA, red/blue team) → Read
references/patterns/advanced-patterns.md
- Script not working → Read
references/gotchas.md
- User wants to understand how hcom works → Read
references/how-it-works.md
- User needs command syntax → Read
references/cli-reference.md
Script template (baseline reference)
Every hcom script must follow this exact structure:
#!/usr/bin/env bash
set -euo pipefail
LAUNCHED_NAMES=()
track_launch() {
local names=$(echo "$1" | grep '^Names: ' | sed 's/^Names: //')
for n in $names; do LAUNCHED_NAMES+=("$n"); done
}
cleanup() {
for name in "${LAUNCHED_NAMES[@]}"; do
hcom kill "$name" --go 2>/dev/null || true
done
}
wait_for_match() {
local timeout="$1"
local sql="$2"
local result
result=$(hcom events --wait "$timeout" --sql "$sql" $name_arg 2>/dev/null || true)
if [[ -n "$result" ]]; then
echo "$result"
return 0
fi
echo "TIMEOUT: no matching event for thread ${thread}" >&2
hcom events --sql "msg_thread='${thread}'" --last 20 $name_arg 2>/dev/null || true
hcom status 2>/dev/null || true
return 1
}
wait_for_idle() {
local agent_name="$1"
local result
result=$(hcom events --wait 30 --idle "$agent_name" $name_arg 2>/dev/null || true)
if [[ -n "$result" ]]; then
return 0
fi
echo "WAIT FAILED: ${agent_name} never reached idle/listening state" >&2
hcom list 2>/dev/null || true
return 1
}
trap cleanup ERR
name_flag=""
task=""
while [[ $# -gt 0 ]]; do
case "$1" in --name) name_flag="$2"; shift 2 ;; -*) shift ;; *) task="$1"; shift ;; esac
done
name_arg=""
[[ -n "$name_flag" ]] && name_arg="--name $name_flag"
thread="workflow-$(date +%s)"
# Launch, wait_for_idle, message, wait_for_match, cleanup — see patterns for specifics
Required flags (every launch must include these)
| Flag |
Why |
--go |
Skips confirmation prompt. Without it, script hangs. |
--headless |
Runs agent as detached background process. Required for scripts. |
--tag X |
Groups agents for @X- routing. Without it, you must capture raw names. |
--hcom-prompt "..." |
Sets the agent's initial task. |
Essential commands
Launch
launch_out=$(hcom 1 claude --tag worker --go --headless \
--hcom-prompt "Do X. Send result: hcom send \"@reviewer-\" --thread ${thread} --intent inform -- \"DONE: result\". Then: hcom stop" 2>&1)
track_launch "$launch_out"
name=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ')
Message
hcom send @worker- --thread "$thread" --intent request -- "do this task"
hcom send @"${name}" --thread "$thread" --intent inform -- "FYI: done"
hcom send -- "broadcast to all"
Wait (replaces sleep — never use sleep in hcom scripts)
result=$(wait_for_match 120 "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%DONE%'")
echo "PASS: $result"
Read another agent's work
hcom transcript @"${worker_name}" --full --detailed
Cleanup
hcom kill "$name" --go # Kill + close pane
hcom kill all --go # Kill everything
Timing (measured on real tests)
| Operation |
Claude |
Codex |
| Launch to ready |
3-5s |
5-10s |
| Message delivery |
under 1s |
1-3s |
| Full 2-agent round-trip |
15-25s |
25-40s |
Common pitfalls
| Pitfall |
Fix |
| Script hangs forever |
Missing --go on launch or kill |
| Launch fails before the first message |
Run the mandatory hook preflight with hcom status / hcom hooks add <tool> |
| Agent not receiving messages |
Check hcom list — agent may have stopped or not bound yet |
| First targeted send fails at startup |
Launch recipients before senders; for Codex also wait for hcom events --wait 30 --idle "$codex_name" |
| Codex gets stale_cleanup |
Wait: hcom events --wait 30 --idle "$codex_name" before sending |
| Wrong agent targeted |
Use @tag- prefix, not raw 4-letter name |
| Messages leaking between workflows |
Always use --thread for isolation |
| PASS/FAIL logic is wrong |
hcom events --wait returns 0 on timeout too — inspect output, not exit code |
| Hidden orchestrator target |
Baseline scripts should broadcast completion on the workflow thread; do not assume @bigboss exists |
| LIKE matching surprises |
'%APPROVED%' matches "approved":true in JSON — this is fine |
Guardrails
- Never use
sleep — use hcom events --wait or hcom listen
- Never send to agents before they are ready — wait for idle or batch launch
- Never skip
--go — scripts hang waiting for confirmation
- Never hardcode agent names — parse from
Names: line in launch output
- Never skip
--thread — messages leak across workflows without it
- Never treat
hcom events --wait exit code as success/failure — capture its output
- Always set
trap cleanup ERR — orphan agents waste resources
- Always use
hcom kill (not stop) for script cleanup — kill closes the pane
Reference files
| File |
When to read |
references/how-it-works.md |
Understanding hcom delivery pipeline, hooks, identity, bootstrap, relay |
references/cli-reference.md |
Complete hcom CLI command reference with all flags |
references/patterns/tested-patterns.md |
6 reference patterns with working event shapes, readiness waits, and thread-based completion checks |
references/patterns/cross-tool.md |
Claude + Codex + Gemini + OpenCode collaboration details |
references/patterns/advanced-patterns.md |
10 advanced patterns from 35-repo research (reflexion, MoA, red/blue team, etc.) |
references/gotchas.md |
Debugging: timing, stale agents, Codex binding, message delivery |
references/scripts/basic-messaging.sh |
Baseline: two agents exchange messages with diagnostics on timeout |
references/scripts/review-loop.sh |
Baseline: worker-reviewer feedback loop |
references/scripts/cross-tool-duo.sh |
Baseline: Claude architect + Codex engineer |
references/scripts/ensemble-consensus.sh |
Baseline: 3 independent agents + judge |
references/scripts/cascade-pipeline.sh |
Baseline: sequential plan then execute |
references/scripts/codex-worker.sh |
Baseline: Codex codes, Claude reviews transcript |