Skip to content

Replicate the Claude Code Status Line

This guide explains how to reproduce the custom two-line Claude Code status display on a new macOS or Debian/Ubuntu machine.

The coloured rows above the Claude Code prompt are provided by ccstatusline, a third-party npm CLI. Claude Code sends status information to ccstatusline as JSON on standard input, and displays the text that ccstatusline returns.

What belongs to Claude Code?

The first two coloured rows are rendered by ccstatusline.

The row resembling:

▶▶ auto mode on (shift+tab to cycle) · ← 6 agents

is Claude Code's native footer and does not require additional installation.

Components

Only two configuration files and the ccstatusline executable are required:

Component Purpose
~/.claude/settings.json Tells Claude Code to execute ccstatusline
~/.config/ccstatusline/settings.json Defines what ccstatusline renders
ccstatusline npm CLI that renders the status rows

The source machine used the following versions:

Component Version
ccstatusline 2.2.22
Node.js v26.3.1
npm 11.16.0

Tip

Pinning ccstatusline to version 2.2.22 helps keep rendering consistent with the source machine.


1. Install Node.js and npm

ccstatusline targets Node.js 14 compatibility, so any modern Node.js version such as Node 18 or newer is suitable.

Install Node.js with Homebrew:

brew install node

Homebrew's global npm packages normally live under:

/opt/homebrew/lib/node_modules

Executable symlinks are placed in:

/opt/homebrew/bin

This setup normally does not require sudo.

Install Node.js using NodeSource:

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs

Configure a user-owned npm global package directory:

mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
exec $SHELL -l

If you use Zsh, write the PATH entry to ~/.zshrc instead.

Tip

nvm can also be used and does not require npm prefix configuration.


2. Install ccstatusline

Install the exact version used on the source machine:

npm install -g ccstatusline@2.2.22

Verify that the executable resolves through your PATH:

which ccstatusline

Typical paths are:

/opt/homebrew/bin/ccstatusline
~/.npm-global/bin/ccstatusline

Depending on how Node.js was installed, it may instead resolve to:

/usr/bin/ccstatusline

Do not install ccstatusline with Homebrew

There is no Homebrew formula for ccstatusline.

The following will fail:

brew install ccstatusline

ccstatusline is installed through npm. On a Homebrew-based Node.js installation, it may only appear to be associated with Homebrew because Node owns the global npm prefix.


3. Configure ccstatusline

Create the configuration directory:

mkdir -p ~/.config/ccstatusline

Create ~/.config/ccstatusline/settings.json:

~/.config/ccstatusline/settings.json
cat > ~/.config/ccstatusline/settings.json <<'EOF'
{
  "version": 3,
  "lines": [
    [
      { "id": "1", "type": "model", "color": "cyan" },
      { "id": "2", "type": "separator" },
      { "id": "3", "type": "context-length", "color": "brightBlack" },
      { "id": "4", "type": "separator" },
      { "id": "5", "type": "git-branch", "color": "brightRed" },
      { "id": "6", "type": "separator" },
      { "id": "7", "type": "git-changes", "color": "yellow" },
      { "id": "5f3c3050-18af-4359-99c8-aa949e929444", "type": "separator" }
    ],
    [
      { "id": "df6fa480-31af-4ffc-b2ab-9735a474a5ec", "type": "tokens-input", "color": "brightMagenta" },
      { "id": "1e4dddf4-b7cd-4613-836e-c520ce730f50", "type": "separator" },
      { "id": "6497c9dd-15c5-4431-9582-a0a4e7d78700", "type": "tokens-output", "color": "brightBlue" },
      { "id": "301b1f5e-53ce-4418-9c34-9490fc6d808d", "type": "separator" },
      { "id": "c9e42aa8-8400-4167-9f95-2ad31f195eab", "type": "tokens-total", "color": "brightGreen" },
      { "id": "63d39087-9188-4bca-a410-66aa5afc0884", "type": "separator" },
      { "id": "8cc384e8-c9e5-4212-9418-465f9d2dd612", "type": "session-cost", "color": "white" },
      { "id": "0d2408ee-a222-43dc-b94f-a217a1dd42d9", "type": "separator" },
      { "id": "aea35e35-9e1a-47e2-acdd-c0dd0aee57fc", "type": "session-usage" }
    ],
    []
  ],
  "flexMode": "full-minus-40",
  "compactThreshold": 60,
  "colorLevel": 2,
  "inheritSeparatorColors": false,
  "globalBold": false,
  "gitCacheTtlSeconds": 5,
  "minimalistMode": false,
  "powerline": {
    "enabled": false,
    "separators": [""],
    "separatorInvertBackground": [false],
    "startCaps": [],
    "endCaps": [],
    "autoAlign": false,
    "continueThemeAcrossLines": false
  },
  "installation": {
    "method": "pinned",
    "installedVersion": "2.2.22"
  }
}
EOF

