markr-cli
v1.0.2
Published
MarkR — a clean, full-width, auto-adjusting status line for Claude Code. Context, rate-limit quota, cost and git at a glance.
Downloads
479
Maintainers
Readme
MarkR
A clean, full-width status line for Claude Code.
Opus 4.8 * ~/work/api git main ~2 ?1 edit server.ts, routes.ts +3
ctx ████░░░░░░ 38% 76k/200k │ 5h ██░░░░ 29% (2h43m) │ 7d ████░░ 60% (4d9h) │ $4.89 │ 24m api 15m │ +800/-368Two rows: what you're working with on top, what you've spent underneath. Both justified edge to edge, so the bar reads as one aligned block at any terminal size.
The identity row separates on whitespace — its segments are short, distinct names that read cleanly on their own. The telemetry row is a dense run of similar-looking figures, so it keeps dividers. Both are configurable.
Why
Claude Code hands the status line far more than most bars show — including your 5-hour and 7-day rate-limit quota, which on a Pro or Max plan is the number that decides whether you can keep working. MarkR surfaces it with a reset countdown, alongside context usage, session cost, and git state.
Install
npx markr-cli@latestThat is the whole install, on macOS, Linux and Windows alike. It renders a preview,
then offers to add MarkR to ~/.claude/settings.json. Your existing settings are
preserved and copied to settings.json.bak first.
Because npx runs from a cache directory npm may clear at any time, MarkR copies
itself to ~/.claude/markr/ and points the settings entry there — so the bar keeps
working long after the cache is gone. Nothing else is left behind.
If you would rather have a markr command on your PATH:
npm install -g markr-cli
markr --installInstalled globally, the settings entry is the bare command markr and no copy is made.
Or wire it up by hand in ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "markr",
"padding": 0
}
}Restart Claude Code. padding: 0 lets the bar use the full width.
Commands
| Command | Does |
| --- | --- |
| markr | Renders from session JSON on stdin — how Claude Code calls it |
| markr --install | Adds MarkR to ~/.claude/settings.json |
| markr --preview | Renders a sample bar using your real working directory |
| markr --help | Usage and flags |
| markr --version | Prints the version |
What it shows
Row 1 — identity
| Segment | Notes |
| --- | --- |
| Model | With * when extended thinking is on, fast in fast mode |
| Effort | low · medium · high · xhigh · max |
| Vim mode | Only when vim bindings are active |
| Directory | Shortened to the trailing segments |
| Git | Branch, ^ahead vbehind, +staged ~unstaged ?untracked xconflicts |
| Worktree / PR / Agent | Shown when the session has them |
| Edited files | Most recently written files this session, +N for the rest |
Row 2 — telemetry
| Segment | Notes | | --- | --- | | Context | Meter, percentage, tokens used against the window | | 5h / 7d quota | Rate-limit usage with a reset countdown | | Cost | Session spend in USD | | Duration | Wall-clock, plus API time — the gap is your own thinking time | | Diff | Lines added and removed | | Version | Claude Code version |
A ! appears before any percentage at or above 85%, so an approaching limit is
visible without introducing a second colour.
Responsive behaviour
The bar adapts to the terminal in three stages:
- The file list grows to use spare width on the identity row. That row is naturally shorter than the telemetry row, and filling it with more filenames beats padding it with whitespace.
- Meters shrink at 140 and 100 columns — a narrower meter still reads correctly.
- Segments drop by priority when even that won't fit. Version and diff go first; the model and context meter are pinned and never dropped.
A row with enough segments is justified edge to edge. One too sparse to reach both edges without large gaps is centred instead, with equal margins either side.
Four columns are held back from the right. Claude Code renders the bar inside its own
frame and truncates anything longer than the space it allots, which is slightly
narrower than COLUMNS.
Configuration
Optional. Create ~/.claude/markr.json:
{
"accent": 173,
"muted": 245,
"track": 239,
"maxFiles": 3,
"alarmAt": 85,
"dividers": {
"identity": false,
"telemetry": true
},
"segments": {
"version": false,
"diff": false
}
}| Key | Default | Meaning |
| --- | --- | --- |
| accent | 173 | Model, version, anything not styled below (xterm-256 code) |
| muted | 245 | Labels, dividers, parenthetical notes |
| track | 239 | Unfilled portion of meters |
| maxFiles | 3 | Minimum edited files listed; grows to fill spare width (max 10) |
| alarmAt | 85 | Percentage at which ! appears |
| dividers.identity | false | Draw │ between row 1 segments |
| dividers.telemetry | true | Draw │ between row 2 segments |
| segments.* | all true | Toggle any segment off |
Colours are xterm-256 codes. 24-bit colour isn't available in every terminal, and 256 degrades predictably.
Colour as meaning
Colour in the bar is information, not decoration. Anything with a healthy and an unhealthy end is drawn from one four-step severity ramp, so green always means the same thing wherever it appears:
| Key | Default | |
| --- | --- | --- |
| scale.good | 71 | green |
| scale.warn | 179 | gold |
| scale.bad | 167 | red |
| scale.severe | 176 | violet |
Every hue peaks at channel d7 and bottoms at 5f, so they sit at one apparent
brightness and no segment shouts louder than its neighbours purely because of its
hue.
Meters cross the ramp at configurable percentages, given as [warn, bad]:
| Key | Default | Meaning |
| --- | --- | --- |
| thresholds.context | [25, 50] | Green to 25%, gold to 50%, red above |
| thresholds.quota | [50, 75] | Green to 50%, gold to 75%, red above |
Context turns earlier than quota because the two failures differ. Filling the context window degrades the conversation you are already in, and the moment worth noticing is while there is still room to act. Quota only bites near the cap.
A quota's reset countdown takes its own meter's colour. (2h43m) is reassuring at
29% and ominous at 90% — the figure carries meaning only next to the usage it
belongs to, so a second independent ramp there would be noise.
Effort maps a level to a key on that same scale:
{ "effort": { "low": "good", "medium": "warn", "high": "bad", "xhigh": "severe", "max": "severe" } }Segments with no healthy-to-unhealthy axis take a fixed colour instead:
| Key | Default | |
| --- | --- | --- |
| palette.directory | 252 | bright, a step below pure white |
| palette.git | 245 | grey — branch state is context, not headline |
| palette.files | 179 | gold |
| palette.cost | 179 | gold |
| palette.duration | 179 | gold |
| palette.added | 71 | green |
| palette.removed | 167 | red |
For a monochrome bar, point every key at the same value:
{ "scale": { "good": 252, "warn": 252, "bad": 252, "severe": 252 } }Notes on rendering
The bar uses only characters that are unambiguously one cell wide. Symbols like
↻, ✳ or ↑ sit in the East Asian Ambiguous range and paint two cells in some
terminals — under a justified layout that silently pushes rows past the edge and
they get truncated. ASCII equivalents are used instead. No Nerd Font is required.
Requirements
- Node.js ≥ 18
- Claude Code ≥ 2.1.153 (earlier versions don't set
COLUMNS; MarkR falls back to probing the tty, then to 120 columns) - macOS, Linux or Windows
On Windows the tty probes are skipped — there is no /dev/tty to read — so the
COLUMNS that Claude Code sets is used, falling back to 120 columns.
Development
npm test # layout, palette, width and degradation tests
npm run demo # render sample payloads at several widths--install always points Claude Code at ~/.claude/markr/, never at your checkout.
To see local edits in a live session, run npm link so markr resolves on PATH, or
point statusLine.command at your working copy by hand.
License
MIT
