HQ Inbox: Interrupts + Idle Autopilot
Each HQ in aide gets its own inbox queue under
~/.aide/hq-queue/<hq-name>/. The queue exists so the aide binary can
unify three kinds of incoming events into one stream that the HQ chat session
(or the daemon, when nobody's home) can consume:
- GitHub issues opened against the HQ repo.
- Member-agent completions (local tasks routed by
[router]finishing). - Manual / external pushes from the CLI (
aide hq-inbox push ...).
Two consumers attach to the same queue:
- Online (you're chatting with the HQ): the HQ Claude session has a
long-running Monitor
watching
aide hq-inbox watch <hq>. When a new event arrives mid-conversation, Claude summarizes it and asks how you want to handle it. - Offline (chat idle ≥ 5 min): the daemon's
auto_handlekicks in and routes the inbox via the existing[router]selector (bandit / round-robin / fanout) without waiting for you.
Layout
~/.aide/hq-queue/<hq>/
inbox/ pending JSON files, one per inbound message (FIFO)
processing/ atomic move from inbox during handling
done/ finished, with result/summary/acked_at appended
last_activity touched by `aide hq-touch <hq>` (mtime tracked)
Each inbox file is JSON:
{
"id": "<nanos-based id>",
"ts": "<RFC3339>",
"source": "github-issue|member-completed|cli|other",
"title": "<short>",
"body": "<full>",
"context": { "...arbitrary..." }
}
Bootstrap an HQ
The fastest way to get a new HQ wired up:
aide hq-init ~/projects/my-hq
aide register ~/projects/my-hq
aide hq-init does three things:
- Ensures
Aidefilehas a[router]block (creates the file if missing). - Writes/merges
.claude/settings.local.jsonto add Claude Code hooks (SessionStartandUserPromptSubmit) that callaide hq-touch <hq>— so every user turn refreshes the activity marker. - Appends an "HQ inbox protocol" section to
CLAUDE.mdinstructing the Claude session about the watcher pattern below.
Online pattern (Monitor + interrupt)
In the HQ project, attach a long-running Monitor to the inbox watcher:
/monitor aide hq-inbox watch my-hq
watch polls the inbox dir every 2s and prints one JSON line per new file:
{"id": "172...", "source": "github-issue", "title": "fix the thing", "ts": "..."}
Each line is a Monitor notification. The CLAUDE.md protocol tells the model:
- Summarize the new item for you in one sentence.
- Ask how to handle it (route to a member, defer, ignore).
- After you decide, dispatch via:
aide dispatch --auto --local "<task>" aide hq-inbox ack my-hq <id> --summary "<one-line>" --success
Offline pattern (idle autopilot)
If you don't reply within [router].auto_idle_secs (default 300 = 5 min), the
daemon calls auto_handle on its next tick. auto_handle:
- Checks
last_activitymtime — if newer than the threshold, no-op. - Otherwise, drains the inbox in FIFO order, routing each item via
router::route_issueusing the same selector you've configured (bandit, round-robin, or fanout). - Acks each item with the route outcome.
Tune the threshold per HQ via auto_idle_secs:
[router]
mode = "bandit"
auto_idle_secs = 600 # 10 min instead of default 5 min
CLI reference
aide hq-inbox push <hq> --source <s> --title <t> [--body <b>] [--context <json>]
Write a new inbox JSON file. Body reads from stdin if --body omitted.
aide hq-inbox push my-hq --source cli --title "manual ping" --body "do the thing"
aide hq-inbox ls <hq> [--state inbox|processing|done] [--limit N]
List files in the chosen state directory, newest first. Default state is
inbox.
aide hq-inbox pop <hq>
Atomically moves the oldest inbox file → processing/, prints the full
JSON to stdout. Returns exit 0 with empty stdout if nothing pending.
aide hq-inbox ack <hq> <id> [--summary <s>] [--success]
Atomically moves processing/<id>.json → done/<id>.json with appended
result + summary + acked_at fields.
aide hq-inbox watch <hq> — long-running
Tails the inbox directory and prints one JSON line per new file (line-buffered, Monitor-friendly). Runs forever until SIGTERM.
aide hq-inbox auto-handle <hq> [--max-idle 5m]
If last_activity mtime > --max-idle ago AND inbox non-empty: drains via
router::route_issue and acks each. Otherwise no-op. Prints exactly one
summary line.
aide hq-touch <hq>
Touches ~/.aide/hq-queue/<hq>/last_activity (creates dir + file if missing).
Used by Claude Code's UserPromptSubmit hook so each user turn extends the
idle window.
aide hq-init <hq-dir>
Bootstrap helper described above.
Recovery
If the HQ chat session crashes mid-processing, files in processing/ are
left in place. On restart, you can:
aide hq-inbox ls my-hq --state processing
# Inspect or move them back manually:
mv ~/.aide/hq-queue/my-hq/processing/<id>.json ~/.aide/hq-queue/my-hq/inbox/
auto_handle will pick them up on the next idle window.
Sources fed by aide-binary
| Source | Producer |
|---|---|
github-issue | router::route_issue after dispatching to a member |
member-completed | dispatch::run_local_task finalize when routed_from_hq is set |
cli | aide hq-inbox push <hq> ... |