@promptctl/claude-powerline
v0.2.3
Published
Powerline statusline for Claude Code — fork of @owloops/claude-powerline with CLI override flags (--layout, --set, --show, --display, --segment) so the entire config can live in settings.json without a separate config file.
Maintainers
Readme
Claude Powerline
Powerline statusline for Claude Code — fork of @promptctl/claude-powerline with CLI override flags so the entire config can live in settings.json without a separate file.
What this fork adds
--layout— define lines and segment ordering inline ("directory git | model context block").--show— enable multipleshow*booleans on a segment in one flag (--show git=workingTree,upstream,timeSinceCommit).--display— set multipledisplay.*fields in one flag (--display autoWrap=false,padding=1).--segment— set multiple segment fields in one flag (--segment block.type=weighted,sessionId.length=8).--set— universal escape hatch for any dotted config path (--set color.git=#3a3a3a/#d0d0d0).install/install-url-handlersubcommands (macOS) — one-shot setup that installs a URL handler app and writes the renderer command into~/.claude/settings.json. Combined withclickActionon the sessionId segment, cmd-clicking the sessionId in your terminal copies the full id to your clipboard.
All flags slot into the existing config precedence chain (CLI > env > file > defaults). See --help for the full reference.
Quick start (macOS)
pnpm dlx @promptctl/claude-powerline@latest installThat single command:
- Builds
~/Applications/PromptCtl URL Handler.appand registers thecpwl://URL scheme with macOS Launch Services. - Copies the runtime into
~/Library/Application Support/PromptCtl/url-handler.mjs(stable path independent of pnpm cache). - Writes the statusline renderer command into
~/.claude/settings.json.
Restart Claude Code. The statusline appears, and cmd-clicking the sessionId copies the full id to your clipboard.
To override the default config, pass renderer flags after install:
pnpm dlx @promptctl/claude-powerline@latest install \
--style=capsule \
--layout 'directory model session' \
--show git=workingTreeInstallation
Requires Node.js 18+, Claude Code, and Git 2.0+. For best display, install a Nerd Font or use --charset=text for ASCII-only symbols.
Setup Wizard (Recommended)
The interactive wizard walks you through theme, style, font, segment, and budget selection.
# run inside Claude Code, one at a time
/plugin marketplace add Owloops/claude-powerline
/plugin install claude-powerline@claude-powerline
/powerlineThe wizard writes ~/.claude/claude-powerline.json and updates your settings.json automatically. Run /powerline again any time to reconfigure.
Manual Setup
If you'd rather skip the install subcommand, you can edit settings.json directly. Important: pin the version, don't use @latest. pnpm dlx caches aggressively and @latest will keep resolving to whatever was first cached, never picking up new releases. The install subcommand handles this for you by baking the current version into the command at setup time.
{
"statusLine": {
"type": "command",
"command": "pnpm dlx @promptctl/[email protected] --style=powerline"
}
}To upgrade later, re-run pnpm dlx @promptctl/claude-powerline@latest install (or update the pinned version in settings.json).
Powerline Studio
powerline.owloops.com is a visual configurator for claude-powerline. Click segments in the preview to toggle options, switch styles and themes live, reorder, then copy or download the JSON into ~/.claude/claude-powerline.json. Paste an existing config to edit it.
6 built-in themes (dark, light, nord, tokyo-night, rose-pine, gruvbox) or create your own.
Config locations (in priority order):
./.claude-powerline.json- Project-specific~/.claude/claude-powerline.json- User config~/.config/claude-powerline/config.json- XDG standard
Override priority: CLI flags > Environment variables > Config files > Defaults
Config files reload automatically, no restart needed.
Get example config:
curl -o ~/.claude/claude-powerline.json https://raw.githubusercontent.com/Owloops/claude-powerline/main/.claude-powerline.jsonCLI Options (both --arg value and --arg=value syntax supported):
--theme-dark(default),light,nord,tokyo-night,rose-pine,gruvbox,custom--style-minimal(default),powerline,capsule,tui--charset-unicode(default),text--config- Custom config file path--help- Show help
Examples:
claude-powerline --theme=nord --style=powerline
claude-powerline --theme=dark --style=capsule --charset=text
claude-powerline --config=/path/to/config.jsonEnvironment Variables:
export CLAUDE_POWERLINE_THEME=dark
export CLAUDE_POWERLINE_STYLE=powerline
export CLAUDE_POWERLINE_CONFIG=/path/to/config.json
export CLAUDE_POWERLINE_DEBUG=1 # Enable debug loggingSegment Configuration
"directory": {
"enabled": true,
"style": "full"
}Options:
style: Display format -full|fish|basenamefull: Show complete path (e.g.,~/projects/claude-powerline)fish: Fish-shell style abbreviation (e.g.,~/p/claude-powerline)basename: Show only folder name (e.g.,claude-powerline)
"git": {
"enabled": true,
"showSha": true,
"showWorkingTree": false,
"showOperation": false,
"showTag": false,
"showTimeSinceCommit": false,
"showStashCount": false,
"showUpstream": false,
"showRepoName": false
}Options:
showSha: Show abbreviated commit SHAshowWorkingTree: Show staged/unstaged/untracked countsshowOperation: Show ongoing operations (MERGE/REBASE/CHERRY-PICK)showTag: Show nearest tagshowTimeSinceCommit: Show time since last commitshowStashCount: Show stash countshowUpstream: Show upstream branchshowRepoName: Show repository name
Symbols:
- Unicode:
⎇Branch •♯SHA •⌂Tag •⧇Stash •✓Clean •●Dirty •⚠Conflicts •↑3Ahead •↓2Behind •(+1 ~2 ?3)Staged/Unstaged/Untracked - Text:
~Branch •#SHA •TTag •SStash •=Clean •*Dirty •!Conflicts •^3Ahead •v2Behind •(+1 ~2 ?3)Staged/Unstaged/Untracked
"model": {
"enabled": true
}Symbols: ✱ Model (unicode) • M Model (text)
"session": {
"enabled": true,
"type": "tokens",
"costSource": "calculated"
}Options:
type: Display format -cost|tokens|both|breakdowncostSource: Cost calculation method -calculated(ccusage-style) |official(hook data)
Symbols: § Session (unicode) • S Session (text)
"today": {
"enabled": true,
"type": "cost"
}Options:
type: Display format -cost|tokens|both|breakdown
Symbols: ☉ Today (unicode) • D Today (text)
"context": {
"enabled": true,
"showPercentageOnly": false,
"displayStyle": "text",
"autocompactBuffer": 33000
}Options:
showPercentageOnly: Show only percentage remaining (default: false)displayStyle: Visual style for context display (default:"text")autocompactBuffer: Number of tokens reserved as the auto-compact trigger zone (default:33000). The usable percentage reflects how close you are to the point where compaction fires. Set to0if you have auto-compact disabled to show raw context usage insteadpercentageMode: How to display the percentage."remaining"counts down from 100% (context left),"used"counts up from 0% (context consumed). Default depends on display style:"remaining"fortext,"used"for bar styles
Display Styles:
| Style | Filled | Empty | Example |
|-------|--------|-------|---------|
| text | -- | -- | ◔ 34,040 (79%) |
| ball | ─ | ─ | ─────●──── 50% |
| bar | ▓ | ░ | ▓▓▓▓▓░░░░░ 50% |
| blocks | █ | ░ | █████░░░░░ 50% |
| blocks-line | █ | ─ | █████───── 50% |
| capped | ━ | ┄ | ━━━━╸┄┄┄┄┄ 50% |
| dots | ● | ○ | ●●●●●○○○○○ 50% |
| filled | ■ | □ | ■■■■■□□□□□ 50% |
| geometric | ▰ | ▱ | ▰▰▰▰▰▱▱▱▱▱ 50% |
| line | ━ | ┄ | ━━━━━┄┄┄┄┄ 50% |
| squares | ◼ | ◻ | ◼◼◼◼◼◻◻◻◻◻ 50% |
Symbols: ◔ Context (unicode) • C Context (text)
Model Context Limits
Configure context window limits for different model types. Defaults to 200K tokens for all models.
"modelContextLimits": {
"sonnet": 1000000,
"opus": 200000
}Available Model Types:
sonnet: Claude Sonnet models (3.5, 4, etc.)opus: Claude Opus modelsdefault: Fallback for unrecognized models (200K)
Note: Sonnet 4's 1M context window is currently in beta for tier 4+ users. Set "sonnet": 1000000 when you have access.
"block": {
"enabled": true,
"displayStyle": "text"
}Options:
displayStyle: Visual style for utilization display (see table below)
Requires Claude Code's native rate_limits hook data (Claude.ai Pro/Max subscribers). Displays the official 5-hour utilization percentage and reset countdown. Hidden when native data is unavailable.
Display Styles:
| Style | Example |
|-------|---------|
| text (default) | ◱ 23% (4h 12m) |
| bar | ◱ ▪▪▫▫▫▫▫▫▫▫ 23% (4h 12m) |
| blocks | ◱ ██░░░░░░░░ 23% (4h 12m) |
| blocks-line | ◱ ██──────── 23% (4h 12m) |
| capped | ◱ ━╸┄┄┄┄┄┄┄┄ 23% (4h 12m) |
| dots | ◱ ●●○○○○○○○○ 23% (4h 12m) |
| filled | ◱ ■■□□□□□□□□ 23% (4h 12m) |
| geometric | ◱ ▰▰▱▱▱▱▱▱▱▱ 23% (4h 12m) |
| line | ◱ ━━┄┄┄┄┄┄┄┄ 23% (4h 12m) |
| squares | ◱ ◼◼◻◻◻◻◻◻◻◻ 23% (4h 12m) |
| ball | ◱ ──●─────── 23% (4h 12m) |
Symbols: ◱ Block (unicode) • B Block (text)
"weekly": {
"enabled": true,
"displayStyle": "text"
}Options:
displayStyle: Visual style for utilization display - same options as the block segment (see table above)
Only visible when Claude Code provides native rate_limits.seven_day data (Claude.ai Pro/Max subscribers). Hidden when the data is not available.
Symbols: ◑ Weekly (unicode) • W Weekly (text)
"metrics": {
"enabled": true,
"showResponseTime": true,
"showLastResponseTime": false,
"showDuration": true,
"showMessageCount": true,
"showLinesAdded": true,
"showLinesRemoved": true
}Options:
showResponseTime: Total API duration across all requestsshowLastResponseTime: Individual response time for most recent queryshowDuration: Total session durationshowMessageCount: Number of user messages sentshowLinesAdded: Lines of code added during sessionshowLinesRemoved: Lines of code removed during session
Symbols:
- Unicode:
⧖Total API time •ΔLast response •⧗Session duration •⟐Messages •+Lines added •-Lines removed - Text:
RTotal API time •LLast response •TSession duration •#Messages •+Lines added •-Lines removed
"version": {
"enabled": true
}Display: v1.0.81
Symbols: ◈ Version (unicode) • V Version (text)
"tmux": {
"enabled": true
}Display: tmux:session-name
"sessionId": {
"enabled": false,
"showIdLabel": true
}Options:
showIdLabel: Show the⌗icon prefix before the session ID (default:true)
Display: ⌗ a1b2c3d4-...
Symbols: ⌗ Session ID (unicode) • # Session ID (text)
"env": {
"enabled": true,
"variable": "CLAUDE_ACCOUNT",
"prefix": "Acct"
}Options:
variable(required): Environment variable name to readprefix: Label shown before the value. Defaults to the variable name
Hidden when the variable is unset or empty.
Symbols: ⚙ Env (unicode) • $ Env (text)
Advanced Configuration
"budget": {
"session": { "amount": 10.0, "warningThreshold": 80 },
"today": { "amount": 25.0, "warningThreshold": 80 },
"block": { "amount": 15.0, "type": "cost", "warningThreshold": 80 }
}Options:
amount: Budget limit (required for percentage display)type: Budget type -cost(USD) |tokens(for token-based limits)warningThreshold: Warning threshold percentage (default: 80)
Indicators: 25% Normal • +75% Moderate (50-79%) • !85% Warning (80%+)
[!TIP] Claude's rate limits consider multiple factors beyond tokens (message count, length, attachments, model). See Anthropic's usage documentation for details.
Choose between Unicode symbols (requires Nerd Font) or ASCII text mode for maximum compatibility.
{
"display": {
"charset": "unicode"
}
}Options:
unicode(default) - Uses Nerd Font icons and symbolstext- ASCII-only characters for terminals without Nerd Font
The charset setting works independently from separator styles, giving you 8 possible combinations:
minimal+unicode/text- No separatorspowerline+unicode/text- Arrow separators (requires Nerd Font for unicode)capsule+unicode/text- Rounded caps (requires Nerd Font for unicode)tui+unicode/text- Bordered panel with rounded or ASCII box characters
Auto-Wrap (enabled by default):
{
"display": {
"autoWrap": true
}
}Segments flow naturally and wrap to new lines when they exceed the terminal width.
Multi-line Layout for manual control:
{
"display": {
"lines": [
{
"segments": {
"directory": { "enabled": true },
"git": { "enabled": true },
"model": { "enabled": true }
}
},
{
"segments": {
"session": { "enabled": true },
"today": { "enabled": true },
"context": { "enabled": true }
}
}
]
}
}Padding - number of spaces on each side of segment text:
{
"display": {
"padding": 1
}
}Set to 0 for compact, 1 (default) for standard spacing.
[!NOTE] Claude Code system messages may truncate long status lines. Use
autoWrapor manual multi-line layouts to prevent segment cutoff.
Create custom themes and configure color compatibility:
{
"theme": "custom",
"display": {
"colorCompatibility": "auto"
},
"colors": {
"custom": {
"directory": { "bg": "#ff6600", "fg": "#ffffff" },
"git": { "bg": "#0066cc", "fg": "#ffffff" },
"session": { "bg": "#cc0099", "fg": "#ffffff" }
}
}
}Color Options: bg (hex, transparent, none) • fg (hex)
TUI Grid Colors: In TUI grid mode, custom colors also support bare segment names and dot-notation parts as keys. A bare segment key (e.g. "context") sets the default color for the segment and all its parts. A part key (e.g. "context.bar") overrides a specific part:
"colors": {
"custom": {
"model": { "fg": "#e0d68a" },
"context": { "fg": "#7dcfff" },
"metrics.lastResponse": { "fg": "#bb9af7" }
}
}Compatibility Modes: auto (default), ansi, ansi256, truecolor
Environment Variables:
NO_COLOR- Disable all colors when set to any non-empty value (follows NO_COLOR standard)FORCE_COLOR- Force enable color output (follows FORCE_COLOR standard):0orfalse- Disable colors1ortrue- Force basic 16 colors (ANSI)2- Force 256 colors3- Force truecolor (16 million colors)- Any other non-empty value - Force basic colors
COLORTERM- Auto-detected for truecolor support
Priority: FORCE_COLOR overrides NO_COLOR (allowing color to be forced on even when NO_COLOR is set)
{
"statusLine": {
"type": "command",
"command": "pnpm dlx @promptctl/[email protected] --style=tui"
}
}By default, the TUI panel uses a built-in responsive layout. For full control over what goes where, add a display.tui object to your config. This activates the grid layout engine, a CSS Grid-inspired system that lets you define rows, columns, spans, and responsive breakpoints.
Grid Layout Configuration
Add display.tui to your config file to enable the grid engine:
{
"display": {
"style": "tui",
"tui": {
"fitContent": true,
"widthReserve": 45,
"minWidth": 32,
"maxWidth": 120,
"padding": { "horizontal": 4 },
"separator": {
"column": " ",
"divider": "─"
},
"box": { ... },
"title": { ... },
"footer": { ... },
"segments": { ... },
"breakpoints": [ ... ]
}
}
}| Property | Type | Default | Description |
|---|---|---|---|
| fitContent | boolean | false | Panel shrinks to fit content instead of filling terminal width |
| widthReserve | number | 45 | Characters reserved from terminal width (ignored when fitContent: true) |
| minWidth | number | 32 | Minimum panel width |
| maxWidth | number | ∞ | Maximum panel width |
| padding.horizontal | number | 0 | Extra horizontal padding in fitContent mode |
| separator.column | string | " " | String placed between columns |
| separator.divider | string | box char | Character used for --- divider rows |
| box | object | -- | Custom box-drawing characters (see below) |
| title | object | -- | Title bar text configuration (see below) |
| footer | object | -- | Footer text configuration (see below) |
| segments | object | -- | Custom segment templates (see below) |
| breakpoints | array | required | Responsive layout definitions |
Breakpoints
Each breakpoint defines a complete layout that activates when the panel width is at or above its minWidth. The engine picks the first match, sorted widest-first.
"breakpoints": [
{
"minWidth": 80,
"areas": [
"git.head git.head git.head . git.working",
"---",
"context.icon context.bar context.bar context.pct context.tokens",
"block.icon block.bar block.bar block.value block.time"
],
"columns": ["auto", "1fr", "auto", "auto", "auto"],
"align": ["left", "left", "right", "right", "right"]
},
{
"minWidth": 55,
"areas": [
"git.head git.working",
"---",
"context.bar context.tokens",
"block ."
],
"columns": ["1fr", "auto"],
"align": ["left", "right"]
},
{
"minWidth": 0,
"areas": [
"git.head",
"git.working",
"---",
"context",
"block"
],
"columns": ["1fr"],
"align": ["left"]
}
]| Property | Type | Required | Description |
|---|---|---|---|
| minWidth | number | yes | Minimum panel width to activate this layout |
| areas | string[] | yes | Grid rows, each string is one row of space-separated cell names |
| columns | string[] | yes | Column sizing: "auto", "1fr" / "2fr", or a fixed number like "20" |
| align | string[] | no | Per-column alignment: "left", "center", or "right" (defaults to "left") |
Column sizing:
"auto"- shrinks to the widest content in that column"1fr","2fr"- fractional units that divide remaining space proportionally"20"- fixed width in characters
Special area tokens:
.- empty cell (renders as blank space)---- full-width horizontal divider row
Spanning: repeat the same name in adjacent cells to span columns:
"context.bar context.bar context.bar context.pct context.tokens"Here context.bar spans the first three columns.
Segment Names
Use bare segment names to render the full pre-formatted segment:
context block session today weekly
git dir version tmux metrics
activity envDot-Notation Subsegments
Use segment.part to place individual pieces of a segment into separate cells with independent alignment:
| Segment | Parts |
|---|---|
| git | icon, branch, status, ahead, behind, working, head |
| context | icon, bar, pct, tokens |
| block | icon, bar, value, time, budget |
| session | icon, cost, tokens, budget |
| today | icon, cost, label, budget |
| weekly | icon, bar, pct, time |
| metrics | response, responseIcon, responseVal, lastResponse, lastResponseIcon, lastResponseVal, added, addedIcon, addedVal, removed, removedIcon, removedVal |
| activity | duration, durationIcon, durationVal, messages, messagesIcon, messagesVal |
| version | icon, value |
| tmux | label, value |
| dir | value |
| env | prefix, value |
Example, block segment with a progress bar, mirroring the context layout:
"areas": [
"context.icon context.bar context.bar context.pct context.tokens",
"block.icon block.bar block.bar block.value block.time"
][!NOTE]
context.bar,block.bar, andweekly.barare width-aware. Their progress bars render at exactly the resolved column width. Block bar usesnativeUtilizationfrom the 5-hour rate limit data. Weekly bar uses the 7-dayused_percentage.
Custom Box Characters
Override individual box-drawing characters. Partial overrides merge with the charset default (unicode or text):
"box": {
"topLeft": "┌",
"topRight": "┐",
"bottomLeft": "└",
"bottomRight": "┘",
"horizontal": "─",
"vertical": "│",
"teeLeft": "├",
"teeRight": "┤"
}Only specify the characters you want to change. The rest inherit from the active charset.
Title Bar
Configure the left and right text in the top border. Supports {model} and any {segment} or {segment.part} token that resolves from segment data:
"title": {
"left": "{model}",
"right": "{dir}"
}| Property | Type | Default | Description |
|---|---|---|---|
| left | string | "{model}" | Left-side text (supports tokens) |
| right | string \| false | "claude-powerline" | Right-side text, or false to hide |
Footer
Same as the title bar, but on the bottom border. Defaults to no text (plain border):
"footer": {
"left": "{weekly}",
"right": "{metrics.lastResponse}"
}| Property | Type | Default | Description |
|---|---|---|---|
| left | string | -- | Left-side footer text (supports tokens) |
| right | string | -- | Right-side footer text (supports tokens) |
Tokens resolve any segment or subsegment reference: {model}, {dir}, {git.head}, {block.value}, {metrics.lastResponse}, etc.
Segment Templates
Define custom compositions for composite cells using the segments key. This assembles multiple parts into a single cell:
"segments": {
"metrics.lastResponse": {
"items": ["{lastResponseIcon}", "{lastResponseVal}"],
"gap": 1,
"justify": "start"
}
}| Property | Type | Default | Description |
|---|---|---|---|
| items | string[] | required | Part references like "{partName}" or literal strings |
| gap | number | 1 | Spaces between items |
| justify | string | "start" | "start" packs items left; "between" distributes across cell width |
The template name (e.g. metrics.lastResponse) can then be used as a cell name in areas.
Automatic Culling
Empty segments are automatically removed. Cells resolve to ., empty rows are dropped, and orphaned dividers are cleaned up. A wide layout gracefully degrades when data is unavailable.
[!NOTE] Claude Code's internal progress indicators (spinner, context bar) may briefly overlap the TUI panel during tool calls. This is a limitation of the hook architecture and resolves once the tool call completes.
Extend the statusline using shell composition:
{
"statusLine": {
"type": "command",
"command": "pnpm dlx @promptctl/claude-powerline && echo \" $(date +%H:%M)\"",
"padding": 0
}
}[!NOTE] Use
tputfor colors:setab <bg>(background),setaf <fg>(foreground),sgr0(reset). Example:echo "$(tput setab 4)$(tput setaf 15) text $(tput sgr0)". For complex logic, create a shell script with multiple commands, conditions, and variables.
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
See CONTRIBUTORS.md for people who have contributed outside of GitHub PRs.
License
This project is licensed under the MIT License.