The widget id values are simply unique keys. They can technically be changed, but copying the working values is the simplest approach.

The configuration path is XDG-based and is identical on macOS and Debian:

~/.config/ccstatusline/settings.json

Status line layout

Line 1

A typical first row resembles:

Model: Opus 5 | Ctx: 0 | ⎇ no git | (no git)
Widget Colour Purpose
model Cyan Active model
context-length Bright black Tokens currently in context
git-branch Bright red Current Git branch or no git
git-changes Yellow Dirty-file count

Line 2

A typical second row resembles:

In: 0 | Out: 0 | Total: 0 | Cost: $0.00 | Session: 63.0%
Widget Colour Purpose
tokens-input Bright magenta Input token count
tokens-output Bright blue Output token count
tokens-total Bright green Total token count
session-cost White Session cost
session-usage Default Percentage of the rolling usage window consumed

Line 3

The third configured line is intentionally empty:

[]

Keep the empty third line

Do not remove the empty array from lines.

It preserves the three-line layout. The auto-mode and agents row shown underneath is provided by Claude Code itself.


4. Understand the global options

flexMode: "full-minus-40"

Allows widgets to flex according to the terminal width minus 40 columns.

compactThreshold: 60

Switches to compact rendering when the terminal becomes narrower than 60 columns.

colorLevel: 2

Enables 256-colour output.

gitCacheTtlSeconds: 5

Caches Git status for five seconds to avoid repeatedly querying the repository.

powerline.enabled: false

Uses plain separators. A Nerd Font is therefore not required.

installation.method: "pinned"

Prevents the configured installation from being silently treated as an automatically updated version.

Terminal colours

colorLevel: 2 expects a terminal that supports 256 colours, such as:

  • xterm-256color
  • screen-256color

On a bare Debian TTY, the source configuration recommends:

export TERM=xterm-256color

For tmux:

set -g default-terminal "screen-256color"

Keep the pinned version in sync

If you install a version other than 2.2.22, update:

"installedVersion": "2.2.22"

so the value matches the installed version.


5. Configure Claude Code

Claude Code must be told to invoke ccstatusline for its status line.

Add the following statusLine object to:

~/.claude/settings.json
"statusLine": {
  "type": "command",
  "command": "ccstatusline",
  "padding": 0,
  "refreshInterval": 10
}

Do not overwrite existing settings

If ~/.claude/settings.json already contains other configuration, merge the statusLine object into the existing JSON rather than replacing the entire file.

Merge into an existing configuration

tmp=$(mktemp)
jq '.statusLine = {type:"command", command:"ccstatusline", padding:0, refreshInterval:10}' \
  ~/.claude/settings.json > "$tmp" && mv "$tmp" ~/.claude/settings.json

Create a new configuration

If ~/.claude/settings.json does not exist:

mkdir -p ~/.claude
cat > ~/.claude/settings.json <<'EOF'
{
  "statusLine": {
    "type": "command",
    "command": "ccstatusline",
    "padding": 0,
    "refreshInterval": 10
  }
}
EOF

Debian PATH issues

The command value is resolved through the login shell's PATH.

If the status line remains blank on Debian, use the absolute path to ccstatusline.

For example:

"command": "/home/franz/.npm-global/bin/ccstatusline"

Use the actual path returned by:

which ccstatusline

6. Test ccstatusline without Claude Code

ccstatusline reads a JSON payload from standard input.

You can test the configuration by sending it a sample payload:

echo '{"model":{"display_name":"Opus 5"},"workspace":{"current_dir":"'"$PWD"'"},"cost":{"total_cost_usd":0,"total_lines_added":0,"total_lines_removed":0}}' \
  | ccstatusline

You should see the configured coloured status rows.

No input received

Running ccstatusline without piping data into it in a non-TTY context can produce:

No input received

This means no JSON payload was received on standard input and is expected in that situation.

After the test succeeds, launch Claude Code. The configured status display should appear above the prompt.


7. Edit the status line interactively

Run ccstatusline directly from a real terminal:

ccstatusline

This opens the interactive configurator.

It can be used to:

  • Add or remove widgets
  • Reorder widgets
  • Change colours
  • Toggle Powerline rendering
  • Preview the status line

Changes are written back to:

~/.config/ccstatusline/settings.json

The file can also be edited manually.


