~ $ man statusline-troubleshooting

Claude Code statusline troubleshooting

8 min · updated

A statusline has exactly one moving part — Claude Code runs your command and prints the first stdout line — so when it misbehaves, the cause is almost always one of a short list. Work through these in order; each step has a definitive test.

Step 1: run the command by hand

Everything starts here. Take the exact statusLine.command from ~/.claude/settings.json and run it with sample input:

echo '{"model":{"display_name":"Test"}}' | node ~/.claude/terminal-pro/terminal-pro-statusline.mjs
echo "exit: $?"

Three outcomes, three diagnoses:

Step 2: check what lands on stdout

Claude Code displays stdout only. Debug output to stderr is invisible (useful!), but a script that logs its result via console.error shows nothing. Also: only the first line counts — a leading blank line (say, from a stray console.log()) renders as an empty statusline even though your real content follows.

Step 3: validate the settings block

{
  "statusLine": {
    "type": "command",
    "command": "node ~/.claude/terminal-pro/terminal-pro-statusline.mjs",
    "padding": 0,
    "refreshInterval": 10
  }
}

Step 4: stale numbers

The line re-runs every refreshIntervalseconds and on session events. If values lag, the interval is high, or your script caches aggressively. Device metrics in the generated runtime are cached on purpose (default 15s TTL) so the statusline doesn't hammer the system — context and rate numbers always come fresh from the payload.

Step 5: wrapping and overflow

A line longer than the terminal width wraps and breaks the UI. The fix is reading COLUMNS and trimming segments — pattern here. Quick test at a forced width:

echo '{}' | COLUMNS=64 node ~/.claude/terminal-pro/terminal-pro-statusline.mjs | wc -c

The count (including newline) must stay ≤ 65.

Step 6: missing fields

No rate_limits on fresh sessions, no repo outside git, no context_window in odd states — all normal. Segments must skip, not crash; guarded access patterns here. If your hand-rolled script keeps fighting you, the builder's generated runtime has these fallbacks built in and tested.

# faq

Why is my statusline blank?

Claude Code shows the first line your command prints to stdout. If the script prints nothing (a crash, an unhandled promise, output only to stderr), the line stays empty. Run the command manually with a sample JSON payload on stdin and confirm exactly one line lands on stdout.

Why does my statusline say 'command not found'?

The statusLine.command runs through your shell. Use an absolute path (or ~ expansion) to the script and confirm the interpreter exists — for Node runtimes, `node ~/.claude/terminal-pro/terminal-pro-statusline.mjs` must work from any directory.

Why are context or rate-limit numbers missing?

Fields like context_window and rate_limits are only present when the session has them. A robust script must fall back gracefully — render a placeholder or skip the segment instead of crashing on undefined.

Why does the line wrap or truncate badly?

Your script is ignoring terminal width. Claude Code exposes it through the COLUMNS environment variable; measure your rendered string and drop optional segments until it fits.

Why do my changes not show up?

The statusline refreshes on a timer (refreshInterval) and on session events. After editing settings.json itself, restart the Claude Code session — the statusLine block is read at startup.