🌈 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
Requires Python 3.10+, and a Nerd Font to render the icons.
curl -fsSL https://raw.githubusercontent.com/tmck-code/yet-another-statusline/main/ops/install.sh | bashOr install manually:
claude plugin marketplace add tmck-code/yet-another-statusline
claude plugin install yas@yet-another-statusline
claude -p "/yas:init"If you need to install non-interactively (e.g. in CI/docker)
curl -fsSL https://raw.githubusercontent.com/tmck-code/yet-another-statusline/main/ops/install.sh | YAS_NO_TTY=1 bash
# install with specific python version e.g. 3.15
curl -fsSL https://raw.githubusercontent.com/tmck-code/yet-another-statusline/main/ops/install.sh | YAS_NO_TTY=1 YAS_PYTHON=3.15 bashRun /yas:config any time to re-run the wizard against the already-installed
plugin — switch theme/glyph mode, toggle labels, change the soft limit, or move
to Python 3.15. It re-wires settings.json without re-registering the
marketplace or reinstalling the plugin.
A dummy session to demonstrate the layout:
The statusline also renders differently according to available width
| mode | width | screenshot |
|---|---|---|
| "medium" | <=80 pixels | ![]() |
| "narrow" | <=55 pixels | ![]() |
Every configurable knob resolves through one fixed precedence chain (highest wins):
CLI flag → canonical YAS_* env var → legacy-alias env var → yas.toml → built-in default
The first source in that chain that is present and valid wins; an absent or
invalid source falls through to the next (an empty-string env var counts as
absent). Canonical YAS_* env vars always win over their deprecated legacy
aliases when both are set — the aliases keep working but are deprecated.
| Knob | Env var | yas.toml key |
Default | Legacy alias |
|---|---|---|---|---|
max_width |
YAS_MAX_WIDTH |
[layout].max_width |
140 |
— |
full_width |
YAS_FULL_WIDTH |
[layout].full_width |
false |
— |
soft_limit |
YAS_SOFT_LIMIT |
[tokens].soft_limit |
150000 |
— |
token_window |
YAS_TOKEN_WINDOW |
[tokens].token_window |
60 |
STATUSLINE_TOKEN_WINDOW |
theme |
YAS_THEME (also --theme CLI) |
[appearance].theme |
claude-dark |
CLAUDE_STATUSLINE_THEME |
bg_shift |
YAS_BG_SHIFT (also --bg-shift CLI) |
[appearance].bg_shift |
warm |
— |
glyph_mode |
YAS_GLYPH_MODE (also --glyph-mode CLI) |
[appearance.glyphs].mode |
nerdfont |
— |
single_width |
YAS_GLYPH_SINGLE_WIDTH (also --glyph-single-width CLI) |
[appearance.glyphs].single_width |
false |
— |
context_state |
YAS_CONTEXT_STATE |
[context].state |
false |
— |
context_labels |
YAS_CONTEXT_LABELS |
[context].labels |
Smart,Coasting,Foggy,Cooked,Dumb |
— |
context_thresholds |
YAS_CONTEXT_THRESHOLDS |
[context].thresholds |
25,50,70,90 |
— |
show_render_time |
YAS_SHOW_RENDER_TIME |
[layout].show_render_time |
false |
— |
theme— 14 built-in themes; unknown or unset falls back toclaude-dark:- Dark:
claude-dark,catppuccin-mocha,dracula,gruvbox-dark,nord,one-dark,solarized-dark,tokyo-night,palenight - Light:
claude-light,catppuccin-latte,gruvbox-light,one-light,solarized-light
- Dark:
bg_shift—warmorcool.glyph_mode— all four modes preserve column geometry; an unknown value falls back tonerdfont:nerdfont— default; full fidelity, needs a Nerd Font.ascii— every non-ASCII glyph → width-1 ASCII; maximum compatibility.unicode— only Nerd Font PUA icons → non-PUA Unicode; keeps box/block/arrow glyphs.github— GitHub-paste-safe: folds every glyph a browser renders double-wide (the box-drawing frame, block/sparkline ramp, and EAW-ambiguous punctuation/icons) to a width-1, EAW-narrow/ASCII stand-in, so a render stays column-aligned when pasted into a GitHub markdown code block.
single_width— orthogonal boolean that folds double-width dynamic content (wide emoji, CJK in branch names/paths) to width-1; combinable with anyglyph_mode. The statusline's own glyphs are already width-1, so column geometry is preserved.full_width— whentrue, makes the box fill the terminal and ignoremax_width.show_render_time— whentrue, annotates the bottom-right border with the previous run's wall-clock render time (e.g.…47.2ms──╯). Off by default; each run shows the prior run's timing, so it is blank on a session's first render.- CLI flags —
--theme NAME/--bg-shift DIRalso accept the--theme=NAME/--bg-shift=DIRform. Pass them in thestatusLine.commandof your~/.claude/settings.json. - Legacy theme file —
~/.claude/statusline-theme(contents = a theme name) still works as the lowest-priority theme fallback, below[appearance].theme.
context_state adds a morphing word to the context line that names how full the
context window is — Smart → Coasting → Foggy → Cooked → Dumb — so you can read
the state at a glance instead of doing percentage math. It is off by default;
enable it with YAS_CONTEXT_STATE=1 or [context].state = true.
The word is tinted with the same threshold colour as the context bar and sits just before it; in a narrow box it sheds first (the bar and percentage stay).
context_labels— exactly 5 comma-separated words (Smart,Coasting,Foggy,Cooked,Dumbby default).context_thresholds— exactly 4 strictly-ascending integers in1..99(25,50,70,90by default), the start percentage of bands 2–5.
The percentage driving the word is YAS's soft-limit fill ratio (the same
basis as the context bar), so the word and the bar always agree — the word turns
Dumb exactly as the bar fills toward the compaction soft_limit.
Credit: the state-word idea and its default labels/thresholds are ported from Dumbometer by Maximo Correa Rosas (MIT). See
NOTICE. Dumbometer maps the word to the full context window; YAS maps it to the soft-limit fill ratio for bar consistency.
yas.toml lives in CLAUDE_CONFIG_DIR (defaults to ~/.claude/). It is not
auto-created — its absence simply means all-defaults — and /yas:init never
writes it. See yas.example.toml for a fully-commented
template; copy it to ~/.claude/yas.toml and uncomment what you want.
[layout]
max_width = 140
[tokens]
soft_limit = 150000
token_window = 60
[appearance]
theme = "claude-dark"
bg_shift = "warm"
[appearance.glyphs]
mode = "nerdfont"
single_width = false
[context]
state = false
labels = ["Smart", "Coasting", "Foggy", "Cooked", "Dumb"]
thresholds = [25, 50, 70, 90]
yas.tomlrequires Python 3.11+ — it is parsed with the stdlibtomllib. On Python 3.10 the file is silently skipped; environment variables work on every Python version.
Bad config never crashes the statusline. A malformed yas.toml is ignored
wholesale, and a single bad / out-of-range / wrong-type value drops only that
one knob back to its default. When any yas.toml value is rejected, a compact
warning row — ⚠ yas.toml: N values ignored (...) — appears at the bottom of
the box listing the rejected knob names. Detailed per-value reasons go to stderr
only when YAS_DEBUG is set.
Beyond the global [tokens].soft_limit, you can declare per-model overrides as
an inline array under [tokens]:
[tokens]
model = [
{ match = "opus", soft_limit = 200000 }, # the whole Opus family
{ match = "opus-4-8[1m]", soft_limit = 1000000 }, # 1M-context variant (longer match wins)
]matchis a case-insensitive plain substring (no glob/regex), tested against the model's id and display name.- When multiple entries match, the longest
matchwins; ties break by array order (first wins). If no entry matches, the globalsoft_limitis used. So to single out a variant from its family, give the variant the longer, more specificmatch(above,opus-4-8[1m]outranksopusfor the 1M model). - A matching per-model override beats the global
soft_limitfrom any source — including theYAS_SOFT_LIMITenvironment variable. This is the one documented exception to the "env beatsyas.toml" rule: specificity beats source precedence (there is intentionally no per-model env var). It lets you raise the compaction-risk threshold for a 1M-context model variant distinctly from the rest of its family.
| var | default | description |
|---|---|---|
CLAUDE_CONFIG_DIR |
~/.claude |
base dir for config/state files (yas.toml, theme file, width file, token-rate log, output payloads) |
YAS_DEBUG |
(unset) | when set, prints detailed per-value config-rejection reasons to stderr |
COLUMNS |
(unset) | terminal-width fallback when tmux / width-file detection fail |
Width is detected by the first source that returns a positive value:
tmux display-message -p '#{pane_width}'~/.claude/terminal-widthfileCOLUMNSenv varshutil.get_terminal_size()//dev/ttyioctl
Remove the statusline config and uninstall the plugin in one step:
curl -fsSL https://raw.githubusercontent.com/tmck-code/yet-another-statusline/main/ops/install.sh | bash -s -- --uninstall --fullOr uninstall manually:
claude -p "/yas:uninstall"
claude plugin uninstall yas@yet-another-statuslineclaude plugin uninstall only deletes the plugin cache — it leaves statusLine.command
in ~/.claude/settings.json pointing at the now-missing script, so the statusline keeps
trying to run. Run the uninstall script (or /yas:uninstall) first to remove that
config, then uninstall the plugin. Reload Claude Code afterwards.
make test # run pytest suite
make demo # animated demo at current terminal width
make statusline/test # same as demo — use during development
make demo/img # render snapshots into demo/
make mon/run # launch multi-session monitor TUIEnable the git pre-commit hooks (runs ruff / mypy / pytest on staged Python before each commit):
make hooksEdits to the checkout take effect immediately — no reinstall step.
git clone https://github.com/tmck-code/yet-another-statusline
cd yet-another-statuslineWire statusLine.command in ~/.claude/settings.json to point at the checkout:
"statusLine": {
"async": true,
"command": "python3 \"/path/to/yet-another-statusline/claude/statusline_command.py\"",
"type": "command"
}Note: if you also have the plugin installed,
claude plugin installwill overwritestatusLine.commandback to the plugin cache path. Either uninstall the plugin or bump the version in.claude-plugin/plugin.jsonbefore reinstalling to keep your local path.
This prompts before setting core.hooksPath. CI runs the same checks on every push, so the hook is fast local feedback rather than the gate.

