/tmck-code-statusline
Edit the Claude Code statusline renderer safely. Use when touching claude/yas/**/*.py (the yas package), claude/statusline_command.py (the entry shim), claude/mon.py, or related tests under test/. Covers the layered renderer (GradientEngine / BorderRenderer / Renderer), the
$ npx -y skills add tmck-code/yet-another-statusline --skill tmck-code-statusline --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/tmck-code-statusline
Context preview
The summary Claude sees to decide when to auto-load this skill.
Edit the Claude Code statusline renderer safely. Use when touching claude/yas/**/*.py (the yas package), claude/statusline_command.py (the entry shim), claude/mon.py, or related tests under test/. Covers the layered renderer (GradientEngine / BorderRenderer / Renderer), the
SKILL.md
tmck-code-statusline.SKILL.mdname: tmck-code-statusline
description: Edit the Claude Code statusline renderer safely. Use when touching claude/yas/**/*.py (the yas package), claude/statusline_command.py (the entry shim), claude/mon.py, or related tests under test/. Covers the layered renderer (GradientEngine / BorderRenderer / Renderer), the SessionView gather seam (yas/info/__init__.py), the LayoutSpec/RowSpec layout pipeline, record_tick/TickRecord, Nerd Font PUA glyph hazards, border/elbow column math, and the demo-based visual check.
Statusline
The statusline renderer is a single-pass terminal painter with hand-tuned column math. Most bugs here are silent — wrong by one column, invisible icon, dropped byte through an Edit round-trip. This skill exists to make those bugs loud.
Architecture map
`claude/statusline_command.py` is a 4-line shim into the **`yas`** package under `claude/yas/` (`app.py`/`layout.py`/`renderer.py`/… at top level, `info/` for data sources, `render/` for pure painting/maths). Full per-module map, entry points, and the "where to make a change" table live in [`ARCHITECTURE.md`](ARCHITECTURE.md) — read it before adding a module, a data source, or a new row/border/gradient kind; skip it for a same-module tweak.
Pre-edit checklist
Run all four before editing:
1. **Read `CONTEXT.md`** at repo root. The terms Billed Input, Cache Read, Output, Day Total, Context Window Size, Compaction-Risk Zone, Five-Hour Limit, Seven-Day Limit are canonical — don't rename or alias them in code without a paired update. 2. **Catalogue PUA glyphs on touched lines.** Scan the package (glyphs can appear in any module, though most are hoisted into `constants.py`):
python3 -c "
import sys
for path in sys.argv[1:]:
for ln, line in enumerate(open(path), 1):
for c in line:
cp = ord(c)
if 0xE000 <= cp <= 0xF8FF or 0xF0000 <= cp <= 0xFFFFD:
print(f'{path}:{ln} U+{cp:05X} {c!r}')
" claude/yas/*.py claude/yas/info/*.py claude/yas/render/*.pyAny hit on a line you plan to Edit triggers the **PUA refactor rule** below. 3. **Baseline tests**: `make test` (or `uv run pytest -q`). Note pass count. **On Android (Termux)** `uv run`/`make test` is unavailable — activate the prebuilt venv and run pytest directly:
. ~/.uvenv/bin/activate
pytest -n 4 test/
4. **Baseline demo**: `make demo` (or `make statusline/test`, both run `uv run python ops/demo.py`). It animates 60 frames in place via cursor escapes; eyeball the final frame and the elbow alignment as it crosses layout thresholds (narrow → medium → wide on `$COLUMNS`). For static snapshot images, `make demo/img` (writes scenario PNGs into `demo/`, honours `COLUMNS=`). For a single piped frame when you need stdout, render one directly: `COLUMNS=160 uv run python claude/statusline_command.py < ops/session-info-example.json` (no transcript-derived rows; enough for border math). For a precise, diff-able baseline instead of eyeballing colour, capture the snapshots as ANSI-stripped text via the **yas-demo-text** skill: `make demo/img && .claude/skills/yas-demo-text/scripts/demo-text.sh && cp -r demo/text /tmp/yas-base`.
PUA refactor rule (mandatory before editing)
Nerd Font icons in this repo live in the Unicode Private Use Area (U+E000–U+F8FF and U+F0000–U+FFFFD). Literal PUA glyphs in source are invisible in many editors, render as `□` in others, and **get dropped through chat/agent round-trips** — which makes `Edit.old_string` matching fail with a stale-looking "string to replace not found" error.
If a line you need to Edit contains a raw PUA glyph, **hoist the glyph to a named constant in `constants.py` first**, then Edit. No exceptions.
Convention (matches the existing block in `constants.py`):
# Nerd Font Private Use Area glyphs. Encoded as escapes so Edit, diff, and
# chat round-trips never lose the bytes. Render only in a Nerd-Font-capable
# terminal.
ICON_COST = '\uefc8' # nf-md currency-usd (cost row)
ICON_TOK_RATE = '\U000f18a7' # nf-md gauge (t/m rate label)
GLYPH_MODEL = '\U000f08b9' # nf-md monitor-dashboard (model row)
GLYPH_THINKING = '\U000f1a53' # nf-md brain (thinking indicator)
Import the constant where needed (`from yas.constants import GLYPH_MODEL`) and reference it in f-strings: `f'{model_clr}{GLYPH_MODEL} {model_name}...'`. Note that `Renderer.ICON_PATH` holds a *colour code*, not a glyph — don't reuse that namespace for glyphs. New glyph constants go in `constants.py` alongside `ICON_COST`/`GLYPH_MODEL`.
Runtime cost is **zero** — `'\uefc8'` (in source) and the literal glyph compile to the identical `str` object; CPython interns and the `.pyc` cache eliminates parse cost after first load.
Fallback when refactor isn't feasible mid-task
If the line has a PUA glyph and you genuinely can't refactor first (e.g., user is mid-edit and asked for one surgical change), use a Bash heredoc with `python3` that reads, `str.replace`s, and writes. Python preserves the bytes exactly:
python3 << 'PY'
path = 'claude/yas/renderer.py'
with open(path) as f:
s = f.read()
old = "...exact old text with raw glyph copied through Read...\n"
new = "...replacement...\n"
assert old in s, 'old not found'
with open(path, 'w') as f:
f.write(s.replace(old, new, 1))
PYThis works because `Read` preserves the bytes when it loads them into your context, even when subsequent `Edit` calls can't transmit them through `old_string`.
Rendering invariants (silent-bug cheat-sheet)
These are the things pytest won't catch — get them wrong and the box draws crooked.
Width math
- **Never** use `len()` for column math. Use `_visible_width` (`render/text.py`) — it strips ANSI escapes via `_ANSI_RE` (`constants.py`) and counts wide chars (BMP emoji `0x1F300–0x1FAFF`) as 2.
- Nerd Font PUA chars count as width 1. Correct in a Nerd-Font terminal; would be wrong el
Read more
name: tmck-code-statusline description: Edit the Claude Code statusline renderer safely. Use when touching claude/yas/**/*.py (the yas package), claude/statusline_command.py (the entry shim), claude/mon.py, or related tests under test/. Covers the layered renderer (GradientEngine / BorderRenderer / Renderer), the SessionView gather seam (yas/info/__init__.py), the LayoutSpec/RowSpec layout pipeline, record_tick/TickRecord, Nerd Font PUA glyph hazards, border/elbow column math, and the demo-based visual check.
Statusline
The statusline renderer is a single-pass terminal painter with hand-tuned column math. Most bugs here are silent — wrong by one column, invisible icon, dropped byte through an Edit round-trip. This skill exists to make those bugs loud.
Architecture map
`claude/statusline_command.py` is a 4-line shim into the **`yas`** package under `claude/yas/` (`app.py`/`layout.py`/`renderer.py`/… at top level, `info/` for data sources, `render/` for pure painting/maths). Full per-module map, entry points, and the "where to make a change" table live in [`ARCHITECTURE.md`](ARCHITECTURE.md) — read it before adding a module, a data source, or a new row/border/gradient kind; skip it for a same-module tweak.
Pre-edit checklist
Run all four before editing:
1. **Read `CONTEXT.md`** at repo root. The terms Billed Input, Cache Read, Output, Day Total, Context Window Size, Compaction-Risk Zone, Five-Hour Limit, Seven-Day Limit are canonical — don't rename or alias them in code without a paired update. 2. **Catalogue PUA glyphs on touched lines.** Scan the package (glyphs can appear in any module, though most are hoisted into `constants.py`):
python3 -c "
import sys
for path in sys.argv[1:]:
for ln, line in enumerate(open(path), 1):
for c in line:
cp = ord(c)
if 0xE000 <= cp <= 0xF8FF or 0xF0000 <= cp <= 0xFFFFD:
print(f'{path}:{ln} U+{cp:05X} {c!r}')
" claude/yas/*.py claude/yas/info/*.py claude/yas/render/*.pyAny hit on a line you plan to Edit triggers the **PUA refactor rule** below. 3. **Baseline tests**: `make test` (or `uv run pytest -q`). Note pass count. **On Android (Termux)** `uv run`/`make test` is unavailable — activate the prebuilt venv and run pytest directly:
. ~/.uvenv/bin/activate pytest -n 4 test/
4. **Baseline demo**: `make demo` (or `make statusline/test`, both run `uv run python ops/demo.py`). It animates 60 frames in place via cursor escapes; eyeball the final frame and the elbow alignment as it crosses layout thresholds (narrow → medium → wide on `$COLUMNS`). For static snapshot images, `make demo/img` (writes scenario PNGs into `demo/`, honours `COLUMNS=`). For a single piped frame when you need stdout, render one directly: `COLUMNS=160 uv run python claude/statusline_command.py < ops/session-info-example.json` (no transcript-derived rows; enough for border math). For a precise, diff-able baseline instead of eyeballing colour, capture the snapshots as ANSI-stripped text via the **yas-demo-text** skill: `make demo/img && .claude/skills/yas-demo-text/scripts/demo-text.sh && cp -r demo/text /tmp/yas-base`.
PUA refactor rule (mandatory before editing)
Nerd Font icons in this repo live in the Unicode Private Use Area (U+E000–U+F8FF and U+F0000–U+FFFFD). Literal PUA glyphs in source are invisible in many editors, render as `□` in others, and **get dropped through chat/agent round-trips** — which makes `Edit.old_string` matching fail with a stale-looking "string to replace not found" error.
If a line you need to Edit contains a raw PUA glyph, **hoist the glyph to a named constant in `constants.py` first**, then Edit. No exceptions.
Convention (matches the existing block in `constants.py`):
# Nerd Font Private Use Area glyphs. Encoded as escapes so Edit, diff, and # chat round-trips never lose the bytes. Render only in a Nerd-Font-capable # terminal. ICON_COST = '\uefc8' # nf-md currency-usd (cost row) ICON_TOK_RATE = '\U000f18a7' # nf-md gauge (t/m rate label) GLYPH_MODEL = '\U000f08b9' # nf-md monitor-dashboard (model row) GLYPH_THINKING = '\U000f1a53' # nf-md brain (thinking indicator)
Import the constant where needed (`from yas.constants import GLYPH_MODEL`) and reference it in f-strings: `f'{model_clr}{GLYPH_MODEL} {model_name}...'`. Note that `Renderer.ICON_PATH` holds a *colour code*, not a glyph — don't reuse that namespace for glyphs. New glyph constants go in `constants.py` alongside `ICON_COST`/`GLYPH_MODEL`.
Runtime cost is **zero** — `'\uefc8'` (in source) and the literal glyph compile to the identical `str` object; CPython interns and the `.pyc` cache eliminates parse cost after first load.
Fallback when refactor isn't feasible mid-task
If the line has a PUA glyph and you genuinely can't refactor first (e.g., user is mid-edit and asked for one surgical change), use a Bash heredoc with `python3` that reads, `str.replace`s, and writes. Python preserves the bytes exactly:
python3 << 'PY'
path = 'claude/yas/renderer.py'
with open(path) as f:
s = f.read()
old = "...exact old text with raw glyph copied through Read...\n"
new = "...replacement...\n"
assert old in s, 'old not found'
with open(path, 'w') as f:
f.write(s.replace(old, new, 1))
PYThis works because `Read` preserves the bytes when it loads them into your context, even when subsequent `Edit` calls can't transmit them through `old_string`.
Rendering invariants (silent-bug cheat-sheet)
These are the things pytest won't catch — get them wrong and the box draws crooked.
Width math
- **Never** use `len()` for column math. Use `_visible_width` (`render/text.py`) — it strips ANSI escapes via `_ANSI_RE` (`constants.py`) and counts wide chars (BMP emoji `0x1F300–0x1FAFF`) as 2.
- Nerd Font PUA chars count as width 1. Correct in a Nerd-Font terminal; would be wrong el
🌈 Check out the official landing page here: YAS! Yet Another Statusline Most common form is displaying the first few rows, which include the loaded plugins & skills. Extra sections appear below them as needed
Other skills on yas.
- /yas-demo-text
Convert `make demo/img` statusline snapshots into ANSI-stripped plain text for diffing and PR embedding. Use when comparing statusline renders before/after a change, producing a text representation of a demo scenario, or preparing before/after statusline output for a pull
Open skill - /yas-pr-screenshots
Generate before/after PNG screenshots for a YAS branch's rendering changes, push them to the yas-pr-screenshots repo, and hand back a markdown before/after table for the PR description. Use when the user wants real image screenshots (not ANSI-stripped text) attached to a YAS
Open skill - /yas-pr
Assemble a pull request that follows this repo's PR template, then open it as a draft. Use when the user wants to open, create, submit, or raise a PR for the current branch.
Open skill - /config
Reconfigure yet-another-statusline — re-runs the interactive install wizard (glyph mode, theme, labels, token soft-limit, and Python version) against the already-installed plugin and re-wires settings.json, without re-registering the marketplace or reinstalling the plugin. Use
Open skill - /init
Wire yet-another-statusline into Claude Code — writes statusLine.command to settings.json in CLAUDE_CONFIG_DIR (default ~/.claude/). Run once after plugin install, and again after every upgrade to update the versioned path.
Open skill - /uninstall
Unwire yet-another-statusline from Claude Code — removes statusLine.command from settings.json in CLAUDE_CONFIG_DIR (default ~/.claude/) and deletes the renderer's runtime state. Run before (or after) `claude plugin uninstall yas`, which only deletes the plugin cache and leaves
Open skill

