zirvDocs

DocsSupervision (zirv ctx)

Usage pacing

README.md, lines 6643–6727View source

Long autonomous runs die if a subscription window (5 hour rolling, 7 day) runs dry mid-task. zirv ctx loop and zirv ctx exec consult a pacing gate before every spawn and every restart, and wait instead of exiting when a window is at or above pace.max_percent (default 99).

Three data layers, best available wins:

  1. Collector, server-authoritative. Claude Code's statusline input carries rate_limits.five_hour and rate_limits.seven_day for Pro and Max sessions after the first response. Wire your statusline through the tee and every live session keeps machine-wide state fresh:

    json
    {
      "statusLine": {
        "type": "command",
        "command": "zirv ctx usage tee -- bash ~/.claude/statusline-command.sh"
      }
    }

    The tee records the fields, then runs your original command unchanged. It always exits 0 and always prints a statusline, so a failure here can never leave you looking at a blank one.

    zirv ctx statusline [-- <your command>] (issue #833) composes with it: it runs your command (or the built-in fallback line when none is given), keeps its output and appends agents n/cap · supervisor off · jev N · $spend to the last line, for example "command": "zirv ctx statusline -- zirv ctx usage tee -- bash ~/.claude/statusline-command.sh". n counts live sessions in the reported directory, cap is dash.max_panes, jev is the 24 hour call count (off without a gate and credential, or past a 2 MiB log), and the spend is Claude Code's own cost.total_cost_usd. It makes no network call; the segment is dropped if it takes over 40 ms, and any error leaves your line exactly as it was. subagentStatusLine is not wired.

  2. Estimator, an approximation. When no fresh collector reading exists, zirv sums token usage across local transcripts (including subagent files) over the trailing window. It is off until you set a budget, because a plan's real token allowance is undocumented and a made-up default would read as data:

    toml
    [pace]
    five_hour_budget_tokens = 0   # set to enable the 5h estimate
    seven_day_budget_tokens = 0   # set to enable the 7d estimate
    count_cache_reads = false     # cache reads are discounted, so excluded
  3. Circuit breaker, authoritative on trip. If the agent prints a documented limit-hit notice, that is treated as 100% no matter what the other layers say: the run is parked until the window resets and then relaunched, without consuming the restart budget.

Full pacing configuration:

toml
[pace]
enabled = true
max_percent = 99.0
collector_max_age_secs = 900
estimator = true
jitter_secs = 30
fallback_delay_secs = 900    # used when a window's reset time is unknown
wait_slack_secs = 3600       # head room added to the window's own length
# max_wait_secs = 7200       # optional absolute override, see below

How long a pause can last#

The wait is bounded per window, not by one global clock: at most the window's own length plus wait_slack_secs, so a five-hour trip is bounded near six hours and a seven-day trip is allowed to wait out the week. That distinction matters, because resuming a seven-day window every few hours would spend tokens against a window that has not reset, which is exactly what pacing exists to prevent.

When a window's reset time is known and lands inside that bound, the pause ends at the reset (plus jitter) and not before. Set max_wait_secs only if you would rather a supervisor give up waiting and proceed after a fixed time; it replaces the per-window bound entirely and is unset by default.

A pause is announced once, not once per check, and appears in the decision log as a single pace-wait entry. Parks and relaunches are logged too. Check the current picture, including how fresh each reading is, with zirv ctx usage.