v3/docs/adr/ADR-379-statusline-optional-usage-segments.md
/home/ruvultra/projects/ruflo/image.png — a screenshot of a
statusline (project july-genesis, not a ruflo repo) showing a header row with
Opus 5 · eff:xhigh · Projects/july-genesis · main ✚19 · 24%/(3M) · session 0% · week 51% · $49.48 · 12:27pm PT/3:27pm ET · /rc, followed by four rotating tip/quote lines (a .gitignore
tip, a "what should I do next?" prompt, a "staging" definition, and a John Doerr quote)..claude/helpers/statusline.cjs renders a deliberately 3-line layout, per its own doc
comment (lines 802–806):
Line 1 — Header (RuFlo version · git · model · timing · context · cost)
Line 2 — Compressed ops (Swarm · Hooks · 🧠 · 💾 · Health)
Line 3 — Promo / disclosure row (funnel surface, ADR-301)
That cap is load-bearing, not arbitrary — the comment explains it's sized to "fit Claude Code's
visible statusline area (line 4+ gets replaced by the system guidance / input prompt line)."
Line 3 already rotates through four content kinds (disclosure, promotional, educational,
insight — see getPromoRow()), server-selected by the CLI's funnel/promo subsystem on a 20s
rotation slot. This is functionally similar to the tip lines in the reference screenshot, but
today it is one line at a time, not several simultaneous lines.
The file already has a working precedent for optional segments: CONFIG.hideCost /
RUFLO_STATUSLINE_HIDE_COST lets a user remove the cost segment from Line 1 without touching
code, and RUFLO_FUNNEL=0 disables Line 3 entirely. Context usage (ctxInfo.usedPct), by
contrast, has no hide toggle today — it renders unconditionally whenever
getContextFromStdin() returns a positive percentage.
Two segments visible in the reference screenshot have no equivalent in this file at all:
session 0% / week 51% — usage against Anthropic's 5-hour and 7-day (weekly) rate
limits. getStdinData() currently reads model, context_window, and cost from the
Claude Code stdin payload; nothing here reads or expects a session/week usage field.eff:xhigh — the active reasoning-effort level. Also absent from getStdinData() and
from every function in this file.Before proposing a schema, search_ruvnet was queried against the decompiled Claude Code
research corpus (ruvector/docs/research/claude-code-rvsource/07-context-and-session-management.md,
built from reverse-engineering the actual Claude Code CLI) and against open-claude-code's
ADR-002 fidelity gap-analysis. Neither documents a session-usage or week-usage stdin field.
That research doc is detailed on context windows, compaction, session persistence, and prompt
caching, but has no mention of a 5-hour/weekly rate-limit percentage being exposed to
statusline scripts. This does not prove the field doesn't exist in a Claude Code version newer
than that research pass — it means this ADR cannot assume a concrete field name or shape,
and implementation must start with a verification spike rather than a schema guess (see
Decision §2 and Implementation Plan Phase 0).
Add each of the reference screenshot's extra segments as an independently optional piece
of the existing 3-line design, following the hideCost precedent exactly (additive CONFIG
field + env var, never a required behavior change), rather than redesigning the layout. Where
the underlying data source is unconfirmed (session %, week %, effort), default the segment to
off until a spike confirms how to source it — this repo does not ship guessed/placeholder
data in a statusline that people trust for real numbers (cost, security status, etc. are all
sourced from real state elsewhere in this file; a fabricated usage percentage would break that
trust).
Add CONFIG.hideContext / RUFLO_STATUSLINE_HIDE_CONTEXT, mirroring hideCost exactly:
hideContext: /^(1|true|yes|on)$/i.test(process.env.RUFLO_STATUSLINE_HIDE_CONTEXT || ''),
Guard the existing render block (statusline.cjs:827) with if (!CONFIG.hideContext && ctxInfo && ctxInfo.usedPct > 0). Default shown (false), so existing behavior is unchanged for
everyone who doesn't set the var — this is a pure opt-out addition.
These cannot be implemented today without knowing where the numbers come from. Phase 0 (Implementation Plan) determines which of the following is true, in this preference order:
data.usage, data.rate_limits,
data.session_usage / data.week_usage — verify against a live payload dump, don't guess
in code)./usage-equivalent CLI
subcommand, or a file under ~/.claude/) that this script would need to shell out to or
read, similar to how getPkgVersion() already probes multiple candidate paths.~/.claude/projects/<hash>/*.jsonl, already known to exist per
the Session Persistence research cited above) against Anthropic's published 5-hour/weekly
window semantics. This is the most expensive path and should only be taken if 1 and 2 are
both dead ends.Once a real source is confirmed, add getSessionUsageFromStdin() / getWeekUsageFromStdin()
(or the equivalent for whichever source won the spike) following the exact null-safe pattern
getContextFromStdin() already uses — return null on any missing/malformed data, never
throw. Render behind two new flags, defaulting to hidden:
hideSessionUsage: !/^(1|true|yes|on)$/i.test(process.env.RUFLO_STATUSLINE_SHOW_SESSION_USAGE || ''),
hideWeekUsage: !/^(1|true|yes|on)$/i.test(process.env.RUFLO_STATUSLINE_SHOW_WEEK_USAGE || ''),
Note the inverted polarity versus hideCost/hideContext — those hide something known-good by
default-on; these are opt-in (default-off) because, unlike cost/context, there is no
existing confirmed data path, so shipping "on by default" risks showing a stale/wrong number
until the spike lands and the feature is validated end-to-end for at least one release.
Color threshold convention should match the existing context-percentage bands
(>=90 red, >=70 yellow, else green — statusline.cjs:828) for visual consistency across
all three usage segments.
eff:xhigh needs its own verification: does Claude Code's stdin payload carry the active
effort level anywhere under data.model or a sibling field? If yes, add
getEffortFromStdin() next to getModelFromStdin(); render behind
RUFLO_STATUSLINE_SHOW_EFFORT (default off, same reasoning as §2). If the effort level is not
in the stdin payload at all, this segment is descoped from this ADR — do not infer it from
environment variables or config files that could drift from the actual runtime effort.
The reference screenshot shows four simultaneous tip/quote lines, which conflicts with this file's own documented constraint that line 4+ gets silently replaced by Claude Code's system UI. Do not change the default line count. Instead:
RUFLO_STATUSLINE_EXTRA_TIP_LINES (integer, default 0,
clamp to 0–3) that appends up to N additional lines below Line 3, sourced from a small,
local, static TIP_POOL array shipped in this file (git/workflow tips and quotes, in the
spirit of the reference screenshot's .gitignore / "staging" / John Doerr lines) — not
the funnel/promo server payload, since these are meant to be plain educational/static content,
not promotional or personalized.0 means some or all of
those lines may be visually overwritten by Claude Code's own input-prompt UI depending on
terminal height and Claude Code version — this is a known, accepted tradeoff for users who
explicitly opt in, not a bug to chase.TIP_POOL using the same 20s-slot cadence already established for Line 3
(ROTATION_SLOT_MS, referenced in the existing comment at statusline.cjs:61-69) so the
extra lines feel consistent with the existing rotation rather than introducing a second timing
system.CONFIG, env-var gated, and defaults to preserving current
output for anyone who sets nothing.getContextFromStdin()'s null-safe shape: return null/false
on anything missing or malformed, never throw — consistent with getPromoRow()'s own
try { … } catch { return null; } wrapper, which exists specifically so "the promo row must
never break the statusline" (statusline.cjs:1037-1039). The same invariant applies to every
segment added by this ADR.hideCost,
identityMode, RUFLO_FUNNEL); forking a second file duplicates the git/cost/security
plumbing this one already does carefully (single execSync call, 2s timeouts, shared cache)
for no real benefit.null forever (because the real field, if any, has a different name) would look like
a shipped feature that quietly never works — worse than not having it, because it's not
discoverable as broken.CONFIG/env-var surface area to document and keep consistent (inverted default polarity
between the "hide a known-good thing" group and the "opt into an unconfirmed thing" group is
a deliberate but easy-to-forget asymmetry — call it out in the code comment, not just here).RUFLO_STATUSLINE_EXTRA_TIP_LINES users may see their own terminal visually clip/overwrite
the extra lines depending on Claude Code version and terminal height — accepted tradeoff, but
worth a one-line note in ruflo doctor output or docs so it isn't reported as a bug.cat what this script actually receives on stdin during a live session) on a current Claude
Code version and grep it for anything resembling session/week usage or an effort field.
Cross-check against Claude Code's own /usage-style output if one exists. This phase's output
is a yes/no answer per segment plus, if yes, the exact field path — not code.RUFLO_STATUSLINE_HIDE_CONTEXT per Decision §1.
Independent of Phase 0; can ship immediately.TIP_POOL + RUFLO_STATUSLINE_EXTRA_TIP_LINES,
independent of Phase 2.RUFLO_STATUSLINE_* /
RUFLO_FUNNEL docs (wherever those are currently documented for end users), including the
visible-area tradeoff warning for Phase 3.~/.claude/projects/*/*.jsonl
accurate enough to be trustworthy, or does it risk showing a confidently-wrong number (arguably
worse than showing nothing)?.claude/statusline-tips.json), or does that add more surface area than the feature is worth?.claude/helpers/statusline.cjs — existing 3-line design doc comment (lines 802–806),
CONFIG.hideCost precedent (lines 34–42), getContextFromStdin() (lines 598–604),
getPromoRow() and its rotation-slot comment (lines 61–69, 937–1039)ruvector/docs/research/claude-code-rvsource/07-context-and-session-management.md —
decompiled Claude Code research; cited as the negative-evidence source for "no documented
session/week usage stdin field" in the Context section aboveopen-claude-code/docs/adr/ADR-002-path-to-100-percent.md — independent Claude Code
reimplementation's own feature-gap analysis, also silent on a session/week usage field