11# Claude Code Statusline
22
3- A batteries-included statusline for [ Claude Code] ( https://code.claude.com ) .
4- Shows what the built-in ` /statusline ` can't: live quota with reset countdowns,
5- adaptive polling, model abbreviation, subscription tier, themes, and bar styles.
3+ [ ![ tests] ( https://github.com/thevibeworks/claude-code-statusline/actions/workflows/test.yml/badge.svg )] ( https://github.com/thevibeworks/claude-code-statusline/actions/workflows/test.yml )
4+ [ ![ version] ( https://img.shields.io/github/v/tag/thevibeworks/claude-code-statusline?label=version&sort=semver )] ( https://github.com/thevibeworks/claude-code-statusline/releases )
5+ [ ![ license] ( https://img.shields.io/github/license/thevibeworks/claude-code-statusline )] ( LICENSE )
6+
7+ A batteries-included status bar for [ Claude Code] ( https://code.claude.com ) .
8+ Live quota with reset countdowns, adaptive polling, model abbreviation,
9+ subscription tier, 5 themes, 9 bar styles.
610
711```
8- myproject (main*) +84/-14 8m $6.72 opus4.6[1m][███ ░░░26%] [MAX|feast.t.] 5h[24%] 7d[100%~12h6m]
12+ myproject (main*) +84/-14 8m $6.72 opus4.6[1m][█░░ ░░░26%] [MAX|feast.t.] 5h[24%] 7d[100%~12h6m]
913 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
1014 project branch edits time cost model context user 5h quota 7d quota
1115```
1216
1317## Install
1418
15- ** One-liner** (recommended -- needs ` jq ` and ` curl ` ):
16-
1719``` bash
1820curl -fsSL https://raw.githubusercontent.com/thevibeworks/claude-code-statusline/main/install.sh | bash
1921```
2022
21- Downloads the script, merges into your ` settings.json ` , done.
23+ Downloads the script to ` ~/.claude/ ` , configures ` settings.json ` , done. Needs ` jq ` and ` curl ` .
24+
25+ <details >
26+ <summary >Other install methods</summary >
2227
23- ** Ask Claude Code** -- paste this into any session:
28+ ** Ask Claude Code** -- paste into any session:
2429
2530```
2631Install claude-code-statusline: curl -fsSL https://raw.githubusercontent.com/thevibeworks/claude-code-statusline/main/install.sh | bash
2732```
2833
29- ** Manual** -- if piping curl to bash makes you twitch:
34+ ** Manual: **
3035
3136``` bash
3237curl -fsSL https://raw.githubusercontent.com/thevibeworks/claude-code-statusline/main/statusline.sh -o ~ /.claude/statusline.sh
3338chmod +x ~ /.claude/statusline.sh
3439```
3540
36- Then add to ` ~/.claude/settings.json ` :
41+ Add to ` ~/.claude/settings.json ` :
3742
3843``` json
3944{
@@ -45,61 +50,57 @@ Then add to `~/.claude/settings.json`:
4550}
4651```
4752
48- ## What's New in v0.3.0
49-
50- ** Quota reset countdowns.** Percentages don't answer your actual question:
51-
52- - 5h >= 80%: wall-clock -- ` 5h[87%@14:30] ` -- "can I resume after lunch?"
53- - 7d >= 70%: countdown -- ` 7d[75%~2d5h] ` -- "how long until capacity?"
54- - Below threshold: just the percentage. No noise until you need it.
53+ </details >
5554
56- ** Model abbreviation.** ` claude-opus-4-6 ` becomes ` opus4.6 ` . Short aliases
57- stay unchanged. Version only appears when you've pinned a specific model.
55+ ## Why This Instead of ` /statusline ` ?
5856
59- ## Components
60-
61- Default order: ` activity,time,cost,model,context,user,quota `
57+ Claude Code's built-in [ ` /statusline ` ] ( https://code.claude.com/docs/en/statusline )
58+ generates basic one-off scripts. This does more:
6259
63- | Component | Shows | Example |
64- | ------------| -----------------------------| -----------------------|
65- | ` activity ` | Lines added/removed | ` +84/-14 ` |
66- | ` time ` | API duration | ` 8m ` |
67- | ` cost ` | Session cost | ` $6.72 ` |
68- | ` model ` | Active model (abbreviated) | ` opus4.6[1m] ` |
69- | ` context ` | Context window usage bar | ` [███░░░26%] ` |
70- | ` user ` | Tier + display name | ` [MAX\|feast.t.] ` |
71- | ` quota ` | 5h / 7d quota utilization | ` 5h[24%] 7d[100%~12h6m] ` |
60+ | Feature | ` /statusline ` | This |
61+ | ---------| :---:| :---:|
62+ | Context bar | * | * |
63+ | Cost / duration | * | * |
64+ | Git branch | * | * |
65+ | Live quota (5h/7d) | | * |
66+ | Quota reset countdown | | * |
67+ | Adaptive API polling | | * |
68+ | Subscription tier | | * |
69+ | Model abbreviation | | * |
70+ | Themes / bar styles | | * |
71+ | OAuth credential resolution | | * |
72+ | macOS Keychain support | | * |
7273
73- Custom order: ` --order "model,context,quota" `
74+ ## Features
7475
75- ## Context Window
76+ ### Quota Reset Countdowns
7677
77- Matches the CLI's ` /context ` formula :
78+ When utilization enters the warning zone, reset time appears automatically :
7879
7980```
80- percentage = totalTokens / contextWindow * 100
81+ Low usage: 5h[24%] 7d[10%]
82+ Warning: 5h[87%@14:30] 7d[75%~2d5h]
83+ Critical: 5h[95%@14:30] 7d[88%~2d5h]
8184```
8285
83- Where ` totalTokens = cache_read_input_tokens + input_tokens ` from the latest
84- assistant message.
85-
86- ** 1M auto-detection:** If ` model.id ` contains ` [1m] ` , the window is 1,000,000
87- tokens. Otherwise 200,000. Override with ` CLAUDE_CONTEXT_LIMIT ` .
86+ - ** 5h** : wall-clock time (` @14:30 ` ) -- you're planning your day
87+ - ** 7d** : relative countdown (` ~2d5h ` ) -- you need the duration, not a date
8888
89- Color: green < 85%, yellow >= 85%, red >= 100% .
89+ Thresholds: 5h at 80% ( yellow), 7d at 70% (yellow) .
9090
91- ## Quota
91+ ### Model Abbreviation
9292
93- Format: ` 5h[24%] 7d[100%~12h6m] op[45%] `
93+ Full model IDs get shortened. Aliases stay unchanged.
9494
95- - ** 5h** -- 5-hour rolling window. Yellow at 80%, red at 90%.
96- - ** 7d** -- 7-day aggregate. Yellow at 70%, red at 85%.
97- - ** op** -- Opus-specific 7d (MAX users only).
98- - ** sn** -- Sonnet-specific 7d (PRO / TEAM / ENT users).
95+ ```
96+ claude-opus-4-6[1m] --> opus4.6[1m] (pinned version)
97+ opus[1m] --> opus[1m] (alias, unchanged)
98+ claude-haiku-4-5-* --> haiku4.5
99+ ```
99100
100101### Adaptive Polling
101102
102- Doesn't hammer the API. TTL scales with 5h utilization:
103+ Quota polling scales with usage. Doesn't waste API calls when you're idle.
103104
104105| 5h Utilization | Poll Interval |
105106| ----------------| ---------------|
@@ -108,91 +109,131 @@ Doesn't hammer the API. TTL scales with 5h utilization:
108109| 50-79% | 1 min |
109110| >= 80% | 30 sec |
110111
111- Error backoff: 2 min.
112+ Error backoff: 2 min. Atomic cache writes via tmp+mv.
112113
113- ### OAuth Gate
114+ ### Context Window
114115
115- Quota and user components are ** skipped** when ` ANTHROPIC_API_KEY ` ,
116- ` ANTHROPIC_AUTH_TOKEN ` , or ` ANTHROPIC_BASE_URL ` is set. The usage endpoint
117- only works with OAuth tokens at ` api.anthropic.com ` .
116+ Matches the CLI's ` /context ` formula exactly:
118117
119- ### Credentials
118+ ```
119+ percentage = totalTokens / contextWindow * 100
120+ ```
120121
121- 1 . ** Linux:** ` ~/.claude/.credentials.json ` (` claudeAiOauth.accessToken ` )
122- 2 . ** macOS:** Keychain first, plaintext fallback
123- 3 . ** OrbStack:** resolves real ` $HOME ` via ` getent passwd `
122+ 1M auto-detected from ` model.id ` ` [1m] ` suffix. Override: ` CLAUDE_CONTEXT_LIMIT ` .
124123
125- ## Themes ( ` --theme ` )
124+ ## Components
126125
127- | Theme | What you get |
126+ Default order: ` activity,time,cost,model,context,user,quota `
127+
128+ | Component | Shows | Example |
129+ | ------------| -----------------------------| ----------------------- |
130+ | ` activity ` | Lines added/removed | ` +84/-14 ` |
131+ | ` time ` | API duration | ` 8m ` |
132+ | ` cost ` | Session cost | ` $6.72 ` |
133+ | ` model ` | Active model (abbreviated) | ` opus4.6[1m] ` |
134+ | ` context ` | Context window usage bar | ` [█░░░░░26%] ` |
135+ | ` user ` | Tier + display name | ` [MAX\|feast.t.] ` |
136+ | ` quota ` | 5h / 7d utilization | ` 5h[24%] 7d[100%~12h6m] ` |
137+
138+ Reorder: ` --order "model,context,quota" `
139+
140+ ## Themes and Styles
141+
142+ <details >
143+ <summary >5 themes, 9 bar styles</summary >
144+
145+ ### Themes (` --theme ` )
146+
147+ | Theme | Layout |
128148| -------------| --------------------------------------|
129149| ` minimal ` | Model + context + user only |
130150| ` compact ` | Everything, unicode bars (default) |
131151| ` detailed ` | Bracketed bars, working path |
132152| ` developer ` | Dot bars, right-aligned, full path |
133153| ` manager ` | Percent only, cost prominent |
134154
135- ## Bar Styles (` --style ` )
155+ ### Bar Styles (` --style ` )
156+
157+ | Style | Output |
158+ | --------------------| -------------------------|
159+ | ` unicode-blocks ` | ` [███░░░42%] ` (default) |
160+ | ` single-block ` | ` ▓ 42% ` |
161+ | ` bracketed-bars ` | ` [████░░░░] 42% ` |
162+ | ` filled-dots ` | ` ●●●○○○ 42% ` |
163+ | ` square-blocks ` | ` ▰▰▰▱▱▱ 42% ` |
164+ | ` line-segments ` | ` ━━━┅┅┅ 42% ` |
165+ | ` ascii-bars ` | ` \|\|\|░░░ 42% ` |
166+ | ` percent-only ` | ` 42% ` |
167+ | ` fraction-display ` | ` 3/8 ` |
136168
137- | Style | Output |
138- | --------------------| ------------------------|
139- | ` unicode-blocks ` | ` [███░░░42%] ` (default)|
140- | ` single-block ` | ` ▓ 42% ` |
141- | ` bracketed-bars ` | ` [████░░░░] 42% ` |
142- | ` filled-dots ` | ` ●●●○○○ 42% ` |
143- | ` square-blocks ` | ` ▰▰▰▱▱▱ 42% ` |
144- | ` line-segments ` | ` ━━━┅┅┅ 42% ` |
145- | ` ascii-bars ` | ` \|\|\|░░░ 42% ` |
146- | ` percent-only ` | ` 42% ` |
147- | ` fraction-display ` | ` 3/8 ` |
169+ </details >
148170
149- ## Options
171+ ## Configuration
150172
151173```
152174--style <style> Progress bar style
153- --theme <theme> Preset theme (overrides style/order/path/alignment)
154- --order <csv> Component order: activity,time,cost,model,context,user,quota
175+ --theme <theme> Preset (overrides style/order/path/alignment)
176+ --order <csv> Component order
155177--path-display <type> project | cwd | full | relative
156178--alignment <type> left-right | right-left | center
157179--debug Log to /tmp/claude-code-statusline.log
158- --test [json] Test mode (pipe JSON or pass as argument)
180+ --test [json] Test mode
159181```
160182
161- ## Environment Variables
183+ | Variable | Default | Purpose |
184+ | ----------------------------------| ------------------| -------------------------------|
185+ | ` CLAUDE_CONTEXT_LIMIT ` | auto | Context token limit override |
186+ | ` CLAUDE_DATA_DIR ` | script directory | Usage log location |
187+ | ` CLAUDE_CACHE_DIR ` | ` $DATA_DIR/sessions ` | Quota/profile cache |
188+ | ` CLAUDE_CODE_MAX_OUTPUT_TOKENS ` | ` 32000 ` | Max output tokens |
189+ | ` CLAUDE_CONFIG_DIR ` | ` ~/.claude ` | Claude config directory |
190+
191+ <details >
192+ <summary >OAuth gate and credentials</summary >
193+
194+ Quota/user components are ** skipped** when ` ANTHROPIC_API_KEY ` ,
195+ ` ANTHROPIC_AUTH_TOKEN ` , or ` ANTHROPIC_BASE_URL ` is set.
162196
163- | Variable | Default | Purpose |
164- | ----------------------------------| ------------------| ---------------------------------------|
165- | ` CLAUDE_CONTEXT_LIMIT ` | auto | Override context token limit |
166- | ` CLAUDE_DATA_DIR ` | script directory | Where ` usage.jsonl ` lives |
167- | ` CLAUDE_CACHE_DIR ` | ` $CLAUDE_DATA_DIR/sessions ` | Quota/profile cache |
168- | ` CLAUDE_CODE_MAX_OUTPUT_TOKENS ` | ` 32000 ` | Max output tokens |
169- | ` CLAUDE_CONFIG_DIR ` | ` ~/.claude ` | Claude config directory |
197+ Credential resolution:
198+ 1 . ** Linux:** ` ~/.claude/.credentials.json `
199+ 2 . ** macOS:** Keychain first, plaintext fallback
200+ 3 . ** OrbStack:** resolves real ` $HOME ` via ` getent passwd `
201+
202+ </details >
170203
171204## Testing
172205
173- Pipe JSON to verify output:
206+ ``` bash
207+ bats t/ # 50 tests (needs: npm install -g bats)
208+ ```
209+
210+ Or pipe mock JSON directly:
174211
175212``` bash
176- echo ' {"model":{"id":"claude-opus-4-6-20251101 [1m]","display_name":"Opus"},"cwd":"/home/dev/ project","cost":{"total_cost_usd":6.72,"total_lines_added":84,"total_lines_removed":14,"total_api_duration_ms":480000}}' \
177- | bash ~ /.claude/ statusline.sh --test
213+ echo ' {"model":{"id":"claude-opus-4-6[1m]","display_name":"Opus"},"cwd":"/tmp/ project","cost":{"total_cost_usd":6.72,"total_lines_added":84,"total_lines_removed":14,"total_api_duration_ms":480000},"version":"2.1.139" }' \
214+ | bash statusline.sh --test
178215```
179216
180- Add ` --debug ` to dump diagnostics to ` /tmp/claude-code-statusline.log ` .
217+ ## Project Structure
218+
219+ ```
220+ statusline.sh Main script (single file, no dependencies beyond jq/curl)
221+ install.sh One-liner installer (downloads + configures settings.json)
222+ t/
223+ statusline.bats 38 unit + integration tests
224+ install.bats 12 install tests (mock curl, isolated $HOME)
225+ helpers.bash Test helper (sources functions from real statusline.sh)
226+ ```
181227
182- ## Official Docs
228+ ## Contributing
183229
184- The [ Claude Code statusline documentation] ( https://code.claude.com/docs/en/statusline )
185- covers the built-in JSON fields (` context_window.used_percentage ` ,
186- ` rate_limits.five_hour.resets_at ` , etc.) and basic configuration.
230+ See [ CONTRIBUTING.md] ( CONTRIBUTING.md ) . Short version: run ` bats t/ ` before pushing.
187231
188- This script uses all of those fields and adds quota tracking with reset
189- countdowns, adaptive polling, subscription tier display, and model abbreviation
190- -- things the official examples don't cover.
232+ ## Acknowledgments
191233
192- Worth knowing from the official docs: settings live in ` ~/.claude/settings.json ` ;
193- ` refreshInterval ` enables periodic updates; script fires after each assistant
194- message (debounced 300ms); ` disableAllHooks: true ` kills the statusline too.
234+ Built on the [ Claude Code statusline API] ( https://code.claude.com/docs/en/statusline ) .
235+ API contract verified against Claude Code CLI v2.1.76 and v2.1.139 binaries.
195236
196237## License
197238
198- MIT
239+ [ MIT] ( LICENSE )
0 commit comments