From 81a64bfc8e254dd335c86cb07ca6b0686d25ead4 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Tue, 28 Jul 2026 23:03:31 -0700 Subject: [PATCH] The agent surface: usage-insight skill reads the state dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three layers, one source of truth: line 1 shows the numbers, the advisor row says the one sentence, and this skill carries the full conversation — should I start a heavy task, which account has headroom, what did I waste this week. It encodes the state-dir contract, the learned-forecast semantics, and the advisor's judgment rules (feasibility before advice, facts only while unlearned, staleness said out loud), and runs the same report/check subcommands instead of re-mining — so the layers cannot disagree. Install: cp -r skills/usage-insight ~/.claude/skills/ Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 16 +++++++ README.md | 19 ++++++++ docs/api/state-dir.md | 2 +- llms.txt | 1 + skills/usage-insight/SKILL.md | 85 +++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 skills/usage-insight/SKILL.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc9aec..27ee9a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## v0.22.0 — 2026-07-28 — the agent surface + +**New: `skills/usage-insight` — teach Claude Code to read its own +usage.** Three layers, one source of truth: line 1 shows the numbers, +the advisor row says the one sentence that matters, and the skill +carries the full conversation — "should I start a heavy task now?", +"which account has headroom?", "what did I waste this week?". Install +with `cp -r skills/usage-insight ~/.claude/skills/` and ask. + +The skill encodes the state-dir contract, the learned-forecast +semantics, and the advisor's judgment rules — feasibility before +advice, facts only while the ratio is unlearned, staleness said out +loud, fresh siblings only. It runs the same `report`/`check` +subcommands instead of re-mining, so all three layers always agree. +Docs-only release: no script changes, test count unchanged. + ## v0.21.0 — 2026-07-28 — the advisor, wired into your world **New: `statusline.sh check` — the advisor as an exit code.** The diff --git a/README.md b/README.md index f3f534f..a39e3f8 100644 --- a/README.md +++ b/README.md @@ -356,6 +356,25 @@ Run it bare and it summarizes the last session in the log. Window deltas are positive-delta sums, so a session that straddles a 5h reset still reports what it actually consumed. +## The agent surface + +Three layers, one source of truth: line 1 shows the numbers, line 2 +says the one sentence that matters, and for the full conversation — +"should I start a heavy task now?", "which account has headroom?", +"what did I waste this week?" — there's a skill that teaches Claude +Code itself to read the state dir: + +```bash +cp -r skills/usage-insight ~/.claude/skills/ +``` + +Then just ask. The skill knows the state-dir contract +(`docs/api/state-dir.md`), the learned-forecast semantics +(`pct_per_window`, weekday profile, prediction calibration), and the +advisor's judgment rules — including the important one: never advise +what the data can't back. It reads the same files and runs the same +`report`/`check` subcommands, so all three layers always agree. +
OAuth and API behavior Quota, profile, and extra-usage requests use Claude Code's OAuth credentials diff --git a/docs/api/state-dir.md b/docs/api/state-dir.md index da468bf..53e786d 100644 --- a/docs/api/state-dir.md +++ b/docs/api/state-dir.md @@ -7,7 +7,7 @@ is the ONLY writer; everything here is safe to read concurrently. - Contract version: **1** (bump on any breaking layout/field change; this file is the changelog) -- Synced with: statusline.sh v0.21.0 +- Synced with: statusline.sh v0.22.0 - Permissions: the script runs under `umask 077` — files are owner-only. Caches hold account PII (email, uuid, org names). diff --git a/llms.txt b/llms.txt index 8dd6980..e6e3e7c 100644 --- a/llms.txt +++ b/llms.txt @@ -39,3 +39,4 @@ Key facts for agents: ## Optional - [Site](https://thevibeworks.github.io/claude-code-statusline/): animated demo of the line +- [usage-insight skill](https://github.com/thevibeworks/claude-code-statusline/blob/main/skills/usage-insight/SKILL.md): teaches an agent to read the state dir and answer usage questions (install: `cp -r skills/usage-insight ~/.claude/skills/`) diff --git a/skills/usage-insight/SKILL.md b/skills/usage-insight/SKILL.md new file mode 100644 index 0000000..086cc96 --- /dev/null +++ b/skills/usage-insight/SKILL.md @@ -0,0 +1,85 @@ +--- +name: usage-insight +description: > + Answer Claude Code usage and quota questions from the statusline state + dir (~/.claude/statusline/): why the statusline is yellow/red, whether + to start a heavy task now, which account has headroom, what expired + unused this week, when a capped model comes back. Triggers on quota, + 5h/7d windows, rate limits, capacity planning, statusline questions, + "should I run this now", "which account", "what did I waste". +--- + +# Usage insight from the statusline state dir + +claude-code-statusline maintains a read-only-for-you state dir and +documents it as a contract (docs/api/state-dir.md in +https://github.com/thevibeworks/claude-code-statusline). This skill +teaches you to read it and answer usage questions conversationally — +the deep-dive version of what the advisor row says in one sentence. + +## Ground rules + +1. READ-ONLY. Never write, touch, or delete anything under + `~/.claude/statusline/`. The statusline is the only writer. +2. Account scoping: state for tagged accounts lives under + `~/.claude/statusline/accounts//`; the top level is the default + account. If `STATUSLINE_ACCOUNT` or `DEVA_AUTH_TAG` is set in the + environment, that names the current account. +3. Staleness: trust `fetched_at` (epoch seconds) in usage.cache. + Older than ~1h means no active session feeds that account — say the + numbers are stale instead of presenting them as now. +4. These files hold account PII (email, uuid, org). Quote numbers and + reset times to the user; do not echo emails/uuids unless asked. + +## What to read for which question + +| Question | Source | +|----------|--------| +| "Why is the line yellow/red?" / "what's my quota now?" | `usage.cache`: `five_hour.{utilization,resets_at}`, `seven_day.*`, `limits[]` (per-model weekly caps, `kind=weekly_scoped`) | +| "Should I start a heavy task now?" | `usage.cache` now + `forecast.cache` patterns (below) | +| "Which account has headroom?" | every `accounts/*/usage.cache`, compare `five_hour.utilization` and `fetched_at` freshness | +| "What did I waste?" / weekly retrospective | run `~/.claude/statusline.sh report [--days N]` — the reference consumer; don't re-mine by hand | +| "Anything I should know right now?" | run `~/.claude/statusline.sh check` — exit 0 calm / 1 opportunity / 2 pressure / 3 unknown | +| "What did that session cost me?" | `~/.claude/statusline.sh session-summary` (last session), or pipe `{"session_id":"..."}` | + +## Semantics crib (forecast.cache) + +```json +{"days_history": 21, "recent_24h": 14.2, + "pct_per_window": 11.83, + "weekday_profile": {"0": 5.1, "1": 27.3, "6": -1}} +``` + +- `weekday_profile`: learned percent-of-7d-quota burned per weekday + (0=Sun..6=Sat), EWMA half-life 14 days; `-1` = never observed. + Cold start below 14 `days_history` — say projections are unlearned. +- `pct_per_window`: the exchange rate — 7d percentage points one fully + burned 5h window costs THIS account. `-1` = unlearned. A week holds + roughly `100 / pct_per_window` full windows. +- usage.jsonl lines carry `predicted_end` (the projection made at + sample time): compare old predictions against what actually happened + before presenting the forecast as reliable. + +## Judgment rules (mirror the advisor; never advise what data can't back) + +- Feasibility before advice: with S% of the 7d window unused and T + hours to its reset, the burnable maximum is roughly + `pct_per_window x (T / 5h)` (capped by the current 5h window's own + headroom). If that is less than S, do NOT say "use it up" — say how + much expires no matter what. +- With `pct_per_window = -1`, state facts, not advice. +- A scoped limit (`limits[]`) at 100% means that model is unavailable: + the useful fact is its `resets_at`, not the percentage. +- 5h pressure with a reset < 30min away is self-healing — say "resets + in N minutes" instead of alarming. +- Recommending another account: only name siblings whose cache is + fresh (< 1h); an idle-looking stale account is unknown, not free. + +## Answer style + +Lead with the verdict ("yes, start it — 5h at 22% with 4h of window +left"), then the two or three numbers that justify it. Convert +percentages into work-terms using the exchange rate ("~49% expires +even at full burn — about 4.7 windows' worth"). Say when data is +stale, unlearned, or invisible (usage from other devices between +renders never reaches the log).