Statusline preview
Skill dox187/usage-aware-claude-statusline/.claude/skills/statusline-preview
Usage-aware status line for Claude Code: session & weekly rate-limit gauges with reset countdowns and a precise context-window meter, plus tokens, git & weather. Template-driven and extensible — set it up by chatting with Claude or via a TUI. Pure-stdlib Python, no pip install. macOS, Linux & Windows.
npx -y skills add dox187/usage-aware-claude-statusline --skill statusline-previewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Render a statusline config against sample data and show it as a terminal preview and/or export an SVG screenshot (the same style as examples/*.svg). Invoke when the user says things like "preview my statusline", "show me what it looks like", "render the statusline", "export an SVG of my bar", or "make a screenshot of the statusline".
SKILL.md
10.5 KB, as published. Nobody here has run it
statusline-preview
Render the statusline against fixed sample data so the user can SEE the result
without waiting for real git / weather / usage, and optionally export an SVG
screenshot that matches the look of examples/*.svg.
This skill is read-only. It never writes statusline_config.json. It only
shells out to the renderer with a chosen config and captures the colored output.
Use the statusline-config or statusline-theme skills to actually change the
config; use this one to look at the result.
What it produces
- A terminal preview: the real ANSI-colored status line printed to your terminal (truecolor). This is exactly what Claude Code would draw, but driven by deterministic sample data (sample git stats, sample weather, sample usage).
- An optional SVG screenshot written to a path you choose, in the same
visual style as the bundled
examples/*.svg(dark rounded card, Agave Nerd Font with a monospace fallback, truecolor spans, block / eighth-block gauge glyphs, emoji drawn as a single cell).
Files in this skill
render_demo.py— importsstatusline.pyas a module, monkeypatches the network/git helpers with believable sample values, feeds the canonical sample JSON on stdin, runs the renderer, and prints the ANSI bar. With--svg <path>it also hands the ANSI toansi2svg.py.ansi2svg.py— converts the captured ANSI (24-bit SGR runs) into an SVG that matches the visual style ofexamples/*.svg. Runnable standalone (python ansi2svg.py < ansi.txt > out.svg) and importable.assets/sample_input.json— the canonical Claude Code session JSON used for the render (so previews are deterministic and reproducible).
Both .py files are standard-library only (the project is dependency-free).
How to run it
The renderer lives at F:/ai/statusline/statusline.py (adjust the repo root if
the project lives elsewhere). render_demo.py finds it automatically: it sits
three directories above this skill (statusline-preview -> skills -> .claude ->
repo root), but you can also pass --statusline-dir.
0. Resolve the ACTIVE statusline first (do this every time)
"Preview my statusline" must show what Claude Code is REALLY running — usually
the deployed copy (e.g. ~/.claude/statusline.py), not the repo copy. Before
rendering, resolve the active target with the shared helper that lives in the
statusline-config skill (a sibling of this skill):
# from this skill's dir, the helper is ../statusline-config/statusline_io.py
python F:/ai/statusline/.claude/skills/statusline-config/statusline_io.py locate
It prints one JSON object, e.g.:
{"statusline_py": "...", "config_path": "...", "settings_json": "...",
"launcher": "...", "source": "pointer"|"settings"|"none",
"pointer_path": "...", "notes": "..."}
Use it as follows:
sourceis"pointer"or"settings"→ render that target: pass--config <config_path>and--statusline-dir <dir of statusline_py>.sourceis"none"→ ask the user where the active statusline / config is, then render with the path they give. For convenience you may also offer to save a pointer viastatusline_io.py save-pointer --statusline-py <P> --config <C>so future previews resolve instantly. (Likewise, ifsource == "settings"you may offer to save a pointer so future runs are instant — both are optional and not required just to preview.)
1. Preview the user's ACTIVE config (what's really running)
Point the renderer at the resolved config_path and its statusline directory —
this is the deployed/live config, rendered without modifying it.
# PowerShell — substitute the resolved paths from step 0
python F:/ai/statusline/.claude/skills/statusline-preview/render_demo.py --config <config_path> --statusline-dir <dir of statusline_py>
# bash / macOS / Linux
python3 /f/ai/statusline/.claude/skills/statusline-preview/render_demo.py --config <config_path> --statusline-dir <dir of statusline_py>
If uv is available you may use uv run … instead of python …; plain
python/python3 works because there are no third-party deps. (Running
render_demo.py with no --config/--statusline-dir falls back to the renderer
inferred from this skill's location and its normal STATUSLINE_CONFIG / repo
statusline_config.json resolution — use that only when locate cannot resolve
a target and the user points you at the repo copy on purpose.)
2. Preview a SPECIFIC config (e.g. an example or a candidate)
Use --config <path>. The skill sets STATUSLINE_CONFIG to that path for the
render only — the live file is untouched.
python F:/ai/statusline/.claude/skills/statusline-preview/render_demo.py --config F:/ai/statusline/examples/hero.json
3. Export an SVG screenshot
Add --svg <output-path>. You still get the terminal preview as well.
python F:/ai/statusline/.claude/skills/statusline-preview/render_demo.py --config F:/ai/statusline/examples/hero.json --svg F:/ai/statusline/examples/hero.svg
Useful flags:
--config <path>— config to render (default: the renderer's normal config resolution, i.e.STATUSLINE_CONFIGor the repostatusline_config.json).--svg <path>— also write an SVG screenshot to this path.--input <path>— use a different sample session JSON instead of the bundledassets/sample_input.json.--statusline-dir <path>— folder containingstatusline.py(default: the repo root inferred from this skill's location).--emoji-cells {1,2}— how many columns an emoji occupies for the SVG width math only (default 1, matching how the SVG draws emoji in a single cell).
Procedure for Claude
- Decide which config to render:
- "preview my statusline" / "show me what it looks like" → resolve the
active target first (see step 0): run
python <skills-dir>/statusline-config/statusline_io.py locate(=../statusline-config/statusline_io.pyfrom this skill), then pass the resolved--config <config_path>and--statusline-dir <dir of statusline_py>so you preview what is REALLY running, not the repo copy. Ifsource == "none", ask the user for the config path and render that — and you may offer to save a pointer viastatusline_io.py save-pointer --statusline-py <P> --config <C>so future previews resolve instantly (optional; previewing does not require it). - "render
examples/hero.json" / a candidate path → pass--config <path>directly (nolocateneeded; the user named the file).
- "preview my statusline" / "show me what it looks like" → resolve the
active target first (see step 0): run
- Run
render_demo.pywith the chosen flags. Show the terminal output to the user (it is real ANSI — your terminal renders the colors). - If the user asked for a screenshot / SVG ("export an SVG", "make a
screenshot"), add
--svg <path>, pick a sensible output path (default toexamples/<name>.svgwhen regenerating an example, otherwise ask), and run again. Tell the user where the SVG was written. - Mention the rendering assumptions when relevant: the SVG targets Agave Nerd
Font (falling back to a generic monospace), draws emoji as a single
cell, and uses a fixed monospace cell grid — matching the visual style of
the existing
examples/*.svg(interior baselines can differ by ~0.1px due to rounding, which is imperceptible). The preview uses sample git/weather/usage data, not the user's real values, so countdowns and stats are illustrative.
Notes
- Sample data baked into
render_demo.py: weather is a believable partly-cloudy day with sunrise/sunset computed for today (so{sun}resolves correctly), usage issession 41%/week 63%with reset times computed at runtime (~3h and ~2d out, so the countdowns look real), and git ismainwith+128 / -34. The session JSON (model, version, context %, tokens) comes fromassets/sample_input.json. - Empty lines render nothing (the renderer skips blank rows), so a config that
only defines
line1produces a single-line preview and a single-line SVG. - English only. Standard library only.
Previewing the status-page indicator ({status} / {status_header})
{status}, {status_icon} and {status_header} render EMPTY unless an incident
is currently active, so a normal preview of a status config shows nothing for
those lines — the renderer reads the live incident cache at
~/.claude/status_cache.json (refreshing it from status.claude.com only when
it's stale). To preview them with a guaranteed active incident without
touching the user's real cache, point HOME/USERPROFILE at a throwaway dir
that holds a fake cache, then render as usual:
# 1. throwaway home with a fake ACTIVE incident cache (PowerShell)
$home2 = "$env:TEMP/sl-status-preview"
New-Item -ItemType Directory -Force "$home2/.claude" | Out-Null
$now = [int][double]::Parse((Get-Date -UFormat %s))
@"
{"ts": $now, "etag": null, "incidents": [
{"title": "Elevated API error rates",
"link": "https://status.claude.com/incidents/preview-sample",
"status": "investigating", "label": "Investigating",
"text": "We are investigating elevated error rates on the API.",
"when": "preview", "pub_date": "", "pub_ts": $now,
"state": "incident", "emoji": "🔍", "updates": 1}]}
"@ | Set-Content -Encoding utf8 "$home2/.claude/status_cache.json"
# 2. render with HOME/USERPROFILE redirected to the throwaway home
$env:HOME = $home2; $env:USERPROFILE = $home2
python F:/ai/statusline/.claude/skills/statusline-preview/render_demo.py --config F:/ai/statusline/examples/status.json --svg F:/ai/statusline/examples/status.svg
This works because statusline.py resolves its STATUS_CACHE path from the
home directory at import time — so the override must be set before the
python process starts (a subprocess/new shell, not from inside the renderer).
Keep ts fresh (within the 120s cache TTL) so get_incidents() returns the
cache as-is instead of hitting the network, and pub_ts fresh so the incident
passes the config's max_age_hours filter. state must be "incident" (or
"maintenance" with include_maintenance: true). The bundled
examples/status.svg was generated exactly this way. The user's real
~/.claude/status_cache.json is never read or written.