uberline
v0.3.4
Published
An expressive, animated, data-rich status line for Claude Code
Maintainers
Readme
UberLine
An expressive, animated, data-rich status line for Claude Code.

UberLine surfaces seven categories of live data through three pluggable themes — Aurora (animated, expressive), Neon (cyberpunk signage with sub-perceptual flicker), and Mono (minimal) — with per-widget config:
- core — model, context %, cwd, git branch + dirty, session duration, effort badge (tiered —
⚡forhigh/xhigh, an animated★apex formax; ultracode reports asxhighand is not a separate tier), 5h/7d rate-limit bars - tool — what tool Claude is running right now, derived live from your transcript
- velocity — token/sec rolling average, $/hour rate, session total
- worktime — real working time per project today, AFK-aware. Aggregates across all sessions/worktrees of the same repo; inferred from transcript event gaps with no OS-level activity monitoring.
- ci — latest commit's GitHub check-runs (✓/✗/◐), with current PR number
- mcp — active subagents, pending todos, connected MCP servers
- net — Anthropic API health dot
Install
npm (recommended)
npm install -g uberline
uberline installRequires Node ≥ 20. uberline install writes the status line into ~/.claude/settings.json (backing up any prior statusLine); uberline uninstall restores from the backup.
Interactive vs scripted setup
npx uberline install # interactive: pick theme + widgets when stdin is a TTY
npx uberline install --yes # non-interactive: accept all defaults (CI-friendly)
npx uberline install --yes --theme=mono # scripted: skip the picker, force a theme
npx uberline install --force # replace a foreign statusLine without promptingWhen stdin is a TTY and no --non-interactive / --yes flag is passed, uberline install runs a short wizard:
- Theme picker — choose from built-in themes (
aurora,neon,mono) plus any TOML themes discovered under~/.config/uberline/themes/. Bypass with--theme=<name>. - Widget toggles — enable/disable individual widgets and per-widget features (e.g.
worktimeheartbeat opt-in).
In CI or piped contexts (stdin not a TTY), the wizard is skipped automatically — behaviour matches the legacy non-interactive install.
Install flags
| Flag | Behaviour |
|---|---|
| --non-interactive | Skip all prompts; use defaults. |
| --yes | Alias for --non-interactive. |
| --force | When a foreign statusLine is detected, replace it without confirmation. |
| --theme=<name> | Skip the theme picker; use this name. Combinable with --non-interactive for fully-scripted setup. |
Conflict detection
UberLine inspects the existing statusLine in ~/.claude/settings.json before writing:
- Same as ours — idempotent skip; settings.json is left untouched and no backup is written.
- Foreign tool (Starship, Powerlevel10k, Oh My Posh, Spaceship Prompt) — interactive: prompt
replace / abort / keep. CI: aborts with a clear stderr message and exit code 2; pass--forceto replace. - Unknown user script — interactive: confirm before overwrite. Explicit
--non-interactive/--yesrequires--force; implicit non-interactive (CI / piped) proceeds with replace for backwards compatibility.
When an existing statusLine is replaced, a sentinel-marked backup is written to ~/.claude/statusline-backup-<timestamp>.json (sentinel: "_uberline_backup": 1). uberline uninstall only deletes backup files carrying that sentinel.
From source
git clone https://github.com/TheFJK/UberLine
cd UberLine
npm install
npm run build
node bin/uberline installUseful for hacking on the codebase. The settings file gets pinned to an absolute path under your clone, so moving or renaming the directory breaks the status line — re-run node bin/uberline install from the new location to repair.
Other channels (in progress)
The repo is currently private; channels marked gated on public flip unblock once the repo goes public.
- curl-pipe single binary —
scripts/install.shand the binary matrix in.github/workflows/release.ymlare wired, but no GitHub Release assets have been published yet. Gated on public flip + a tagged release run that uploads the binaries. - Claude Code plugin marketplace (
/plugin install uberline) —src/plugin/plugin.jsoncurrently registers only a/uberline-configeditor slash command, not a status-line install affordance. Gated on public flip + plugin manifest rewrite.
Configure
UberLine creates ~/.config/uberline/config.toml on first run. Edit it to enable/disable widgets, change thresholds, or tune animation level (0=static, 1=subtle, 2=expressive).
theme = "aurora"
widgets = ["core", "tool", "velocity", "ci", "mcp", "worktime", "net"]
[animation]
level = 2
spinner_glyphs = "◐◓◑◒"
[thresholds]
ctx_warn = 70
ctx_crit = 90
cost_per_hour_warn = 5.00
[widget.core]
show_session_duration = true
show_effort_badge = true
budget_usd = 50.0See src/config/default.toml for the full key reference (per-widget options for tool, velocity, worktime, ci, mcp, net).
Worktime privacy & accuracy
AFK is inferred from gaps between transcript events (tool invocations and completions), not from OS-level keystrokes or window focus. UberLine never observes input. Long quiet periods of reading code count as idle even if you're at the keyboard — a known limitation; richer signals (Stop-hook heartbeats, GH PR enrichment) are tracked as separate follow-up issues.
Worktrees of the same repo get distinct identity via git rev-parse --git-common-dir + --show-toplevel. Persisted JSONL lives at $XDG_CONFIG_HOME/uberline/worklog.jsonl (override via UBERLINE_WORKLOG). Rows older than 90 days are compacted out.
worktime — privacy, heartbeat opt-in, and CLI
Privacy. AFK is inferred from gaps between transcript events (tool invocations and completions). UberLine never reads keystrokes or window focus. Worktree identity is SHA256-hashed: git rev-parse --git-common-dir + --show-toplevel are hashed to a 12-char key, never stored as a plaintext path.
Heartbeat (opt-in). Long quiet "reading code" periods count as idle by default because the only signal is the transcript event timeline. To fill those gaps, install a Stop hook that pings uberline heartbeat:
// ~/.claude/settings.json
{
"statusLine": { "type": "command", "command": "uberline" },
"hooks": {
"Stop": [{ "type": "command", "command": "uberline heartbeat" }]
}
}Then enable in ~/.config/uberline/config.toml:
[widget.worktime]
heartbeat_enabled = trueHeartbeats are written to $XDG_CONFIG_HOME/uberline/heartbeat.jsonl (override via UBERLINE_HEARTBEAT). Each heartbeat counts as a 1-second active window — enough to split a sub-AFK gap so the surrounding inter-event time classifies as active. Truly long idle windows still classify as idle.
GH PR enrichment. When the cwd is inside a git repo with an open PR (and gh CLI is authenticated), the widget appends · on #42. Toggle off with gh_enrichment_enabled = false. Read-only — no write scope is required; uses the same cached fetchPrNumber as the ci widget.
CLI.
uberline worktime today # today's active/idle grouped by repo · branch · #PR
uberline worktime project # today's totals rolled up to one row per repo
uberline worktime project --all # all-time totals per repo (since worklog began)
uberline worktime pr 42 # totals for PR #42 across sessionsThemes
Three themes ship in v1; a fourth path lets users author their own:
- aurora (default) — Aurora 2.0: phase-shifted hue sweep along bars (the "borealis ribbon"), Deep Borealis palette (cooler violet/teal/cyan accents), level-2 animation. Renders like a flowing band on multi-cell bars; identical to today on single-cell bars.
- neon — cyberpunk signage with sub-perceptual flicker: saturated magenta/cyan accents, gentle brightness wobble that reads as "alive" without distracting.
- mono — single-color minimal renderer for low-contrast terminals or screen-reader workflows. Auto-engages when
NO_COLORis set orTERM=dumb.
User-authored themes
Drop a TOML file in ~/.config/uberline/themes/<name>.toml and select it via theme = "<name>" in your config:
# ~/.config/uberline/themes/mocha.toml
name = "mocha"
extends = "aurora"
[palette]
accent = "#cba6f7"
"value-id" = "#f5c2e7"
"git-branch" = "#94e2d5"
success = "#a6e3a1"
warn = "#f9e2af"
crit = "#f38ba8"Sample themes live in examples/themes/. Helpful CLI:
uberline theme list # print discovered themes (built-in + TOML)
uberline theme show aurora # dump a theme as a TOML you can copy/edit
uberline theme preview mocha # render the test fixture with a named theme
uberline doctor --themes # extends doctor with theme discovery reportTo author a new theme, see docs/design/specs/2026-04-29-aurora-2.0-and-toml-themes-design.md.
Doctor
uberline doctorPrints a health report: which Claude Code settings file is in use, whether the configured statusLine command resolves on PATH, current config path, theme, enabled widgets, cache state, and any input-parse errors from the most recent invocation. Useful when the status line is silent and you want to know why.
Uninstall
uberline uninstall # interactive: confirms before removal
uberline uninstall --yes # non-interactive: skip the confirmation
uberline uninstall --dry-run # print the removal plan; no fs mutation; exit 0Uninstall flags
| Flag | Behaviour |
|---|---|
| --non-interactive | Skip the confirmation prompt. |
| --yes | Alias for --non-interactive. |
| --dry-run | Print the removal plan with [dry-run] prefix; no fs mutation; exit 0. |
Removal scope
uberline uninstall removes:
- The
statusLinebinding in~/.claude/settings.json(or restores it from the most recent sentinel-marked backup). - Sentinel-marked
~/.claude/statusline-backup-*.jsonfiles. Pre-RFC backups (no sentinel) are listed on stderr and skipped — UberLine will not delete files it cannot prove it owns;rmthem manually if desired. ~/.config/uberline/recursively — config, user themes, the known-binary marker, heartbeat + worklog state./tmp/uberline/recursively — disk cache + error log.
Use --dry-run first if you want to see exactly which paths would be touched.
Troubleshooting
Statusline reverts to default on subsequent Claude Code sessions in the same folder
If your UberLine statusline renders correctly on the first claude session in
a folder but reverts to a stripped-down default on every subsequent session,
run:
uberline doctorIf doctor reports project-scope .claude/settings.local.json exists ... but
does not declare a statusLine entry, copy the JSON snippet it prints into
your project's .claude/settings.local.json. Background:
anthropics/claude-code#19487
documents that a project-scope .claude/settings.local.json shadows the
user-scope statusLine (closed not-planned upstream); UberLine detects this
and surfaces a copy-pasteable fix.
If doctor does NOT report shadowing but the statusline still reverts, the
cause is likely an empty locale env in the spawned subprocess (issue #28
Candidate A — fixed in v0.2.0; upgrade with npm i -g uberline@latest).
License
MIT.
Contributing
Issues and PRs welcome at https://github.com/TheFJK/UberLine/issues. The architecture (widgets → Cell IR → Theme) and v1 implementation plan live in docs/design/.
