Smooth, gradient statusline for Claude Code — context window + Pro/Max 5h/7d rate-limit bars (Windows / macOS / Linux)
English | 한국어
A drop-in statusline for Claude Code that ships the same look across Windows, macOS, and Linux.
| OS | Installer | How it runs |
|---|---|---|
| Windows | install.cmd (or install.ps1) |
statusline.cmd invokes Python |
| macOS / Linux | install.sh |
statusline.py runs directly via shebang |
The core renderer (statusline.py) is identical on every OS. Only the installer branches per OS, and ~/.claude/settings.json's statusLine.command is wired to the right entry point automatically.
youja@HOSTNAME ~/workspace │ ⎇ main │ Claude Opus 4.7 │ ctx [████▏ ] 42% │ 5h [██▏ ] 28% ↻3h11m │ 7d [▉ ] 12% ↻4d23h
user@host+ current directory (home shown as~)- git branch (when present)
- model name
ctx— context window usage of the current session (10-cell bar)5h— Claude Pro/Max 5-hour rolling window usage + time until reset↻Xh Ym(8-cell bar)7d— Claude Pro/Max 7-day rolling window usage + time until reset↻Xd(8-cell bar)
All bars use 1/8-cell smooth Unicode glyphs and a green→yellow→red gradient that follows the percentage.
When
5h/7dshow up: only for Claude.ai Pro/Max subscribers. After the first API response, the statusline JSON includesrate_limits.five_hour.*/rate_limits.seven_day.*(per Anthropic's official statusline schema). For API-key users, or before the first message, those two chunks are hidden automatically.
The renderer parses stdin JSON once and reads .git/HEAD directly — no git subprocess per prompt.
- Python 3.x — required to run
statusline.py. Any Python build works.- Windows:
python/python.exemust be reachable on PATH, or set the absolute path insidestatusline.cmd - macOS/Linux:
python3orpythonmust be on PATH (install.shdiscovers this automatically)
- Windows:
- A terminal with truecolor (24-bit) ANSI support so the gradient renders. Windows Terminal / iTerm2 / recent GNOME Terminal / etc. all qualify.
Verify Python:
# Windows (PowerShell)
where.exe python
# macOS / Linux
which python3 || which pythonDestination: %USERPROFILE%\.claude\ (e.g. C:\Users\<USERNAME>\.claude\) on Windows, ~/.claude/ elsewhere.
The installer writes this file at install time, baking in the absolute path to the Python it found on PATH. You normally don't touch it. A typical generated copy:
@echo off
"C:\Users\<USERNAME>\AppData\Local\Programs\Python\Python312\python.exe" "C:\Users\<USERNAME>\.claude\statusline.py"If python is not on PATH at install time, the installer falls back to the literal python and warns you. Once Python is installed and on PATH, just re-run the installer.
Use the
statusline.pyshipped in this package as-is. The full source (Pro/Maxrate_limitsrendering included) lives in the file — the installer wires up the canonical copy.
Encoding note:
statusline.pymust be saved as UTF-8 (no BOM). PowerShell's default forSet-Content/Out-Fileis UTF-16 LE, which corrupts it. The "One-shot install" section below handles this safely.
A pure-PowerShell fallback. No colors, no smooth bars, ASCII only. You don't normally need it — keep it as a backup for machines without Python installed.
The installer adds/merges the statusLine key into ~/.claude/settings.json, preserving any other keys.
If you wire it up by hand, here is what the OS-specific entry looks like:
Windows — %USERPROFILE%\.claude\settings.json
{
"statusLine": {
"type": "command",
"command": "C:\\Users\\<USERNAME>\\.claude\\statusline.cmd",
"padding": 0
}
}macOS / Linux — ~/.claude/settings.json
{
"statusLine": {
"type": "command",
"command": "/Users/<USERNAME>/.claude/statusline.py",
"padding": 0
}
}Replace
<USERNAME>. On macOS/Linux,statusline.pyischmod +x'd and has a#!/usr/bin/env python3shebang, so it runs directly — no wrapper needed.
The installer pulls everything it needs straight from GitHub, drops it under ~/.claude/, and patches settings.json.
curl -fsSL https://raw.githubusercontent.com/youja2014/smoothline/main/install.sh | bashirm https://raw.githubusercontent.com/youja2014/smoothline/main/install.ps1 | iexcurl -fsSL https://raw.githubusercontent.com/youja2014/smoothline/main/install.cmd -o install.cmd && install.cmd && del install.cmdGrab the sources and run the installer in local mode. Sibling files are copied verbatim, so this works fully offline.
install.cmd :: double-click worksor PowerShell:
.\install.ps1bash install.sh
# or
chmod +x install.sh && ./install.shOn a machine that already has Claude Code, cd into the unpacked folder and just say:
"Run install.sh in this folder to set up the statusline"
- Source the assets — if
statusline.pyis a sibling, copy it (local mode); otherwise download from the GitHub raw URL (one-liner mode) - Auto-detect Python — Windows checks
pythonon PATH, Unix triespython3thenpython - On Windows, regenerate
statusline.cmdwith the detected Python's absolute path (so the one-liner install just works without editing) - Add/replace only the
statusLinekey in~/.claude/settings.json(other keys preserved) - Run the statusline once with a dummy JSON payload and print the output
If you'd rather grab smoothline as a regular Python tool — no installer, no file copies under ~/.claude:
uv tool install smoothlineor
pip install --user smoothlineEither way you get a smoothline executable on PATH. Wire it into ~/.claude/settings.json directly:
{
"statusLine": {
"type": "command",
"command": "smoothline",
"padding": 0
}
}Restart Claude Code. The PyPI binary is the entry point — no separate ~/.claude/statusline.py needed.
brew install youja2014/tap/smoothlineor, the two-step form:
brew tap youja2014/tap
brew install smoothlineHomebrew drops smoothline into a managed virtualenv. The settings.json registration is identical to 3-C:
{
"statusLine": {
"type": "command",
"command": "smoothline",
"padding": 0
}
}The installer prints sample output, so usually you don't need to do anything. To re-run the check:
Windows (PowerShell)
$json = '{"model":{"display_name":"Claude Opus 4.7"},"workspace":{"current_dir":"D:\\workspace"},"context_window":{"used_percentage":42},"rate_limits":{"five_hour":{"used_percentage":28,"resets_at":2000000000},"seven_day":{"used_percentage":12,"resets_at":2000300000}}}'
$tmp = [System.IO.Path]::GetTempFileName()
[System.IO.File]::WriteAllText($tmp, $json, (New-Object System.Text.UTF8Encoding $false))
& cmd /c "type `"$tmp`" | `"$env:USERPROFILE\.claude\statusline.cmd`""
Remove-Item $tmpPiping
'{...}' | statusline.cmddirectly in PowerShell encodes as UTF-16 LE and breaks Python's JSON parser. Going through a tempfile is the safe path.
macOS / Linux (bash)
NOW=$(date +%s)
echo '{"model":{"display_name":"Claude Opus 4.7"},"workspace":{"current_dir":"'"$HOME"'"},"context_window":{"used_percentage":42},"rate_limits":{"five_hour":{"used_percentage":28,"resets_at":'$((NOW+11600))'},"seven_day":{"used_percentage":12,"resets_at":'$((NOW+424600))'}}}' \
| "$HOME/.claude/statusline.py"You should see two colored lines. After that, restart Claude Code — the new statusline shows up immediately.
| Symptom | Cause / Fix |
|---|---|
| Korean / emoji garbled | statusline.py was saved as UTF-16 or CP949. Re-save as UTF-8 (no BOM). |
Raw color codes ([38;2;...m) visible |
Terminal lacks ANSI truecolor. Switch to Windows Terminal / iTerm2 / recent GNOME Terminal. |
'python' is not recognized (Win) / python3: command not found (Unix) |
Python not on PATH. On Windows, hard-code the absolute path inside statusline.cmd. On macOS, brew install python or use python.org. On Linux, use the distro's package manager. |
| Statusline doesn't show at all | Verify the command path in settings.json. Run section 4 manually to debug. On macOS/Linux, check chmod +x ~/.claude/statusline.py. |
| Bar glyphs out of alignment | Font lacks Powerline / Unicode box characters. Switch to Cascadia Mono / JetBrains Mono / Menlo. |
Permission denied on Linux |
chmod +x ~/.claude/statusline.py was skipped. Re-run the installer or fix it manually. |
- Bar width: the 4th argument to each
render_usage(...)call insidemain()(ctxis 10,5h/7dare 8) - Colors:
GRAY / BLUE / PURPLE / ORANGE / SEPRGB tuples - Gradient breakpoints:
green / yellow / redinsidegradient_color() - Display order: reorder how
line1/line2chunks are appended - Hide the 5h / 7d chunks: comment out their
render_usage(...)calls - Drop the reset-time tail: pass
Noneas theresets_atargument torender_usage()