statusline

module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: Apache-2.0

README

statusline

statusline rendering a full Claude Code session in the claude-dark theme

CI status CodeQL status Go version License

A single-binary, themeable Claude Code statusLine command written in Go. Flat, no-background segments joined by a thin Nerd Font chevron divider, truecolor gradients, seven built-in themes, and an optional TOML config file for anyone who wants to tweak it further.

(The image above is a real render — statusline demo --theme claude-dark --scenario full — captured as an image since GitHub can't render truecolor ANSI escape codes or Nerd Font glyphs inside a Markdown code block.)

Contents

Install

From source:

git clone https://github.com/scrothers/statusline.git
cd statusline
make build      # produces ./statusline

Or, once a release exists:

go install github.com/scrothers/statusline/cmd/statusline@latest

Preview it

statusline demo renders built-in sample payloads directly — no need to craft JSON fixtures or wire up Claude Code first:

./statusline demo                                   # "full" scenario, all 7 themes
./statusline demo --theme dracula                    # one theme only
./statusline demo --theme nord --scenario minimal    # early-session look
./statusline demo --scenario narrow --columns 40     # test width-based truncation

Scenarios: minimal (early session, no git repo yet), full (every segment at once — dirty repo, open PR, context/cost/rate-limit/cache data, a named session, a worktree), narrow (the full payload rendered at 30 columns, to see which segments drop first).

Configure Claude Code

Add to ~/.claude/settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "~/code/statusline/statusline",
    "padding": 2,
    "refreshInterval": 2,
    "hideVimModeIndicator": true
  }
}
  • refreshInterval: 2 keeps the clock-style duration, cost, and context bar ticking during long idle stretches (a slow tool call, a background subagent), not just after each assistant message.
  • hideVimModeIndicator: true suppresses Claude Code's built-in -- INSERT -- text, since the vim badge already shows the mode when enabled in config (see Segments).

Segments

Three lines, each answering one question. Every segment is plain colored text — no background is ever painted, so lines read as flat, breathing text joined by a thin chevron divider, not powerline pills.

Line Segments Notes
1 — Claude model, thinking, effort, context window, rate limits (5h/7d), cache The model's own state: what it's running, how hard, and how much room/budget is left.
2 — session session name, directory, lines added/removed, token counts, cost, duration Omitted fields (no custom name, no diff yet) just don't appear.
3 — git repo (host/owner/name), open PR (number + review state), branch + status, worktree The whole line disappears outside a git repository.

Segments not in the default layout but still available via custom config: vim (vim mode), agent (subagent name), output_style. These render with no background either — they just aren't wired into any line by default.

Under width pressure, segments drop in priority order (lowest first) until a line fits; model and directory never drop, only self-truncate.

effort is the one segment colored by intensity rather than theme: its icon escalates from an empty gauge (low) through a full gauge (xhigh) to fire (max) and an alert fire (ultra), and its color runs a fixed green → red → purple scale independent of the active theme, so "getting hotter" reads the same everywhere.

