Historical Note: This post describes early agentchute mechanics (such as push-based wakes, watchdogs, or recipient-side service polling) that were deleted in the v0.8.0 pull-only redesign. For the current stable specification, see the AGENTCHUTE.md Protocol Specification.

May 20, 2026 · agentchute team

v0.2: recipient polling, by hand and by hook

tmux made the first agentchute demos feel immediate. It also blurred the protocol boundary. v0.2 fixes that.

agentchute is not tmux. agentchute is the mailbox.

The durable protocol step is simple: a sender writes a no-overwrite message into the recipient's inbox. Everything after that is best-effort liveness. A wake poke can reduce latency, but it is not what makes the protocol correct. The recipient must still discover its own inbox on its own cadence and run the normal recipient flow.

v0.2 makes that no-tmux story explicit — in the spec, in the CLI, and in the generated services agents now ship to their operators.

Four-panel comic of the agentchute workflow: a human writes instructions in a notebook; hands them to a screen of agent characters; the agents coordinate among themselves through their inboxes; the agents deliver the finished result back to the human.
The full loop. v0.2 makes the third panel — agents coordinating through their own inboxes — work the same way regardless of whether they share a tmux server, a host, or even a network.

The rule: schedule the wrapper, not check

agentchute check is a consuming command. It reads message bodies, archives inbox files, quarantines malformed protocol state, and records reply-required obligations. If a shell timer runs check by itself, the model never sees the message. That is silent drain.

The safe loop has two phases:

  1. A read-only preflight asks, "should I wake the wrapper?"
  2. If work exists, the wrapper starts a model turn, and the model runs check.

That is the difference between automation and data loss.

Three recipient-polling tiers

Different wrappers give us different scheduling surfaces, but the same invariant holds in each one.

Tier 1 — native recurring task

Claude Code has a built-in scheduler. One line in the session arms the loop:

/loop 5m process any agentchute mail; reply or defer required messages before stopping

The existing SessionStart / UserPromptSubmit / Stop hooks do the rest. Each tick fires agentchute boot, the model runs check when there is mail, and the Stop hook refuses to finish if the inbox or reply ledger is still dirty.

Codex App has native Automations. Same shape: a 5-minute Automation that prompts the agent to process its mail. Zero new infrastructure.

Tier 2 — preflighted scheduler

Terminal codex CLI and Gemini CLI don't have native recurring tasks today, so v0.2 leans on the simplest dependable primitive: an operator-owned scheduler that runs a side-effect-free preflight and launches the wrapper only when work exists.

agentchute self-poll --as codex --json

Exit 0 means idle. Exit 2 means wake the wrapper. self-poll is deliberately boring: it's a read-only helper over the same inbox and ledger state that pending already exposes. It does not archive, does not quarantine, does not update last_seen, does not poke peers.

It answers exactly one question:

{
  "agent": "codex",
  "should_wake": true,
  "reasons": ["unread"],
  "unread_count": 1,
  "replies_pending": 0,
  "recommended_prompt": "..."
}

That lets a launchd job, systemd timer, cron entry, or shell loop poll every 30 seconds without spending model tokens on empty inboxes. The expensive part — codex exec or gemini -p — only runs when the recipient has work.

Writing the unit file is the only chore. v0.2 ships a generator for it:

# macOS launchd
agentchute doctor --generate-service launchd --as codex \
  --out ~/Library/LaunchAgents/com.agentchute.codex.plist
launchctl load ~/Library/LaunchAgents/com.agentchute.codex.plist

# Linux systemd user
agentchute doctor --generate-service systemd-service --as codex \
  --out ~/.config/systemd/user/agentchute-codex.service
agentchute doctor --generate-service systemd-timer --as codex \
  --out ~/.config/systemd/user/agentchute-codex.timer
systemctl --user enable --now agentchute-codex.timer

# Portable shell loop (cron @reboot, tmux pane, manual sh)
agentchute doctor --generate-service script --as codex \
  --out ~/bin/agentchute-codex.sh

Each artifact is single-flight (POSIX mkdir-as-lock), uses self-poll as preflight, and launches the wrapper with a plain-text prompt that tells the model to run boot + check. Doctor emits only — install / load / start is the operator's job.

Tier 3 — finish-hook continuation

Polling handles idle recipients. Finish hooks handle recipients that are already awake.

If a new message arrives while a model turn is running, the Stop (Claude / codex) or BeforeAgent (Gemini) hook scans the inbox at the end of the turn. If work appeared, the hook refuses to let the wrapper go idle.

The shipped Gemini hook uses structured gate JSON under BeforeAgent:

agentchute gate --as gemini-cli --before finish --json

On work it emits blocked JSON and exits 2. On a clean inbox it emits clear JSON and exits 0.

This is not sender-side wake. It's recipient-side catchup at a lifecycle boundary.

Where tmux fits now

tmux is still useful. If two agents share one tmux server, typing check into the recipient pane is a fast wake hint. The same idea can be implemented with HTTP, SSH, notification services, or a relay.

Those are convenience adapters. They are not the protocol. The new §8.2 says so in normative text:

The protocol's discovery mechanism is recipient-side polling. A recipient agent MUST discover unread mail via its own inbox scans on its own cadence; it MUST NOT depend on external wake signals for correctness.

The protocol stays small: deliver to the inbox; recipient polls; model consumes; reply or defer obligations before stopping. That's enough to run without tmux.

Upgrade

go install github.com/agentchute/agentchute@latest
agentchute doctor --generate-service --help

Three new commands: self-poll, gate --before continue, and doctor --generate-service. The v5 enrollment block teaches the three-tier polling model to any new agent that runs agentchute init. See spec §8 for the full adapter contract and §8.2 for the wake-responsibility text.