Agent quota warmup (agent-warmup)¶
agent-warmup starts the Claude Pro/Max 5-hour subscription usage window at
a scheduled time (e.g. 06:00 on workdays), so a fresh window is already running
before you begin real work — plus an ad-hoc "warm up at this time" one-shot.
The CLI lives at dot_dotfiles/bin/executable_agent-warmup (deployed to
~/.dotfiles/bin/agent-warmup, on PATH). Claude-only by design — Codex /
OpenCode have different quota systems.
Why it drives an interactive session (not claude -p)¶
The 2026-06-15 billing split changed everything
Since 2026-06-15, only interactive Claude Code usage advances the
rolling 5-hour subscription window. Headless claude -p (and the Agent
SDK, GitHub Actions, third-party agents) now draws from a separate metered
Agent SDK credit pool — it does not move the window. A claude -p
"warmup" would silently burn metered API credit and accomplish nothing.
See pitfalls/headless-claude-p-does-not-move-5h-window.md.
So agent-warmup run drives a real interactive claude TUI:
- prefers an existing Herdr session and creates a no-focus transient workspace; falls back to a transient session in the existing GUI-login tmux server when no unambiguous Herdr session is running;
- in an isolated cwd (
$XDG_CACHE_HOME/agent-warmup/claude) so no projectCLAUDE.md/ context is loaded; - with
ANTHROPIC_API_KEYunset (env -u) so it uses your subscription auth (an API key would route to metered credit and not move the window); - accepts the first-run folder-trust prompt, sends a tiny prompt + Enter, waits
for the reply, logs the pane (and
/usagewith--verify), then kills that workspace/session (unless--keep).
Default model is $AICAP_CLAUDE_MODEL (→ haiku) to keep window-token
consumption tiny.
The tmux fallback must borrow your existing server
claude's TUI renders nothing when its tmux server was created by a
background daemon (launchd/pueue) — but renders fine when a daemon connects
to your already-running GUI-session server and spawns claude there. So the
tmux fallback injects into your default tmux server. Constraint: a tmux
server must be running at warmup time when Herdr is unavailable. If none exists
and the caller is not a TTY, run notifies and exits rather than silently
no-op'ing. Full four-trap story (uv launcher hang, amfid/pyexpat stall,
secondary-volume Python, daemon-server blank pane):
pitfalls/agent-warmup-scheduled-run-hangs-or-blank-under-daemon.md.
Confirmed working (2026-06-20)
Both backends verified end-to-end (pueue one-shot and launchd timer):
the scheduled run rendered claude, sent the prompt, got ⏺ hi, and captured
/usage showing the usage on the "Current session" (5-hour) bucket with
the metered "Usage credits" pool off — i.e. genuine interactive
subscription usage that advances the window.
Commands¶
# One-off: warm up now, keep the session + capture /usage for inspection
agent-warmup verify
# Recurring: 06:00 every weekday (launchd on macOS, systemd user timer on Linux)
agent-warmup install --daily weekdays --time 06:00
agent-warmup uninstall
# Ad-hoc one-shot via pueue
agent-warmup at --at '06:00'
agent-warmup at --delay 8h
# Backend control (auto prefers ambient/default/unique running Herdr)
agent-warmup run --backend herdr --herdr-session default
agent-warmup run --backend tmux
# Inspection
agent-warmup status # timer state + pending one-shots + recent run logs
agent-warmup status --json
agent-warmup cancel # remove pending one-shots
# The primitive the schedulers call
agent-warmup run [--backend auto|herdr|tmux] [--herdr-session NAME] [--model haiku] [--prompt 'Reply with just: hi'] [--timeout 120] [--keep] [--verify]
The public CLI is generated from Tyro dataclasses. at and install forward
the shared run flags, including backend selection, into the scheduled run.
Backends¶
| Schedule | macOS | Linux |
|---|---|---|
Recurring (install) |
~/Library/LaunchAgents/com.<user>.agent-warmup.plist (StartCalendarInterval), loaded with launchctl bootstrap; validated with plutil -lint |
~/.config/systemd/user/agent-warmup.{service,timer} (OnCalendar=, Persistent=true), systemctl --user enable --now; validated with systemd-analyze verify |
One-shot (at) |
pueue group agent-warmup, label agent-warmup:oneshot:<ts> |
same |
The recurring timer is imperative and opt-in — generated by install, it is
not chezmoi-managed (so there is no .chezmoi.toml.tmpl prompt and no forced
install on every machine). Run install on the host where you want the warmup.
Both install and at enter through a main-volume Python and a hidden,
stdlib-only bootstrap. The bootstrap tries the pinned PEP 723/Tyro environment
with uv first (--no-project --no-env-file --offline --python <main-python>).
The public run touches a startup sentinel before any interactive side effect.
Only a timeout or failure before that sentinel can fall back to the stdlib
core; once the sentinel exists, fallback is forbidden so a prompt cannot be sent
twice. Logs record runtime: uv or runtime: direct-fallback; uv bootstrap
diagnostics live in ~/.cache/agent-warmup/uv-bootstrap.log.
On 2026-08-25, uv 0.9.24 was re-probed successfully through both pueue and a
temporary gui/<uid> LaunchAgent with the exact flags above. No uv upgrade was
needed; the old blanket "uv cannot run under daemons" assumption was too broad.
Caveats¶
- Herdr mode requires an already-running Herdr session.
agent-warmupdoes not start a daemon. Ambient Herdr wins, then the default or sole running session; ambiguous sessions require--herdr-session. - Tmux fallback requires a login-session tmux server. A daemon-created server still renders a blank Claude TUI.
- Machine asleep at the scheduled time → the job fires on wake (launchd
coalesces missed calendar events; systemd uses
Persistent=true), so the window geometry shifts to wake time. - Keychain must be unlocked (you must be logged into the GUI session) for subscription auth.
- Auth expiry / blank pane →
runlogs the capture and fires a desktop notification (statuswarning: blank pane) rather than reporting a falseok. - Brief workspace blip → a no-focus
warmup-<ts>Herdr workspace or tmux session exists for about a minute, then only that created resource is closed.
Relationship to agent-wakeup¶
agent-warmup is a separate tool from
agent-wakeup (quota recovery — scheduling a
continue into an existing blocked pane). Warmup needs no existing pane, starts
a fresh isolated session, and must not continue real work. The broader
auto-continue loop and a unified dashboard remain backlog items.