context_window and the two ratelimit_* gauges share the same bar treatment: context_window's width scales with the detected terminal width (clamped between 8 and 24 cells); the rate-limit bars stay a fixed, narrower 6 cells and are explicitly labeled 5h/7d so the two aren't distinguishable by icon alone. On all three, each bar cell's color is fixed by its position along the bar — green on the left sliding through warning to danger on the right — so filling the bar reveals more of a stable on-screen gradient from the left rather than shifting every already-filled cell's color together each time the percentage changes. (Each gauge's icon and percentage text use a separate smooth gradient based on its own overall percentage.) The context bar also shows a used/remaining token count next to the percentage whenever the context window size is known.

Each ratelimit_* gauge also shows a muted reset countdown (a restart icon plus a compact "resets in" duration like 2h or 3d 2h) whenever the payload reports a reset time — a coarser, more actionable signal than the percentage alone, since it tells you when the budget actually comes back rather than just how much is used right now.

cache reuses that same smooth gradient for its icon and hit-rate percentage, but inverted: a high cache-hit rate is good, so it runs green at 100% down to red at 0% (the opposite direction from the gauges above, where high usage is the thing to watch). The raw cache-read count in parentheses stays a plain muted color.

lines_changed leads with a pencil icon (given two trailing spaces of its own, since its glyph reads tight against a following icon), then diff-added/diff-removed icons that alone carry the +/- meaning. token_counts leads with a ticket icon (same two-space treatment) and breaks down usage into four counts, each behind its own icon: an inbound tray for input tokens, an outbound tray for output tokens, a database-plus for cache-creation tokens, and the same cache icon used elsewhere for cache-read tokens. Input/output are session-cumulative totals — the same time scope as lines_changed's add/remove counts — while cache-creation/ cache-read come from the most recent API response, since the schema has no cumulative field for either and "how well is caching working right now" is inherently a per-turn question anyway (the same time scope the standalone cache segment already uses). In both segments, only the icons carry semantic color (green/red for add-remove and input-output, info for the cache pair); the counts themselves are always the theme's secondary text color, with no ASCII sign.

cost and duration follow the same icon/text split: the dollar icon is success-green (money) and the clock icon is info, while the amount and the clock-style duration both render in the theme's primary text color — plain prose, not a semantic accent, since a dollar figure or elapsed time isn't inherently good/bad/informational the way a gauge fill is.

Line 3 follows the same rules as everywhere else. git's status badges (staged/modified/untracked/conflicts/ahead/behind) each split into a category-colored icon and a TextSecondary count, matching lines_changed/token_counts; conflicts use a proper alert icon rather than a bare !. The branch name, repo's final /name piece, pr's number, and worktree's name all use IdentityText — the same "headline label following an identity-colored icon" role as model/directory/ session_name — while pr's icon and review-state word still share the review-state color, since that state is the actual signal.

repo's icon is host-branded: GitHub, GitLab, and Forgejo each get their own logo when the remote host contains that name (matching public domains like github.com and enterprise/self-hosted ones like github.company.com alike), falling back to a generic git icon for anything else — including Forgejo instances with no "forgejo" in their hostname (e.g. Codeberg), since the host string is the only signal available.

Themes

Seven built-in themes, selected with theme = "<name>" in config or --theme <name> on the command line. claude-dark is the default. Themes are foreground-only palettes (identity accent + success/warning/danger/info/muted roles) — there's no background token, since the statusline never paints one.

All seven built-in themes rendering the same full session

Name Style
claude-dark Anthropic's coral/terracotta accent on a warm near-black ink background (default)
claude-light The same coral/terracotta accent on a warm cream background — the one built-in theme meant for a light terminal
gruvbox Warm, retro, high-contrast
catppuccin-mocha Soft pastel-on-dark
tokyo-night Cool blues/purples on near-black
nord Arctic blues
dracula High-contrast purple/pink

claude-dark and claude-light are built from Anthropic's published brand palette (the #D97757 coral, #141413 ink, #FAF9F5 cream, plus a sage green and dusty blue used for success/info); warning and danger aren't part of that palette, so they're original colors chosen to sit comfortably in the same warm, muted family rather than clashing with a generic bright red/yellow.

Configuration

Optional TOML config file, discovered in this order (first match wins):

  1. --config <path> flag
  2. $XDG_CONFIG_HOME/statusline/config.toml (or ~/.config/statusline/config.toml)
  3. ~/.claude/statusline-config.toml
  4. Built-in defaults (Gruvbox theme, the 3-line layout above)

A missing or malformed config file is never fatal — it falls back to the built-in default and prints a warning to stderr (never stdout, which is reserved for the rendered statusline).

Example overriding the theme and disabling one segment:

theme = "nord"

[segments.pr]
enabled = false

[theme_overrides]
success = "#00ff00"

Take over lines[].segments entirely to reorder, drop, or add segments — see the Segments table for every available ID:

[[lines]]
enabled = true
segments = ["model", "context_window", "cache"]

Requirements

  • A Nerd Font in your terminal for the icons and the divider glyph. Without one, set nerd_font = false in config to fall back to plain Unicode/ASCII for every icon.
  • git on PATH for the repo/branch/PR segments; everything else works without it.

Development

make build             # go build -> ./statusline
make test              # unit tests
make test-integration  # + real git subprocess tests
make test-e2e          # + builds and drives the real binary
make bench             # benchmarks for the render/parse/config/theme hot paths
make lint              # go vet + golangci-lint
make security          # govulncheck + gosec

The whole non-git-subprocess render path — JSON decode, config/theme load, and the full three-line render — benchmarks at roughly 1.3ms combined on modest hardware, comfortably inside the sub-100ms-per-invocation budget the design targets; internal/gitstatus's porcelain parser alone handles a 500-file working tree in well under a millisecond.

Contributing

Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md for the development workflow and what to check before opening a PR. This project follows the Contributor Covenant.

Security

See SECURITY.md for supported versions and how to report a vulnerability privately. Please don't file a public issue for security reports.

License

Apache License 2.0 — see LICENSE.md.

Directories

Path Synopsis
cmd
statusline command
Command statusline is a Claude Code statusLine command: it reads session JSON from stdin and prints a themed, Nerd-Font-powerline status line to stdout.
Command statusline is a Claude Code statusLine command: it reads session JSON from stdin and prints a themed, Nerd-Font-powerline status line to stdout.
internal
cache
Package cache provides a small generic JSON file cache with atomic writes, used to avoid re-running slow subprocesses (git status) on every statusline refresh.
Package cache provides a small generic JSON file cache with atomic writes, used to avoid re-running slow subprocesses (git status) on every statusline refresh.
config
Package config loads the statusline's TOML configuration: a built-in default merged with an optional user file, discovered by a fixed precedence and never failing hard — a missing or malformed config always degrades to the built-in default plus a warning.
Package config loads the statusline's TOML configuration: a built-in default merged with an optional user file, discovered by a fixed precedence and never failing hard — a missing or malformed config always degrades to the built-in default plus a warning.
demo
Package demo provides canned statusline scenarios — synthetic payloads and git status, not real Claude Code JSON — so the demo command can render representative output without any external input.
Package demo provides canned statusline scenarios — synthetic payloads and git status, not real Claude Code JSON — so the demo command can render representative output without any external input.
fallback
Package fallback provides the last-resort degraded statusline used when normal rendering can't proceed at all (stdin parse failure, an unrecovered panic that reached main, or an empty render result), so the binary always prints something rather than leaving the status bar blank.
Package fallback provides the last-resort degraded statusline used when normal rendering can't proceed at all (stdin parse failure, an unrecovered panic that reached main, or an empty render result), so the binary always prints something rather than leaving the status bar blank.
gitstatus
Package gitstatus collects git branch and working-tree status for the git segment, caching results per session so repeated statusline refreshes don't re-run git on every trigger.
Package gitstatus collects git branch and working-tree status for the git segment, caching results per session so repeated statusline refreshes don't re-run git on every trigger.
input
Package input defines the JSON schema Claude Code sends to a statusLine command on stdin and parses it defensively, tolerating absent, null, and unknown fields so the binary never fails on partial or future data.
Package input defines the JSON schema Claude Code sends to a statusLine command on stdin and parses it defensively, tolerating absent, null, and unknown fields so the binary never fails on partial or future data.
render
Package render composes segment output into the final statusline text: it joins each line's segments with powerline cap/connector glyphs (or a plain divider between pill-less badges), drops lowest-priority segments under width pressure, and never lets one segment's panic take down the whole line.
Package render composes segment output into the final statusline text: it joins each line's segments with powerline cap/connector glyphs (or a plain divider between pill-less badges), drops lowest-priority segments under width pressure, and never lets one segment's panic take down the whole line.
segment
Package segment defines the Segment interface and every concrete statusline segment (model, directory, git, context window, cost, rate limits, and low-priority bonus badges), each rendering itself into style.Chunks from a RenderContext.
Package segment defines the Segment interface and every concrete statusline segment (model, directory, git, context window, cost, rate limits, and low-priority bonus badges), each rendering itself into style.Chunks from a RenderContext.
style
Package style provides truecolor ANSI painting, OSC 8 hyperlinks, and the escape-sequence stripping used both for NO_COLOR passthrough and for rendering-independent golden test comparisons.
Package style provides truecolor ANSI painting, OSC 8 hyperlinks, and the escape-sequence stripping used both for NO_COLOR passthrough and for rendering-independent golden test comparisons.
theme
Package theme resolves the five built-in named color palettes (Gruvbox, Catppuccin Mocha, Tokyo Night, Nord, Dracula) that segments render against, plus the shared Nerd Font icon table with plain-text fallbacks.
Package theme resolves the five built-in named color palettes (Gruvbox, Catppuccin Mocha, Tokyo Night, Nord, Dracula) that segments render against, plus the shared Nerd Font icon table with plain-text fallbacks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL