| name | pai-cost-tracker |
| description | Hourly Claude subscription usage guardrail. Reads PAI canonical usage cache (~/.claude/MEMORY/STATE/usage-cache.json) for 5h/7d window percentages. Voice-alert via pai-pulse if threshold exceeded. Use when user says usage, cost, am I burning too much, take a break, claude limit, rate limit. |
pai-cost-tracker skill
Why this exists
Two goals: catch API-vs-subscription cost leaks early (PAI's CostTracker.ts ledger shows a real $498 invoice from processes silently billing API), and wellness — voice-alert when the 5h/7d subscription window is near its limit so the user stops.
When to use
User intent:
- "usage" → snapshot current 5h/7d %
- "am I close to limit" → threshold check
- "cost this month" → API spend from admin key (if available)
- Automated hourly cron — see
cron/README.md (Hermes jobs.json registration)
Data sources
| Source | What | Path |
|---|
| PAI usage cache | 5h/7d %, native rate_limits | ~/.claude/MEMORY/STATE/usage-cache.json |
| PAI CostTracker ledger | Historical snapshots | ~/.claude/PAI/MEMORY/OBSERVABILITY/anthropic-cost.jsonl |
| Hermes own model usage | Multi-provider tokens consumed | ~/.hermes/state.db (sqlite, table TBD) |
| Anthropic admin API | API spend $ this month | deferred to v0.2 — ANTHROPIC_ADMIN_API_KEY path not yet implemented |
Thresholds (default)
Canonical source: tools/cost_check.py DEFAULT_THRESHOLDS. Values below are read from that dict.
| Window | Warn | Alert (voice) | Block |
|---|
| 5h Claude | 60% | 80% | 95% |
| 7d Claude | 70% | 85% | 95% |
| 7d Opus-specific | — | 90% | — |
| 7d Sonnet-specific | — | 90% | — |
| Monthly extra_usage credits | — | 70% | — |
| API spend (admin key) | — | deferred to v0.2 | — |
Configurable in ~/.hermes/config.yaml under pai_hermes.cost_thresholds:.
Algorithm
- Run
cost_check.py --cache "$PAI_USAGE_CACHE" --voice (see Invoking below). It reads five_hour/seven_day/…utilization, classifies against thresholds, and prints only when action is needed (breach or stale cache).
- Quiet hours (22:00–07:00 local): still read + snapshot, but drop
--voice/pai-pulse; log the suppression.
- Non-empty stdout → invoke
pai-pulse with the composed message. At Block level, tag priority + push to Telegram via the Hermes gateway.
- Append the snapshot to
~/.hermes/state/pai-cost-snapshots.jsonl (audit trail) every run.
- Return the JSON summary for in-context display.
Output
{ "schema": "pai-hermes.cost.v1", "ts": "2026-05-16T15:00:00Z",
"five_hour_pct": 78, "seven_day_pct": 52, "opus_7d_pct": 65, "sonnet_7d_pct": 30,
"extra_credits_used_pct": 12, "alerts_triggered": ["five_hour"], "block_triggered": [],
"next_reset_5h": "2026-05-16T18:00:00Z" }
Voice alert composition
Templates per trigger, sent via pai-pulse (ElevenLabs TTS). API-spend voice alert deferred to v0.2.
five_hour: "5 hour Claude window at {pct}%. Consider taking a break."
seven_day: "Weekly Claude limit at {pct}%. Reset in {hours} hours."
extra_credits: "Extra credits at {pct}% of monthly limit. ${used} of ${limit}."
Cron entry
Register via Hermes — see cron/README.md. Job is stored in ~/.hermes/cron/jobs.json:
{ "name": "pai-cost-tracker", "schedule": { "kind": "cron", "expr": "0 * * * *" }, "skill": "pai-cost-tracker" }
Coordination with omc skill
Pre-flight gate: if 5h window ≥80% (ALERT, per tools/cost_check.py DEFAULT_THRESHOLDS), omc skill refuses ralph/team/autopilot/ultrawork until reset or user passes --force.
Invoking cost_check.py
cost_check.py lives at the pai-hermes checkout root, not inside the installed skill dir — running it relative to the skill cwd fails. install.sh records the checkout path as PAI_HERMES_ROOT in $HERMES_HOME/pai-hermes.env. Source that env file, then call by absolute path:
set -a; . "${HERMES_HOME:-$HOME/.hermes}/pai-hermes.env"; set +a
/usr/bin/python3 "$PAI_HERMES_ROOT/tools/cost_check.py" \
--cache "${PAI_USAGE_CACHE:-$HOME/.claude/MEMORY/STATE/usage-cache.json}" --voice
execute_code is the preferred execution path for cron invocations.
Caveats
- Schema/path drift — some canonical installs place 5h/7d fields at the top level (no
rate_limits wrapper) and store the cache at ~/.claude/MEMORY/STATE/usage-cache.json rather than the older ~/.claude/PAI/MEMORY/STATE/ path. cost_check.py handles both schemas; pass --cache explicitly if it reports 0% across the board. See references/usage-cache-schema.md.
- Empty
--voice stdout is the success path — all metrics within threshold. Only non-empty output signals an alert.
- Stale cache is itself alertable —
--voice emits a staleness warning when cache mtime >15 min old. Common; alert on it, do not treat as broken state.
- 5h/7d % from the Claude OAuth API rate-limits aggressively (5 reads before 429). Hourly cron is safe.
- Hermes own model usage (z.ai/GLM, OpenRouter, etc.) is NOT in Claude windows — separate spend.
- Quiet hours (22:00–07:00): run the read + snapshot but suppress
--voice/pai-pulse; log the decision.
- Audit: append metric JSON to
~/.hermes/state/pai-cost-snapshots.jsonl every run for a continuous burn-rate record.
- If
terminal returns pending_approval / pattern_key: "tirith:unknown", re-run via execute_code with subprocess.run([...], timeout=15) instead of retrying terminal unchanged.
References
references/usage-cache-schema.md — canonical cache path, current top-level schema, and stale-cache alert semantics.
references/tool-path.md — why cost_check.py lives outside the installed skill dir and how to invoke it via $PAI_HERMES_ROOT.
Cost
ZERO AI cost. File reads + JSON parsing + optional Pulse POST.
Triggers in Hermes natural language
- "how much have I used" → snapshot
- "am I close to limit" → threshold check, summarize
- "what's my burn rate" → trend from snapshots jsonl
- Pre-flight before
omc ralph etc. — silent unless threshold hit