A custom status line script for Claude Code that displays directory, git branch, model, current task, context window usage, session stats, and rate limits in the terminal.
- Node.js (available as
nodeon$PATH) git(for thegitsegment)
-
Place the script at
~/.claude/statusline.js. -
Add the
statusLinehook to~/.claude/settings.json:{ "statusLine": { "type": "command", "command": "node /home/YOUR_USERNAME/.claude/statusline.js" } }Replace
YOUR_USERNAMEwith your actual username, or use the full absolute path.Note: Use an absolute path — the
~shorthand does not expand in this config value.
~/projects/myapp | main* ↑2 | Claude Sonnet 4.6 | plan | Writing tests +2
⏱ 12m | ████░ 74% (80%) | 85% cache · $0.023/hr · $0.042 · 1.2k tpm | +156 -23 | 5h ███░░ 60% (!45m/↺2h) · 7d █░░░░ 20% (↺5d)
| Segment | Description |
|---|---|
~/projects/myapp |
Working directory ($HOME replaced with ~); truncated if truncatePath is enabled |
main* ↑2 |
Git branch name; * if uncommitted changes; ↑N/↓N for commits ahead/behind upstream |
Claude Sonnet 4.6 |
Active model name; hidden before the first API response |
plan |
Permission mode — only shown when non-default (bypass in red, auto-edit in yellow, plan in cyan) |
Writing tests +2 |
In-progress task label from the Claude Code task list; +N shows pending task count |
⏱ 12m |
Session elapsed time |
████░ 74% (80%) |
Context window bar; usable% (total%) |
85% cache |
Cache hit efficiency from the current context; green ≥ 80%, yellow ≥ 50%, grey below |
$0.023/hr |
Cost burn rate per hour |
$0.042 |
Cumulative session cost |
1.2k tpm |
Tokens per minute (input + output combined) |
+156 -23 |
Lines added (green) and removed (red) this session |
5h ███░░ 60% (!45m/↺2h) |
5-hour rate limit bar; ! predicted exhaustion time, ↺ time until reset |
7d █░░░░ 20% (↺5d) |
7-day rate limit bar |
The bar shows two percentages: usable% (total%).
- usable% — percentage of the usable context (excluding the auto-compact buffer) that has been used; this is what the bar visualises
- total% — raw percentage of the full context window used (shown in grey, in parentheses)
The greyed-out blocks at the right of the bar represent the auto-compact buffer zone (read from CLAUDE_AUTOCOMPACT_PCT_OVERRIDE, defaulting to 20%). The bar color transitions green → yellow → orange → red per barColorThresholds, and starts blinking above contextBlinkThreshold.
The time shown in parentheses after each rate limit bar is:
↺reset time only — if usage is 0% or 100%, or exhaustion time cannot be computed!exhaustion +↺reset — if the limit will be exhausted before it resets:- Yellow if the gap between exhaustion and reset is less than
exhaustionWarningPercentof the period - Red if the gap is larger
- Yellow if the gap between exhaustion and reset is less than
With useRelativeTime: false, times are shown as absolute dates (Thu 27/03 14:00) instead of relative durations.
All options live in the config object at the top of statusline.js. They can also be overridden via settings.json without editing the script — see Overriding via settings.json below.
Default: 5
Width of all progress bars, in block characters.
Default: [50, 65, 80]
Three percentage cutoffs [low, mid, high] that control bar and text color:
| Usage | Color |
|---|---|
| < 50% | Green |
| 50–64% | Yellow |
| 65–79% | Orange |
| ≥ 80% | Red (or blinking red for context bar above contextBlinkThreshold) |
Default: 95
When context total usage exceeds this percentage, the context bar switches to blinking red.
Default: 20
When the predicted rate-limit exhaustion time is within this percentage of the period before the reset, the exhaustion label turns yellow (rather than red).
Default: ' · '
String placed between segment names within a group array.
Default:
{
elapsedTime: '⏱',
gitDirty: '*',
gitAhead: '↑',
gitBehind: '↓',
rateLimitsReset: '↺',
rateLimitsExhaustion:'!',
rateLimits5h: '5h',
rateLimits7d: '7d',
}Short strings and icons used in the output. When overriding via settings.json, only the keys you specify are changed (see merge behaviour below).
Default: 40
Maximum characters for the directory path before truncation (only applied when truncatePath is true). Truncation uses a centre-ellipsis strategy.
Default: 40
Maximum characters for the task label before truncation. Same centre-ellipsis strategy.
Default:
[
'directory',
'git',
'model',
'permissionMode',
'task',
'\n',
'elapsedTime',
'context',
['cache', 'burnRate', 'totalCost', 'tpm'],
'linesChanged',
['rateLimits5h', 'rateLimits7d'],
]Controls which segments appear and in what order. Rules:
- Each entry is a segment name string, a group array, or
'\n'. - A
'\n'entry starts a new output line. - An array of names (e.g.
['cache', 'burnRate', 'totalCost', 'tpm']) groups those segments together, joining them withgroupSeparator(·) instead ofsegmentSeparator(|). - Segments whose data is unavailable are automatically hidden; empty groups are omitted.
Available segment names:
| Name | Description |
|---|---|
burnRate |
Cost burn rate ($/hr) |
cache |
Cache hit efficiency % |
context |
Context window bar with usable% and total% |
directory |
Current working directory path |
elapsedTime |
Session elapsed time |
git |
Branch name, dirty indicator, ahead/behind counts |
linesChanged |
Lines added/removed this session |
model |
Active Claude model name |
permissionMode |
Active permission mode (hidden when default) |
rateLimits5h |
5-hour rate limit bar and reset/exhaustion time |
rateLimits7d |
7-day rate limit bar and reset/exhaustion time |
task |
In-progress task label and pending task count |
totalCost |
Cumulative session cost in USD |
tpm |
Tokens per minute |
Default: ' | '
String placed between top-level segments (and between groups) on the same line.
Default:
{
reset: '\x1b[0m',
bold: '\x1b[1m',
dim: '\x1b[2m',
path: '\x1b[34m', // blue
git: '\x1b[35m', // magenta
accent: '\x1b[36m', // cyan
good: '\x1b[32m', // green
warning: '\x1b[33m', // yellow
caution: '\x1b[38;5;208m',// orange
critical: '\x1b[31m', // red
alert: '\x1b[5;31m', // blinking red
secondary:'\x1b[90m', // grey
}ANSI escape codes for each color role. When overriding via settings.json, only the keys you specify are changed — the rest keep their defaults (see merge behaviour below).
Default: true
When true, directory paths longer than maxPathLength are truncated with a centre ellipsis (…).
Default: true
When true, rate limit times display as relative durations (↺2h30m). When false, they display as absolute timestamps (Thu 27/03 14:00).
You can override any config value by adding a statusLine object to ~/.claude/settings.json alongside the existing type/command keys:
{
"statusLine": {
"type": "command",
"command": "node /home/YOUR_USERNAME/.claude/statusline.js",
"segmentOrder": [
"directory", "git", "model",
"\n",
"elapsedTime", "context", ["burnRate", "totalCost"]
],
"segmentSeparator": " ",
"groupSeparator": " / ",
"barBlockCount": 8,
"maxPathLength": 50,
"maxTaskLength": 30,
"barColorThresholds": [40, 60, 80],
"contextBlinkThreshold": 90,
"exhaustionWarningPercent": 15,
"truncatePath": false,
"useRelativeTime": false,
"theme": {
"path": "\u001b[33m"
},
"labels": {
"elapsedTime": "🕐",
"rateLimits5h": "5H",
"rateLimits7d": "7D"
}
}
}The following top-level keys replace the default entirely when provided:
segmentOrder, segmentSeparator, groupSeparator, barBlockCount, maxPathLength, maxTaskLength, barColorThresholds, contextBlinkThreshold, exhaustionWarningPercent, truncatePath, useRelativeTime
Type-checking is enforced: a wrong type is silently ignored and the default is kept.
theme and labels are not replaced wholesale. Instead, only the keys you provide are updated; all other keys keep their defaults. This means you can change a single icon or color without restating the entire object.
Only existing keys are accepted — unknown keys are silently ignored.
| Path | Purpose |
|---|---|
~/.claude/statusline.js |
The status line script |
~/.claude/settings.json |
Claude Code settings where statusLine is configured and overrides are placed |