Skip to content

Building a Custom Claude Code Statusline

Building a Custom Claude Code Statusline

Who This Guide Is For

Software engineers who use build-cli regularly and want richer session information at a glance. You should be comfortable with a terminal and basic shell scripting. No prior experience customising Claude Code is required.

What You Will Learn

  • How the Claude Code statusline works (JSON stdin → script → stdout)
  • Two approaches: extending the existing bar vs replacing it from scratch
  • Key JSON fields your script can consume
  • How to install and test a custom statusline script
  • How to troubleshoot common statusline issues

Note on the example script: The v1 guide referenced a downloadable my-statusline.sh script file. That asset file requires a separate decision on how to host it in v2 (this is recorded as an open question for the Plan-04 editorial gate). In the meantime, this guide explains the anatomy of such a script in full so you can build your own.

Step-by-Step Instructions

Step 1: Understand How the Statusline Works

Every time Claude Code refreshes the bar, it pipes a JSON snapshot of the current session to your script on stdin. Your script reads that JSON, formats a line, and prints it. Whatever your script writes to stdout (first line) becomes the statusline.

A few things to know:

  • ANSI colors and emoji are supported.
  • Updates are debounced (~300 ms) — the script runs after each assistant message, after /compact, and on a fixed timer if you set refreshInterval.
  • If your script exits non-zero or prints nothing, the bar goes blank — fail gracefully.
  • Keep it fast; a slow script delays every refresh.

The key JSON fields available to your script:

FieldWhat it is
model.display_nameThe active model, e.g. Opus
workspace.current_dirCurrent working directory
context_window.used_percentageHow full the context window is (0–100)
cost.total_cost_usdEstimated cost of the current session
cost.total_lines_addedLines of code added this session
cost.total_lines_removedLines of code removed this session

You can inspect the full payload at any time by piping a mock JSON blob to jq:

Terminal window
echo '{"context_window":{"used_percentage":95}}' | jq .

Step 2: Choose Your Approach

Option A — Keep build-cli’s budget bar, just add to it

If you only want to add a small piece of your own information to the existing bar, call build-cli claude statusline from your own script and append your segment:

#!/bin/sh
my_segment="my-custom-info"
bcli_out=$(build-cli claude statusline < /dev/null 2>/dev/null)
if [ -n "$bcli_out" ]; then
echo "${bcli_out} | ${my_segment}"
else
echo "${my_segment}"
fi

Then tell build-cli not to overwrite your configuration on the next setup run:

Terminal window
build-cli config set statusline_disabled true

Option B — Build your own from scratch

Steps 3–4 below cover this approach. It still embeds the build-cli budget bar as one segment.

Step 3: Install Prerequisites

The script needs two common command-line tools:

  • jq — parses the JSON that Claude Code sends
  • git — reads the current repo and branch
Terminal window
# macOS (Homebrew)
brew install jq git
# Debian / Ubuntu / WSL
sudo apt-get install -y jq git

Verify they are available:

Terminal window
jq --version && git --version

Step 4: Write and Install Your Script

Create your script at ~/.config/my-statusline.sh. A full script reads stdin, parses JSON fields with jq, renders a colored bar with ANSI escape sequences, and assembles the segments with dim | separators.

The key sections to implement:

  1. Read stdin and parse fields — read the whole JSON payload once, then extract fields with jq using // "default" fallbacks for missing data.
  2. Context gauge — render a colored progress bar using 24-bit ANSI colors interpolated from green (empty context) through amber to red (full context).
  3. Threshold emoji🟢 (plenty of room), (working), 🔥 (getting full), 🚨 (critical).
  4. Build-cli budget segment — call build-cli claude statusline and embed the output as a segment; skip cleanly when build-cli isn’t installed.
  5. Cost, velocity, git, model — format $2.14, +156 -23, repo/branch from git -C "$cwd", and 🤖 Opus.
  6. Assemble — join segments with dim | separators, omitting empty segments.

Make the script executable:

Terminal window
chmod +x ~/.config/my-statusline.sh

Step 5: Point Claude Code at Your Script

First, stop build-cli from overwriting your configuration on future setup runs:

Terminal window
build-cli config set statusline_disabled true

Then edit ~/.claude/settings.json:

{
"statusLine": {
"type": "command",
"command": "~/.config/my-statusline.sh",
"refreshInterval": 360
}
}

Restart Claude Code (close and reopen). The new bar should appear at the bottom.

Step 6: Test Without Restarting

Because the script reads JSON from stdin, you can feed it a mock payload and see the output immediately:

Terminal window
echo '{
"model": { "display_name": "Opus" },
"workspace": { "current_dir": "'"$PWD"'" },
"context_window": { "used_percentage": 31 },
"cost": { "total_cost_usd": 2.14, "total_lines_added": 156, "total_lines_removed": 23 }
}' | ~/.config/my-statusline.sh

Adjust used_percentage to watch the gradient and emoji change.

Verification

Your custom statusline is working when:

  • The test command in Step 6 prints a formatted bar without errors
  • After restarting Claude Code, the custom bar appears at the bottom of the session window
  • build-cli doctor reports the statusline is enabled and the script exists

Next Steps

  • See the ‘Installing build-cli’ guide if you haven’t set up build-cli yet
  • See the ‘Your First Session with build-cli’ guide to get productive with build-cli
  • Official docs: build-cli Statusline and Usage Tracking

Troubleshooting

The bar is blank. Your script exited non-zero or printed nothing. Run the test command in Step 6 directly to see the error. Make sure jq is installed and the script is executable.

build-cli claude setup overwrote my custom statusline. Run build-cli config set statusline_disabled true so setup leaves your ~/.claude/settings.json entry alone, then re-point it at your script.

The budget segment is missing. build-cli wasn’t found on your PATH, or you’re not logged in. Confirm with build-cli claude statusline < /dev/null. This segment is optional — the rest of the bar works without it.

Something’s off and I’m not sure what. Run build-cli doctor — it checks whether the statusline is enabled, whether the script exists, and whether ~/.claude/settings.json has a valid statusLine entry.

I want the default budget bar back. Run build-cli config set statusline_disabled false then build-cli claude setup to restore the defaults.