Files and paths

Path macOS Debian
Binary symlink /opt/homebrew/bin/ccstatusline ~/.npm-global/bin/ccstatusline
Package /opt/homebrew/lib/node_modules/ccstatusline ~/.npm-global/lib/node_modules/ccstatusline
ccstatusline config ~/.config/ccstatusline/settings.json ~/.config/ccstatusline/settings.json
ccstatusline cache ~/.cache/ccstatusline ~/.cache/ccstatusline
Claude Code settings ~/.claude/settings.json ~/.claude/settings.json

Tip

The ~/.cache/ccstatusline directory is safe to delete.


Common problems

brew install ccstatusline fails

There is no Homebrew formula for ccstatusline.

Install it with npm:

npm install -g ccstatusline@2.2.22

npm global packages become root-owned

Avoid using:

sudo npm install -g ccstatusline

on Debian when using a user-owned npm prefix.

Configure the prefix under your home directory instead.

Layout changes after editing the configuration

Make sure the empty third line remains in the lines array:

[]

Colours look incorrect

The configuration uses:

"colorLevel": 2

which expects a 256-colour terminal.

Powerline symbols are missing

The supplied configuration has Powerline disabled:

"powerline": {
  "enabled": false
}

No Nerd Font is required in this configuration.

If Powerline separators are enabled later, a patched font such as MesloLGS NF will be required.

Session cost or usage shows zero

Session and cost data comes from the JSON payload supplied by Claude Code, not from ccstatusline itself.

A value of zero can therefore simply mean the session has not accumulated that usage yet.

Status line is blank on Debian

Check the executable path:

which ccstatusline

If required, replace:

"command": "ccstatusline"

with its absolute path.


One-shot installation

The following block installs the pinned version of ccstatusline, creates its configuration, and adds the Claude Code statusLine configuration.

Warning

This assumes Node.js and npm are already installed.

set -e
npm install -g ccstatusline@2.2.22
mkdir -p ~/.config/ccstatusline ~/.claude

cat > ~/.config/ccstatusline/settings.json <<'EOF'
{
  "version": 3,
  "lines": [
    [
      { "id": "1", "type": "model", "color": "cyan" },
      { "id": "2", "type": "separator" },
      { "id": "3", "type": "context-length", "color": "brightBlack" },
      { "id": "4", "type": "separator" },
      { "id": "5", "type": "git-branch", "color": "brightRed" },
      { "id": "6", "type": "separator" },
      { "id": "7", "type": "git-changes", "color": "yellow" },
      { "id": "8", "type": "separator" }
    ],
    [
      { "id": "9",  "type": "tokens-input",  "color": "brightMagenta" },
      { "id": "10", "type": "separator" },
      { "id": "11", "type": "tokens-output", "color": "brightBlue" },
      { "id": "12", "type": "separator" },
      { "id": "13", "type": "tokens-total",  "color": "brightGreen" },
      { "id": "14", "type": "separator" },
      { "id": "15", "type": "session-cost",  "color": "white" },
      { "id": "16", "type": "separator" },
      { "id": "17", "type": "session-usage" }
    ],
    []
  ],
  "flexMode": "full-minus-40",
  "compactThreshold": 60,
  "colorLevel": 2,
  "inheritSeparatorColors": false,
  "globalBold": false,
  "gitCacheTtlSeconds": 5,
  "minimalistMode": false,
  "powerline": {
    "enabled": false,
    "separators": [""],
    "separatorInvertBackground": [false],
    "startCaps": [],
    "endCaps": [],
    "autoAlign": false,
    "continueThemeAcrossLines": false
  },
  "installation": {
    "method": "pinned",
    "installedVersion": "2.2.22"
  }
}
EOF

if [ -f ~/.claude/settings.json ]; then
  tmp=$(mktemp)
  jq '.statusLine = {type:"command", command:"ccstatusline", padding:0, refreshInterval:10}' \
    ~/.claude/settings.json > "$tmp" && mv "$tmp" ~/.claude/settings.json
else
  printf '%s\n' '{"statusLine":{"type":"command","command":"ccstatusline","padding":0,"refreshInterval":10}}' \
    > ~/.claude/settings.json
fi

echo "done — restart Claude Code"

Final checklist

  • Node.js and npm are installed
  • ccstatusline@2.2.22 is installed globally
  • which ccstatusline returns a valid executable
  • ~/.config/ccstatusline/settings.json exists
  • The empty third line remains in the lines array
  • ~/.claude/settings.json contains the statusLine configuration
  • The test JSON renders the two status rows
  • Claude Code has been restarted