agent lifecycle and GC
how --gc parks, reaps, or keeps agent panes alive, why moves are two-phase and crash-safe, and the one known caveat with background subagents.
a heavy TUI holds real memory. left running, dozens of idle agents would take a machine down. GC (garbage collection) is how orcr reclaims panes it no longer needs, on one policy you set per agent: --gc auto | immediate | never.
--gc governs pane lifetime only. history in the store is never affected: an ended agent's row, path, uuid, turns, and transcript locator all remain queryable under ls --all. GC applies only to managed agents; orcr never touches an unmanaged agent's pane.
the three modes
| mode | behavior |
|---|---|
auto (default) | turn-complete and idle for timings.idle_after (5m) moves the pane to the idle workspace (status parked). timings.kill_after (10m) more triggers a graceful kill and releases the memory. an inbound send at any point moves the agent back to its home workspace and resets both clocks. |
immediate | the pane closes as soon as the first turn completes and its final response has been captured (stable idle, then transcript settled, then response recorded, then kill). the agent ends with exit_reason: completed. |
never | exempt from parking and reaping; lives until an explicit agent kill. for pinned long-livers such as heartbeat agents, or a worker you keep talking to across many turns. |
under auto, a reaped agent ends with exit_reason: reaped: it had finished its turns and sat parked past kill_after, so nothing was cut short. under immediate, the final response is verified readable from the transcript before the pane dies, so a waiting ask can read it. see status model and completion for how completion is verified.
there is no default timeout
an agent never times out unless the caller passed an explicit --timeout <dur>; on expiry it is killed with exit_reason: timeout. a stuck-working agent otherwise stays alive and visible (blocked or working in ls and top) until a human or a script acts. the internal stuck-start guard is a separate thing: it only catches spawns that never produce a pane, and it is not a turn timeout. see queue and concurrency.
park and un-park are two-phase and crash-safe
moving a pane between workspaces is not atomic at the herdr layer, so orcr tracks it as a lease. an internal move_state field (parking or unparking) acts as an exclusive move lease (a move_token, a start time, the source terminal, and the destination) recorded alongside the agent's home workspace.
the public status flips to parked (or returns to idle on un-park) only once the store and the actual herdr pane location agree. if the server crashes mid-move, the reconciler completes or rolls back the half-done move on restart. a send that arrives mid-move completes or rolls back that exact move (by token) before delivering, and delivery always addresses the live terminal_id after the location is confirmed, never a pre-move pane id. un-park recreates the tab in the home workspace, labeled from the path, if the original tab is gone.
the GC engine ticks about every timings.gc_tick (30s), and every transition is one store transaction. because all status transitions are serialized through the single-writer server, the interlocks hold:
sendcancels a pending park or reap atomically before delivering input.- completion capture and GC-kill are ordered: the response is recorded before the pane dies.
- GC never moves or reaps a pane with an active attach. attach sessions are persisted as leases (agent, mode, connection, start time, heartbeat), so the guard survives a server restart; leases are cleaned up on socket disconnect or heartbeat expiry.
see durability and recovery for reconciliation, and configuration for the timings.* knobs.
known caveat: background subagents
use --gc never for agents you know will fan out background work.
claude code sometimes reports its main turn idle while background subagents are still running, and herdr then reports idle. under gc auto the agent may be parked. when the subagents return (typically within 15 minutes) it goes working again and is un-parked back to its home workspace, so work is not lost. but a kill_after shorter than the subagents' runtime could reap it mid-flight.
detecting in-flight background subagents from the transcript is future work. until then, --gc never for those agents avoids the reap window entirely.
agents and subagents (lineage)
how an orcr agent spawns subagents, how the server derives scope and records lineage from the environment, and how orcr top renders the tree.
status model and completion
the one status vocabulary every surface shares, the exit_reason groups, and how orcr verifies that a turn is genuinely complete instead of trusting a stale idle.