Help us improve
Share bugs, ideas, or general feedback.
From cafleet
Documents the cron-loop primitive for CAFleet Directors per backend (Claude Code: CronCreate + /loop) and team-facilitation instructions (poll, ACK, dispatch, health-check, escalate). Load when spawning or managing CAFleet team members as foundation layer.
npx claudepluginhub himkt/cafleet --plugin cafleetHow this skill is triggered — by the user, by Claude, or both
Slash command
/cafleet:cafleet-agent-team-monitoringThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Foundation layer for CAFleet Directors. This skill documents the cron-like mechanism a Director uses to wake itself up periodically and the team-facilitation instructions it executes on each tick. Load this skill before the `cafleet-agent-team-supervision` skill — supervision builds on the mechanism documented here.
Governs CAFleet agent teams by defining supervision protocol, idle semantics, authorization-scope guards, and communication model. Must be loaded with agent-team-monitoring.
Orchestrates Claude Code multi-agent teams with lifecycle management, failure recovery, idle guardrails, and degraded mode fallback. Invoked when creating or managing agent teams.
Coordinates multiple Claude Code instances as agent teams for workflows needing inter-agent communication. Covers TeamCreate, SendMessage types, task coordination, hooks, and orchestration patterns.
Share bugs, ideas, or general feedback.
Foundation layer for CAFleet Directors. This skill documents the cron-like mechanism a Director uses to wake itself up periodically and the team-facilitation instructions it executes on each tick. Load this skill before the cafleet-agent-team-supervision skill — supervision builds on the mechanism documented here.
Every command below uses angle-bracket tokens (<fleet-id>, <director-agent-id>, <member-agent-id>) as placeholders, not shell variables. Substitute the literal UUID strings printed by cafleet fleet create (which returns both the fleet UUID and the root Director's agent_id — see the cafleet skill § Typical Workflow for the exact output shape) directly into the command. Do not introduce shell variables for agent or fleet IDs — permissions.allow matches command strings literally, and shell expansion breaks that matching.
Flag placement: --fleet-id is a global flag (placed before the subcommand). --agent-id is a per-subcommand option (placed after the subcommand name). For example: cafleet --fleet-id <fleet-id> message poll --agent-id <director-agent-id>.
<fleet-id> — the fleet UUID printed on line 1 of cafleet fleet create text output (or the fleet_id field in --json output)<director-agent-id> — the root Director's UUID printed on line 2 of cafleet fleet create text output (or director.agent_id in --json output). cafleet fleet create inside a tmux session auto-bootstraps the root Director with its placement row — no separate cafleet agent register call is needed to obtain the Director's agent_id.<member-agent-id> — a target member's agent UUID (from member create / member list)CAFleet members do not act autonomously. The Director drives the team — and the Director needs a way to wake itself up periodically to check inboxes, dispatch queued work, and detect stalls. The mechanism for this differs between coding-agent backends.
Claude Code's harness exposes two in-session scheduling tools the Director can call:
| Tool | Use |
|---|---|
CronCreate | Schedule a recurring prompt to fire at a cron interval. Used to set up the active /loop monitor (typically 1-minute cadence). |
ScheduleWakeup | Self-pacing dynamic-mode wake-up — used by /loop when the Director picks its own next-tick delay. |
The /loop Prompt Template (§ /loop Prompt Template below) is the canonical setup — it uses CronCreate under the hood. The loop is mandatory before any cafleet member create call when the Director runs under Claude Code.
Neither Codex CLI (confirmed via survey of https://developers.openai.com/codex/cli/features as of 2026-05) nor opencode exposes an equivalent in-session scheduling primitive. There is no CronCreate, no ScheduleWakeup, no harness-level tool the model can invoke from inside a running session to schedule a future tick. Codex Automations exist but are app-only and cannot be triggered from the local CLI. Opencode's TUI similarly does not surface a self-wakeup primitive — its --agent cafleet binding controls the permission posture, not scheduling.
This means: a codex or opencode root Director cannot run the active /loop monitor. The mechanism is unavailable on either backend.
When active supervision of a CAFleet member team is required, use cafleet fleet create --coding-agent claude for the root Director. Codex and opencode members are fully supported via cafleet member create --coding-agent codex (or --coding-agent opencode) — only the Director needs the cron mechanism. A mixed-backend team (claude Director + codex / opencode members) is the canonical configuration for active-supervision workloads.
If a codex or opencode root Director is required (e.g. operator preference, backend-specific workflow, no claude binary available), one of the following fallbacks must be in place. Active supervision without one of these fallbacks is not supported.
| Fallback | Mechanism | Operational cost |
|---|---|---|
| Out-of-band cron driver | An OS-level scheduler (cron(8), systemd timer, watch -n 60 …) running outside the Director's session keystrokes the supervision-tick prompt into the Director's tmux pane via tmux send-keys. (Operator-side; the Director itself never invokes raw tmux — that is forbidden by the cafleet skill § Shutdown Protocol's use cafleet primitives only rule. This fallback exists because neither codex CLI nor opencode has an in-session scheduler.) | Operator must set up + tear down the timer; not visible inside the session. |
| MCP scheduling server | Codex CLI supports MCP servers; a custom MCP server can expose a scheduling tool the codex Director invokes inline. Opencode also supports MCP, but per docs/reference/coding-agents/opencode.md operators MUST NOT add MCP servers to any opencode config the CAFleet pane loads (MCP-contributed tools bypass the deny-list safety floor) — so this fallback is codex-only. | Requires writing or installing an MCP server; configuration lives in ~/.codex/config.toml. |
| User-driven nudges | The user types a tick prompt at intervals (e.g. "tick" every minute). | Manual, error-prone, doesn't scale beyond short sessions. |
| No active monitor — synchronous in-turn facilitation only | The Director performs all health checks + dispatch within each of its own active turns; no scheduled wake-up. The team only progresses while the Director has an active turn. | Acceptable only for short, fully-Director-driven workflows (no long-running parallel members). The Director's idle window is the team's idle window. |
The fallback in use must be documented in the session's launch instructions. The supervision skill's Authorization-Scope Guard applies regardless of which fallback is in use.
On every supervision tick — whether fired by /loop (Claude Code) or by a fallback (codex or opencode), or executed inline within an active turn — the Director runs these five steps in order. The goal is to facilitate the team in completing tasks, not merely to detect stalls.
cafleet --fleet-id <fleet-id> message poll --agent-id <director-agent-id> returns only the un-acked (input_required) deliveries; ACKing each one (step 2) consumes it, so the next tick's poll surfaces only what has arrived since.cafleet --fleet-id <fleet-id> message ack --agent-id <director-agent-id> --task-id <task-id>. Unacknowledged tasks accumulate in the Director's inbox and obscure new arrivals.cafleet message send. Do not wait for a fresh "go" from the user — the user's original authorization persists across ticks; see the cafleet-agent-team-supervision skill § Authorization-Scope Guard.AskUserQuestion after two nudges produce no progress, or whenever a queued action requires a new user decision (option choice, risky/remote-visible operation, ambiguous teammate question). Do not emit passive-hold messages like Skipping. Holding for go. — the tick is a health check, not a permission renewal.Run this sequence once per supervision tick. Order matters — cheapest non-intrusive check first, most invasive last.
| Step | Command | Purpose |
|---|---|---|
| 1 | cafleet --fleet-id <fleet-id> member list | Enumerate all live members and their pane status |
| 2 | cafleet --fleet-id <fleet-id> message poll --agent-id <director-agent-id> | Check inbox for progress reports or help requests from members |
| 3 | For each member with no recent message: cafleet --fleet-id <fleet-id> member capture --member-id <member-agent-id> | Terminal capture fallback — inspect what the member is doing when it has not reported in. If the capture shows an AskUserQuestion-style prompt, see Stall Response below for the member send-input escape hatch. |
| 4 | Based on findings, cafleet --fleet-id <fleet-id> message send --agent-id <director-agent-id> --to <member-agent-id> --text "..." to any stalled or idle member with a specific instruction | Drive the team forward |
| 5 | When all members have reported completion (via messages or visible in terminal output), report to the user: "All deliverables are ready for review." | Signal completion to user |
/loop Prompt Template (Claude Code only)Claude Code-specific. This template depends on
CronCreate/ScheduleWakeup, which are Claude Code harness tools. Codex and opencode Directors cannot use this template — see § Mechanism by backend → Codex Director / Opencode Director for fallback options.
Substitute the literal UUIDs into every <fleet-id>, <director-agent-id>, and <member-agent-id> placeholder before passing the prompt to /loop. The prompt must contain literal UUIDs, not shell variables — the permissions.allow matcher only allows literal command strings. Remember: --fleet-id goes before the subcommand, --agent-id goes after.
Monitor team health (interval: 1 minute). For each member spawned via `cafleet member create`:
1. Run `cafleet --fleet-id <fleet-id> --json member list` to enumerate members.
2. Run `cafleet --fleet-id <fleet-id> --json message poll --agent-id <director-agent-id>` to check incoming un-acked messages. ACK any progress reports — ACKing consumes them, so the next tick's poll returns only what has arrived since.
3. For each member that has NOT sent a message since last check, run `cafleet --fleet-id <fleet-id> member capture --member-id <member-agent-id> --lines 200` to inspect their terminal.
4. If a member's terminal shows no forward progress, send a specific instruction via `cafleet --fleet-id <fleet-id> message send --agent-id <director-agent-id> --to <member-agent-id> --text "Report your progress now. If blocked, state what is blocking you."`.
5. If a member appears stalled despite a recent `message send` (auto-fire missed or pane was busy), re-poke its inbox via `cafleet --fleet-id <fleet-id> member ping --member-id <member-agent-id>`.
6. If all members have reported completion, report to the user: "All deliverables are ready for review."
7. If a member has been nudged 2 times with no progress, escalate to the user.
| Phase | Action |
|---|---|
| Spawn members | Start the /loop (Claude Code) or fallback driver (codex or opencode) BEFORE the first cafleet member create call, so the first tick fires while spawning completes. |
| Run work | Tick at the configured cadence (1 minute is the CronCreate floor); do not intervene unless a tick escalates. |
| User review | Keep the loop alive during the review cycle — revisions and re-reviews still count as in-progress work. |
| User approves final artifact | The loop terminates itself after teardown begins (see Cleanup below). |
Lifecycle rule: The loop MUST stay active from the first member create through every phase (research, compilation, review, revision, user approval). At teardown, stop the loop BEFORE deleting members — this is step 1 of the Shutdown Protocol in the cafleet skill and is non-negotiable. A loop that keeps firing after members are deleted spams member list / message poll against a tearing-down fleet, can race with the member-delete path, and (most visibly) leaks cron output into the operator's terminal after the team is ostensibly gone. Full teardown order: stop every /loop cron (or fallback driver) → cafleet member delete each member → cafleet member list to verify the roster is empty → cafleet fleet delete <fleet-id> → cafleet fleet list sanity check. See the cafleet skill → "Shutdown Protocol" for the authoritative procedure.
When you receive any signal that a member may be stalled (loop check, idle notification, user nudge), evaluate using this 2-stage protocol:
Bash request blocking case: When
cafleet message pollreturns a member message asking for a shell command, dispatch viacafleet member exec "<cmd>"per thecafleetskill § Routing Bash via the Director. Member blocks until the keystroke lands; process requests one at a time, don't skip ahead to other inbox items.
cafleet message poll)cafleet --fleet-id <fleet-id> message poll --agent-id <director-agent-id>
cafleet message poll returns only the un-acked (input_required) deliveries addressed to the Director, newest first. ACKing a delivery consumes it, so a later poll surfaces only what has arrived since the last ACK — there is no last-tick timestamp to track. If the member has sent a progress report or help request via cafleet message send, you can act on it immediately without interrupting the member's work. This is non-intrusive and preferred.
cafleet member capture)cafleet --fleet-id <fleet-id> member capture \
--member-id <member-agent-id> --lines 120
--lines 120 is the recommended fallback when classifying a 4-option AskUserQuestion frame (matches the recommendation in skills/cafleet/reference/director.md § Answer a member's AskUserQuestion prompt; the CLI flag default is --lines 30). Re-run with --lines 200 as a fallback only if the first capture is truncated above the choice-prompt frame (the 1. …, 2. …, 3. …, 4. Type something rows are not all visible).
If cafleet message poll shows no recent messages from the member, fall back to capturing the terminal buffer. This is non-intrusive (read-only inspection that works even when the member is mid-task) and replaces raw tmux capture-pane.
If the terminal buffer shows the member paused on a 4-option choice prompt (a list of "1. …", "2. …", "3. …", "4. Type something" rows — the shape that cafleet member send-input is validated for), the correct unblock is cafleet member send-input — never raw tmux send-keys — and the Director MUST delegate the decision to the user BEFORE invoking the wrapper. The Director never picks the --choice digit or drafts the --freetext body on its own judgment. The full three-beat workflow (capture → user-facing decision prompt with shape-matched options → direct Bash invocation of the resolved cafleet member send-input, gated by the coding agent's native per-call permission prompt) and the pane-shapes table live in the cafleet skill's "Answer a member's AskUserQuestion prompt" section — that is canonical; do not duplicate the table here.
Note that
AskUserQuestionshould be used in Claude Code. The "delegate to the user" beat in the workflow above assumes the Director itself runs in Claude Code, whereAskUserQuestionis the dedicated tool for putting a structured choice in front of the operator. Directors running another coding agent must substitute their own equivalent decision-elicitation surface (or fall back to a plain message to the operator). The 4-option-frame shape thatcafleet member send-inputitself targets is a Claude Code idiom — neither codex nor opencode members render the same frame, so on a codex or opencode member the read-then-respond cadence applies but the--choice/--freetextkeystrokes apply only when the captured buffer matches the validated 4-option layout.
If a member is still unresponsive after 2 nudges via cafleet message send AND cafleet member capture shows no forward progress in the terminal buffer, escalate to the user.
| Channel | Type | When to use |
|---|---|---|
cafleet ... message poll --agent-id <director-agent-id> | Non-intrusive, message-based | First — check if the member has reported in |
cafleet ... member capture --member-id <member-agent-id> | Non-intrusive, terminal snapshot | Second — when no messages, inspect what the member is doing |
cafleet ... message send --agent-id <director-agent-id> --to <member-agent-id> --text "..." | Interactive, authoritative | Third — send a specific instruction to unstick the member (broker keystrokes a 2-line inline preview of the message into the member's pane via tmux.send_inline_preview after persisting; no cafleet message poll invocation is in the auto-fire path) |
cafleet ... member ping --member-id <member-agent-id> | Interactive, fixed-action keystroke | Director's pre-approved manual inbox-poll nudge — keystrokes cafleet message poll into the member's pane as a manual re-poke for the case where the broker's inline preview was missed. Two use cases: (a) a member appears stalled despite a recent cafleet message send (the inline preview was missed or the pane was busy when it arrived), or after a long idle window with a queued message still unread; (b) post-member exec chain — the Director MUST follow every successful cafleet member exec with this ping so the member's next turn fires immediately (see the cafleet skill § Member Exec for the chain definition; do not duplicate the wording). No positional argument, pre-approved in permissions.allow. The only boundary is fleet isolation (cross-fleet --member-id → not found; no caller check), shared with capture / send-input / exec. Failures surface as exit 1 (the auto-fire path swallows them silently). |
cafleet ... member send-input --member-id <member-agent-id> (--choice N | --freetext "<text>") | Interactive, restricted keystroke | --choice / --freetext answer an AskUserQuestion-shaped prompt — delegate the decision to the user via the Director's own AskUserQuestion tool call FIRST, then invoke the resolved command via the Director's Bash tool (the coding agent's native per-call permission prompt is the consent surface; never print a fenced bash block for the user to paste). See the cafleet skill's "Answer a member's AskUserQuestion prompt" section for the canonical three-beat workflow + pane-shapes table. The only boundary is fleet isolation, shared with capture. |
cafleet ... member exec --member-id <member-agent-id> "<cmd>" | Interactive, keystroke dispatch | Director-only shell-dispatch primitive — keystrokes ! <cmd> + Enter into the member's pane via the coding agent's ! shortcut (honored by both claude and codex). Shell-dispatch only — for inbox-poll-only nudges use member ping. See ping row for the required follow-up after every successful exec. The only boundary is fleet isolation, shared with capture / send-input. See the cafleet skill § Routing Bash via the Director. |
cafleet ... member delete --member-id <member-agent-id> --force | Interactive, destructive | When member delete has already exited 2 and capture + send-input have failed to unblock the pane — forces an atomic kill_pane + deregister + layout rebalance. Never fall back to raw tmux kill-pane. |
| Process pending shell-command request from member | Blocking on member side | Dispatch via cafleet member exec "<cmd>" per the cafleet skill § Routing Bash via the Director. Don't skip past a member's request — the member sits idle until the keystroke lands. |
| Escalate to user | Last resort | After 2 nudges + no progress in terminal |