A bun TypeScript statusline for Claude CLI with color-coded context usage indicators
npm install claude-cli-statuslineA TypeScript statusline for Claude CLI that displays project info, git status, model, and context usage with color-coded indicators.


1. Ensure you have Bun installed
2. Add to your Claude config (~/.claude/settings.json or your project's .claude/settings.local.json):
``json`
{
"statusLine": {
"type": "command",
"command": "bunx claude-cli-statusline"
}
}
You can optionally install it globally with Bun to avoid bunx downloading it:
`bash`
bun add -g claude-cli-statusline
2. Clone or copy this repo to your home directory (e.g., ~/claude-cli-statusline)~/.claude/settings.json
3. Add to your Claude config ( or your project's .claude/settings.local.json):
`json`
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts"
}
}
Or with a custom config file:
`json`
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --config=my-config.json"
}
}
Note: Adjust the path if you installed it elsewhere.
Default ("extend" layout - single line):
``
๐ฆ project-name ๐ relative/dir ๐๐ โ branch ๐ง Model โฌ 89%โฆ67%โก๏ธ200K ๐ Explore ๐ต $0.05 โฑ๏ธ 1h23m
Without sub-agent active:
``
๐ฆ project-name ๐ relative/dir ๐๐ โ branch ๐ง Model โฌ 89%โฆ67%โก๏ธ200K ๐ต $0.05 โฑ๏ธ 1h23m
With "render-layout": "normal" (basic info only):
``
๐ฆ project-name ๐ relative/dir ๐๐ โ branch ๐ง Model โฌ 89%โฆ67%โก๏ธ200K ๐ Explore
With "render-layout": "layout-2-line" (two lines):
``
๐ฆ project-name ๐ relative/dir
๐๐ โ branch ๐ง Model โฌ 89%โฆ67%โก๏ธ200K ๐ Explore
Icons:
- ๐ฆ Project root directory (basename only by default)
- With show-project-full-dir: true in config: shows full path like ~/path/to/projectshow-git-repo-name: true
- ๐ Current relative directory
- ๐ Git repo (octopus icon only by default)
- ๐ Clean working tree (๐ข green) - no uncommitted changes
- ๐ ๏ธ Dirty working tree (๐ก yellow) - has uncommitted changes
- ๐ค Staged changes (๐ต light blue) - changes ready to commit
- With in config:๐๐ ๐ฆ
- when repo name matches directory name๐๐ repo-name
- when repo name differs from directory namegit@github.com:user/my-repo.git
- Git repo name is extracted from remote URL (e.g., โ my-repo)89%โฆ67%โก๏ธ200K
- โ Git branch (๐ข green if in repo, ๐ก yellow if no repo)
- โ
No git repository
- ๐ง Model name
- โฌ Context display:
- First percentage (89%): Total remaining context
- โฆ separator
- Second percentage (67%): Remaining before auto-compact (calculated as percentage of usable space after buffer)
- โก๏ธ Not compacted or ๐ซ if context was compacted (auto or manual)
- Max context window (200K, 1M, etc.) with cyan-colored K/M suffix
Context Colors:
- ๐ข Green: >65% remaining
- ๐ก Yellow: 45-65% remaining
- ๐ Orange: 20-45% remaining
- ๐ด Red: <20% remaining
Layout:
The statusline uses a single-line layout by default. You can customize the layout using the render-layout config option or the --layout CLI flag. See the render-layout section for details.
The statusline supports an optional animated spinner with multiple style choices:
Available spinner styles:
- transportation (default): ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐weather
- : โ๏ธ ๐ค๏ธ โ
๐ฅ๏ธ โ๏ธ ๐ฆ๏ธ ๐ง๏ธ โ๏ธhearts
- : โค๏ธ ๐งก ๐ ๐ ๐ ๐ ๐ค ๐คfruit
- : ๐ ๐ ๐ ๐ ๐ซ ๐ ๐ ๐planets
- : ๐ ๐ช ๐ ๐ ๐ ๐ ๐ ๐circles
- : ๐ด ๐ ๐ก ๐ข ๐ต ๐ฃ ๐ค โซsports
- : โฝ ๐ ๐ โพ ๐พ ๐ ๐ ๐ฑflowers
- : ๐น ๐บ ๐ป ๐ผ ๐ท ๐ธ ๐ ๐ต๏ธhands
- : โ ๐ค ๐๏ธ ๐ ๐ค ๐คarrows
- : โก๏ธ โ๏ธ โฌ๏ธ โ๏ธ โฌ
๏ธ โ๏ธ โฌ๏ธ โ๏ธmoon
- : ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐clock
- : ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐circular
- : โ โด โ โท โ โถ โ โตbraille
- : โ โ โ น โ ธ โ ผ โ ด โ ฆ โ ง โ โ dots
- : โ โ โ โก โข โ โ โ blocks
- : โ โ โ โ
Example with animations (transportation):
``
๐ 75%โฆ52%โก๏ธ200K๐
Enable animations in config:
`json`
{
"animations": {
"enabled": true,
"spinner": "transportation"
}
}
Or use CLI:
`bash`
bun ~/claude-cli-statusline/index.ts --spinner=hearts
Note: When animations are enabled, the spinner appears after the max context window.
Note: Animations are disabled by default to maintain a clean, static statusline.
You can pass options to customize the statusline behavior:
Specify a custom config file. If the path is relative, it searches in order:
1. Project .claude/ directory~/.claude/
2. User directory
3. Script directory
Default: statusline-config.json
Examples:
`bashUse absolute path
bun ~/claude-cli-statusline/index.ts --config=/path/to/my-config.json
$3
Customize the color thresholds for context usage display. Values must be integers between 0-100 and in descending order.
Default:
--context-levels=65,45,20Example:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --context-levels=75,50,25"
}
}
`This sets:
- Green: >75% remaining
- Yellow: 50-75% remaining
- Orange: 25-50% remaining
- Red: <25% remaining
$3
Save the input JSON to a file for debugging purposes.
Default filename:
sample-input.jsonExample:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --save-sample"
}
}
`Or with custom filename:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --save-sample=debug.json"
}
}
`$3
Specify the statusline layout. Can be a predefined layout name or a custom layout name you've defined.
Predefined layouts:
-
normal - Basic info only
- extend - Adds cost & duration (default)
- full - Everything including lines
- layout-1-line - Legacy alias for normal
- layout-2-line - Two linesExample:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --layout=extend"
}
}
`Note: This CLI flag overrides the
render-layout setting in the config file.$3
Specify the animated spinner style. Choose from 16 different styles.
Available styles:
transportation, weather, hearts, fruit, planets, circles, sports, flowers, hands, arrows, moon, clock, circular, braille, dots, blocksExample:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts --spinner=hearts"
}
}
`Note: This CLI flag overrides the
animations.spinner setting in the config file. Animations must be enabled separately with animations.enabled: true in your config.Available Widgets
The statusline displays information through widgets that can be arranged using layouts. Each widget shows a specific metric:
| Widget | Icon | Description |
|--------|------|-------------|
|
project | ๐ฆ | Project directory name (workspace root) |
| cwd | ๐ | Current working directory relative to project root |
| git | ๐ | Git repository status (clean/dirty/staged) and branch name |
| model | ๐ง | AI model name (e.g., "Sonnet 4.5") |
| context | โฌ | Context usage (remaining % before full/compact, max tokens) |
| subagent | ๐ | Currently active sub-agent (e.g., "Code-Reviewer", "Explore") |
| cost | ๐ต | Total session cost in USD (cumulative across context resets) |
| lines | ๐ | Lines added/removed during session (vanity metric, doesn't reset with context) |
| duration | โฑ๏ธ | Total session duration in hours/minutes (cumulative across context resets) |Note on metrics:
- Actionable:
git status tells you if you need to commit changes, subagent shows which specialist is handling the task
- Informational: context shows when compaction will occur
- Vanity metrics: cost, lines, and duration are cumulative session stats that don't reset with /clearConfig
The config is reloaded on every statusline update, so you can modify it while Claude CLI is running.
$3
See statusline-config.json for the default configuration file with all available options and their default values.
$3
When using relative paths (default or via
--config), files are searched in:1. Project:
.claude/ in workspace project directory
2. User: ~/.claude/ in home directory
3. Script: in statusline script directory$3
The number of tokens to reserve as a buffer before auto-compact. Claude CLI automatically compacts the conversation when remaining tokens reach this threshold.
Default:
45000 tokensThis setting affects the second percentage in the display (e.g.,
89%โฆ67%):- First percentage: Total remaining context (89% = 178K tokens remaining out of 200K)
- Second percentage: Remaining before auto-compact (67% = percentage of usable space remaining)
- Calculation:
(usableSpace - used) / usableSpace * 100
- Where usableSpace = maxTokens - compactBuffer
- This matches Claude CLI's buffer calculation methodWhen the second percentage reaches 0%, Claude CLI will auto-compact the conversation, which resets the context and may cause the percentages to jump back up.
$3
An array of three descending integers [green, yellow, orange] that define the thresholds for context remaining percentage:
- First value: minimum % for green (default: 65)
- Second value: minimum % for yellow (default: 45)
- Third value: minimum % for orange (default: 20)
- Below third value: red
Note: CLI flag
--context-levels overrides these config values.$3
A mapping of model IDs to their context window sizes in tokens. This is used to calculate the remaining context percentage from the transcript usage data.
Add entries here if you need to support additional models or if Claude releases models with different context windows.
Default: 200,000 tokens for unknown models
$3
A mapping of model display names to their context window sizes. Used as a fallback when model ID is not found.
Example:
`json
{
"display-name-model-context-windows": {
"Sonnet 4.5": 200000,
"Opus 4": 200000,
"Haiku 4": 200000
}
}
`When a context window is found via display name, it shows with a ๐ท๏ธ indicator:
โฌ 60%โฆ15%๐ซ200K๐ท๏ธ$3
The default context window size to use when neither model ID nor display name is found in the config.
Default:
200000 tokensWhen using the default, it shows with a โ๏ธ indicator:
โฌ 60%โฆ15%๐ซ200Kโ๏ธPerformance Optimizations
$3
You can place configuration files at different levels:
Project-level (
.claude/statusline-config.json):`bash
cd /path/to/your/project
mkdir -p .claude
cat > .claude/statusline-config.json << 'EOF'
{
"context-color-levels": [70, 50, 25],
"save-sample": {
"enable": true,
"filename": "debug-input.json"
}
}
EOF
`User-level (
~/.claude/statusline-config.json):`bash
mkdir -p ~/.claude
cat > ~/.claude/statusline-config.json << 'EOF'
{
"context-color-levels": [65, 45, 20],
"model-context-windows": {
"claude-sonnet-4-5-20250929": 200000
}
}
EOF
`This allows you to have different settings per project while maintaining user-wide defaults.
$3
An object to control saving the input JSON on every statusline update. Useful for debugging or analyzing the data structure Claude CLI provides.
Properties:
-
enable (boolean): Enable/disable sample saving
- filename (string): The filename to use when savingDefault:
`json
{
"enable": false,
"filename": "sample-input.json"
}
`Note: You can change
enable to true while Claude CLI is running, and the next statusline update will start saving samples. The CLI flag --save-sample[=filename] overrides these config values.$3
Controls whether to show the git repository name in the statusline.
Default:
false (disabled)When
false (default):
- Shows only: ๐ โ branch (octopus icon + branch)When
true:
- Shows ๐ ๐ฆ โ branch if repo name matches directory name
- Shows ๐ repo-name โ branch if repo name differs from directory nameGit repo name detection:
- First tries to extract from remote URL:
git remote get-url origin
- For example: git@github.com:user/my-repo.git โ my-repo
- Falls back to directory basename if no remote is configuredExample:
`json
{
"show-git-repo-name": true
}
`Why disabled by default: This keeps the statusline shorter and cleaner, as the repository name is often redundant with the project directory name. Enable it if you work in directories where the folder name differs from the actual git repository name (e.g., cloned with a different name, renamed directory, or forked repos).
$3
Controls whether to show the full project directory path or just the basename.
Default:
false (disabled - shows basename only)When
false (default):
- Shows only basename: ๐ฆ project-nameWhen
true:
- Shows full path with home shortening: ๐ฆ ~/path/to/project-nameExample:
`json
{
"show-project-full-dir": true
}
`Why disabled by default: The basename is usually sufficient and keeps the statusline more concise. Enable it if you need to distinguish between multiple projects with the same name in different locations.
$3
Customize the icons used to indicate git repository status (staged/clean/dirty).
Default:
`json
{
"clean": "๐",
"dirty": "๐ ๏ธ",
"staged": "๐ค"
}
`Status combinations:
- Clean (no changes):
๐๐ (octopus + gem in green)
- Unstaged changes: ๐๐ ๏ธ (octopus + tools in yellow)
- Staged changes: ๐๐ค (octopus + outbox in light blue)
- Staged + unstaged: ๐๐ค๐ ๏ธ (staged with additional unstaged changes)Example (using different icons):
`json
{
"git-status-icons": {
"clean": "โ",
"dirty": "โ",
"staged": "โ"
}
}
`Note: The icons are displayed directly adjacent to the octopus git icon (๐) with no space between them. When there are staged changes, only the staged icon (๐ค) is shown. The dirty icon (๐ ๏ธ) is only shown if there are unstaged changes. The clean icon (๐) is only shown when there are no changes at all (no staged, no unstaged).
$3
Controls the layout and ordering of statusline components. You can use predefined layouts or create custom layouts.
Default:
"extend" (single line with cost and duration)Predefined Layouts:
-
"normal" - Basic info only: ["project cwd git model context subagent"]
- "extend" - Adds cost & duration: ["project cwd git model context subagent cost duration"] (default)
- "full" - Everything including lines: ["project cwd git model context subagent cost lines duration"]
- "layout-1-line" - Legacy alias for normal
- "layout-2-line" - Two lines: ["project cwd", "git model context subagent"]Available widgets for custom layouts:
You can use any combination of:
project, cwd, git, model, context, subagent, cost, lines, durationSee the Available Widgets section for details on what each widget displays.
Examples:
Using predefined layouts:
`json
{
"render-layout": "normal" // Basic info only
}
``json
{
"render-layout": "extend" // Adds cost & duration (default)
}
``json
{
"render-layout": "full" // Everything including lines
}
``json
{
"render-layout": "layout-1-line" // Legacy alias for "normal"
}
`Custom single line:
`json
{
"render-layout": ["project cwd git model context"]
}
`Custom two lines:
`json
{
"render-layout": [
"project cwd",
"git model context"
]
}
`Custom order (context first):
`json
{
"render-layout": [
"context model",
"project cwd git"
]
}
`Minimal (git and context only):
`json
{
"render-layout": ["git context"]
}
`Model Isolation Feature
Problem: Claude CLI updates the user-level settings (
~/.claude/settings.json) whenever you change models. This causes all other CLI sessions to immediately pick up the model change, which is often unexpected behavior.Solution: The statusline automatically isolates model selections per project by moving them from user-level to project-level settings.
$3
When you change models in Claude CLI:
1. User picks a specific model (e.g., Sonnet, Opus):
- Statusline detects the user settings file was recently modified (within 5 seconds)
- Moves
model from ~/.claude/settings.json to .claude/settings.local.json in your project
- Clears it from user settings so other projects aren't affected
- Result: This model choice only affects the current project2. User picks "Default":
- Statusline detects user settings was recently modified with no model set
- Removes
model from project-local settings if it was set before user settings
- Result: Project returns to using whatever default is configured$3
- โ Model selections are project-specific
- โ Multiple Claude CLI sessions can use different models without interfering
- โ Other projects maintain their own model preferences
- โ Completely automatic - no manual file editing needed
$3
This feature is enabled by default via the
clear-model config option:`json
{
"clear-model": true
}
`To disable (not recommended):
`json
{
"clear-model": false
}
`Why enabled by default: This fixes unexpected behavior where changing models in one terminal session affects all other sessions. Most users want project-specific model selections.
Development
$3
Run the test suite:
`bash
bun test
`Run with coverage:
`bash
bun coverage
`$3
The project uses Bun as the runtime and doesn't require compilation. All TypeScript files are executed directly.
$3
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Ensure all tests pass
6. Submit a pull request
Debugging
If the context usage shows "โ" instead of a percentage, use the debug script to see what data is available:
$3
Edit your Claude config to use the debug script:
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/tools/debug.ts"
}
}
`$3
Start a Claude CLI session and observe the debug output. It will show:
- The complete JSON structure passed to the statusline
- Whether a
budget field exists
- The transcript file path$3
If a transcript path is shown, you can manually inspect it:
`bash
cat /path/to/transcript.json | jq .
`Look for fields like:
-
usage
- metadata
- budget
- messages[].usage
- Any fields containing "token", "context", or "budget"$3
If you find token usage data in a different location, update
index.ts to include those field names in the appropriate arrays:-
maxKeys - for maximum token limits
- usedKeys - for tokens used
- remainingKeys - for tokens remaining
- remainingPctKeys - for direct percentage values$3
`json
{
"statusLine": {
"type": "command",
"command": "bun ~/claude-cli-statusline/index.ts"
}
}
``