A status bar that works for both Claude Code and GitHub Copilot CLI — plus a high-contrast/neon output proxy for Copilot CLI specifically.
statusline.js— a single, dual-compatible status line script (model, tokens, context %, peak/off-peak marker, cwd), rendered in vivid neon truecolor. Works unmodified as thestatusLinecommand for either Claude Code or GitHub Copilot CLI — it reads whichever tool's stdin JSON schema is actually present (see How it works).copilot-hc.js— a PTY-wrapping proxy that intercepts all of Copilot CLI's own output and rewrites its hardcoded, washed-out gray colors into a brighter, higher-contrast, neon color scheme in real time. Copilot-CLI-specific; not used with Claude Code. This also affects the status line's colors when running under Copilot CLI, since Copilot CLI renders the statusLine command's stdout as part of its own output.
| Segment | Meaning | Color |
|---|---|---|
Sonnet 4.6 (h) |
Active model, plus reasoning effort in parens (low/md/h/xh/MX — Claude Code only, omitted on Copilot CLI) |
Magenta |
122K |
Tokens used in the current context window | Green (< 250K) → yellow (< 1M) → red (≥ 1M) |
61% |
Context window used | Green → yellow → orange → red |
AC!! |
Auto-compact imminent (≤ 20% context remaining) | Yellow → orange → red |
PEAK / 🌙 |
API peak hours (5–11 AM Pacific, Mon–Fri) | Yellow (peak) / teal (off-peak) |
my-project |
Working directory, last path segment | Orange |
The peak/off-peak indicator includes a live countdown to the next state change.
Prerequisites: Node.js (18+) and Claude Code.
-
Keep this folder wherever you like (this README uses
C:\projects\claude-statusline; adjust the path below if you put it elsewhere). No install step —statusline.jshas no dependencies of its own. -
Add the
statusLinekey to~/.claude/settings.json(merge into the existing JSON object, don't replace it):macOS / Linux
{ "statusLine": { "type": "command", "command": "node /home/your-username/projects/claude-statusline/statusline.js" } }Windows
{ "statusLine": { "type": "command", "command": "node C:/projects/claude-statusline/statusline.js" } }(Use forward slashes even on Windows.)
-
Restart Claude Code (or start a new session). The status bar updates on every turn.
Claude Code's stdin JSON schema is stable and documented at code.claude.com/docs/en/statusline: context_window.total_input_tokens, context_window.remaining_percentage, model.display_name, cwd. example-input.json in this repo is a sanitized real payload matching that schema, useful for building/testing against without a live session.
Prerequisites: Node.js (18+) and GitHub Copilot CLI (copilot.exe).
-
Keep this folder at
C:\projects\claude-statusline(or update the path below if you move it). -
In
C:\Users\<you>\.copilot\settings.json, add/merge:{ "statusLine": { "type": "command", "command": "node C:/projects/claude-statusline/statusline.js" } }(Use forward slashes even on Windows.)
-
Restart Copilot CLI / open a new session.
GitHub Copilot CLI's statusline payload isn't pinned by a stable public schema the way Claude Code's is — field names below were confirmed from copilot help config (statusLine section), EncodeTS/copilot-statusline (a real third-party Copilot CLI statusline implementation requiring current_context_tokens / displayed_context_limit under context_window), and blog.madkoo.net's defensive field-probing statusline script, which enumerates every field-name variant seen across Copilot CLI versions.
Spawns the real copilot.exe inside a pseudo-console (via node-pty) so it still detects a TTY and emits color, then intercepts its output byte-for-byte and rewrites every color-setting SGR sequence (truecolor 38;2;/48;2;, 256-color 38;5;/48;5;, and standard 16-color 30-37/90-97/40-47/100-107) through a transform. This step is specific to Copilot CLI's own output and isn't used with Claude Code.
Copilot CLI's built-in themes (default, github, dim, high-contrast, colorblind) are baked into the copilot.exe binary as hardcoded 24-bit truecolor (and some standard 16/256-color) ANSI codes — no terminal color scheme change can fix low contrast, since Copilot CLI's colors bypass the terminal's palette entirely. copilot-hc.js patches this at the byte-stream level:
- Grayish foreground colors are blended sharply towards white (bright, legible labels/text), snapping to pure white once close enough.
- Very dark grays (the box-drawing border glyphs
▄▀╻╹┃around the prompt input) get a light blend instead, so the border stays thin and visible rather than disappearing or turning into a thick bright line. - Grayish backgrounds are left untouched (passed through unchanged). Copilot's overall canvas background is already forced to pure black via the separate OSC 11 rewrite below, so panel backgrounds (e.g. the prompt input box,
~20,27,34) keep their natural, slightly-lighter tone — this is what makes the box's right edge read as a border, since that edge has no explicit border glyph and relies purely on background contrast against the canvas. Forcing panel backgrounds to black too made that border disappear. - Non-gray hues (diff green/red, status line colors, etc.) get a saturation + lightness boost for a vivid neon look, capped so text stays readable and backgrounds stay dark enough for overlaid text.
- Your own submitted prompt line (
❯ <text>in the feed) is detected by its distinct near-white RGB(240,246,252) and recolored to bright neon teal, so your messages visually stand out from Copilot's replies. - OSC 10/11 (the actual terminal default foreground/background, set independently of any per-cell color) are forced to white-on-black.
All the brightness/saturation constants live near the top of the file (BORDER_BLEND_MAX_AVG, BORDER_BLEND_FACTOR, TEXT_BLEND_FACTOR, WHITE_SNAP_THRESHOLD, and the neonify() saturation/lightness math) — tune them there if you want a different intensity.
- Node.js on
PATH(or a known absolute path — see Setup). node-ptyinstalled in this folder (npm install node-pty). It has a native module with an install script (node-gyp rebuild); if npm blocks it, runnpm approve-scripts --allow-scripts-pending, or otherwise permitnode-pty's install script to run.
-
cd C:\projects\claude-statusline && npm install(installsnode-pty; already done ifnode_modules\node-ptyexists). -
Edit
REAL_COPILOTat the top ofcopilot-hc.jsif yourcopilot.exeisn't atC:\Users\<you>\AppData\Local\Microsoft\WinGet\Links\copilot.exe(find it with(Get-Command copilot).Sourcein PowerShell, resolving any symlink withGet-Item <path> | Select-Object -Expand Target). -
Add a
copilotfunction to your PowerShell profile(s) so plaincopilot ...transparently runs through the wrapper. Both PowerShell profiles need this if you use both shells:- Windows PowerShell 5.1:
C:\Users\<you>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 - PowerShell 7 (
pwsh):C:\Users\<you>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
function copilot { & "C:\Program Files\nodejs\node.exe" "C:\projects\claude-statusline\copilot-hc.js" @args }
- Windows PowerShell 5.1:
-
Open a brand new terminal tab/window (existing tabs won't pick up profile changes) and run
copilotas usual.
- This is a wrapper around the official binary, not a patch to it — it doesn't touch or modify
copilot.exeitself, so CLI auto-updates are unaffected. - The wrapper only rewrites color-setting SGR/OSC sequences; it does not otherwise alter Copilot CLI's behavior, input handling, or output content.
- If Copilot CLI changes its internal color palette in a future version, the specific RGB values referenced here (e.g. the user-prompt-line detection color
240,246,252) may need to be re-captured. To recapture, spawncopilot.exedirectly undernode-ptyand dump the raw byte stream to a file (see the constants/comments incopilot-hc.jsfor the exact colors currently matched).
statusline.js is a single self-contained Node.js file, no build step, no dependencies.
Change peak hours or timezone
Find the isPeak assignment and edit the hour bounds or the timezone string:
// Change 5 and 11 to your preferred window, or swap the timezone
const isPeak = isWeekday && ptHour >= 5 && ptHour < 11;
// timeZone: 'America/Los_Angeles' ← change thisAdjust context color thresholds
if (used >= 95) color = FG.red;
else if (used >= 80) color = FG.orange;
else if (used >= 60) color = FG.yellow;
else color = FG.green;Change 95, 80, 60 to whatever breakpoints suit your workflow.
Remove a segment
Comment out the matching parts.push(...) call near the bottom of the file.
statusline-debug.js captures the raw JSON payload piped to the status line command and writes it to disk — handy when building or troubleshooting a status line against either tool.
-
Temporarily point the relevant
settings.jsonat the debug script instead ofstatusline.js:{ "statusLine": { "type": "command", "command": "node C:/projects/claude-statusline/statusline-debug.js" } } -
Run Claude Code or Copilot CLI for one turn. The status bar shows
DEBUG: wrote .... -
Open the output file (default:
~/statusline-capture.json). Override the path with theSTATUSLINE_DEBUG_PATHenvironment variable.
example-input.json in this repo shows a sanitized example of the Claude Code payload schema, so you can build against it without running a live session.
Both Claude Code and Copilot CLI pipe a JSON payload to the status line command via stdin on every turn. The script parses context-window metrics and model info defensively — trying Claude Code's documented field names first, falling back to Copilot CLI's field-name variants — builds an ANSI-colored string, and writes it to stdout. The host tool renders that string in its status bar.
Claude Code / Copilot CLI ──stdin──▶ node statusline.js ──stdout──▶ status bar
JSON ANSI string
The 3-second setTimeout exits the process if stdin never closes — without it, Node processes stack up across long sessions.
MIT