How PixerBar works
Claude Code lets a status line be any command. It runs the command, hands it a blob of JSON on stdin, and prints whatever comes back. PixerBar is one bash script that reads that JSON and prints five rows of half-block characters — a sprite, coloured by what the JSON said.
Installing
You need bash and jq (brew install jq on macOS, apt install jq on Debian/Ubuntu), a terminal with 24-bit colour, and Claude Code. On Windows, run it inside Git Bash or WSL. Pick whichever of the three routes matches how much you like piping things into shells:
Route 1 — the one-liner
Build a skin in the studio and copy its install command:
curl -fsSL 'https://pixerbar.dev/i/<your-skin>' | bash The URL carries the entire skin, so the script that comes back is self-contained — it makes no further network requests and installs nothing but itself. The -f matters: if the link is bad the server answers 400, curl passes nothing to bash, and nothing runs.
Route 2 — read it first recommended if you don't pipe strangers into bash
# download, read, then run — same bytes, two steps
curl -fsSL 'https://pixerbar.dev/i/<your-skin>' -o pixerbar-install.sh
less pixerbar-install.sh # every line it will run, sprite included
bash pixerbar-install.sh Opening the same URL in a browser shows the identical script as plain text. Add --dry-run to see the plan without writing a byte.
Route 3 — no network execution at all
git clone https://github.com/ke11/pixerbar
cd pixerbar
bash runtime/install.sh --skin skins/clawd.sh # or a .sh downloaded from the studioThe studio's download .sh button hands you the skin as a file; this route never executes anything a web server produced.
What every route does
~/.claude/pixerbar/pixerbar.sh— the status line script~/.claude/pixerbar/skins/<name>.sh— your skin- sets
statusLinein~/.claude/settings.json— after copying the file to~/.claude/pixerbar/backups/, and remembering any status line you already had - runs a doctor pass and names anything wrong
Never sudo, never outside ~/.claude, no telemetry, re-running is safe. Then open a new Claude Code session and the sprite appears.
Managing it afterwards
… | bash -s -- --uninstall # put back the status line you had before
… | bash -s -- --doctor # why is the bar blank?
… | bash -s -- --list # skins you have installed
… | bash -s -- --use clawd # switch the active skin
… | bash -s -- --dry-run # print the plan, write nothing The flags work identically on a downloaded copy: bash pixerbar-install.sh --uninstall. Uninstall restores your previous statusLine exactly; the backups folder survives it on purpose.
What the sprite is telling you
| State | Comes from | Looks like |
|---|---|---|
| Idle | the transcript has not changed for 8 seconds | parks on the last frame, perfectly still |
| Working | the transcript was written to just now | walks the beat frames |
| Fast mode | fast mode is on while working | alternates the two frames the skin nominates |
| Context | context_window.used_percentage | the body reddens bottom-up, one pixel row per tenth |
| Uncommitted work | git status --porcelain is not empty | the skin's own git pixels turn cream |
| Five hours | rate_limits.five_hour.used_percentage | a separate column beside the sprite, green through red |
| idle | nothing happening | |
| working | walks poses 1–4, one step per run | |
| fast | alternates poses 1 and 3 | |
| context | 50% of the window used | |
| 100% — the gauge fills every row | ||
| git | uncommitted work in the tree | |
| 5-hour | 30% — green, its own column | |
| 60% — amber | ||
| 95% — red | ||
| all at once | working, full context, dirty, 5h nearly gone |
Two things that never change
The mark is always five rows. Whatever the sprite is doing inside it, the canvas is the same height, so the interface above the status line never jumps.
An empty cell is U+2800, not a space. A leading space gets trimmed somewhere between the script and the screen, and the row snaps left. A braille blank occupies a cell and is not whitespace.
The skin format
A skin is a shell file the runtime sources. Nine variables, two of them arrays of digit strings. It is meant to be readable and hand-editable — the studio is a convenience, not a requirement.
- W
- sprite columns, 8 to 40. The canvas is W+2: the sprite, a blank gap, the tick.
- NFRAMES
- beat frames, 2 to 8. There is always one more frame than this — the idle pose.
- SKIN_BASE
- the creature's own colour.
- SKIN_GAUGE
- the context gauge. Choose it against the base, not from the source art.
- SKIN_CREAM
- what the git pixels turn when the worktree is dirty.
- SKIN_INK2/3/4
- accent ink: colours the gauge and the git mask both leave alone.
- FAST_A / FAST_B
- the pair fast mode alternates. Pick the two frames furthest apart.
- DIRTY
- 10 rows of 0 and 1: which pixels answer to git.
- FRAMES
- (NFRAMES+1)×10 rows of digits 0–4, each exactly W wide.
Digits in FRAMES are not a bitmask. 0 is off, 1 is the body — the part the gauge and the git mask act on — and 2, 3 and 4 select accent inks, which they leave alone.
When the bar is blank
Almost always workspace trust. A status line is gated by it exactly like hooks are, keyed by the exact absolute path with no inheritance from parent folders — and when a folder is not trusted the bar is empty with no error anywhere. Claude Code asks once per folder; answer yes and it appears.
After that: jq missing, or refreshInterval not set to 1 — without it the sprite only moves when something else happens, which looks like a bug and is not one. Run the install line with --doctor and it checks all of these.