Skip to main content

A small, dependency-free CLI for inspecting Claude Code's statusLine JSON payload, with currency conversion, cost tracking, and an HTML dashboard.

Project description

statusline-toolkit

Tests

A small, dependency-free Python CLI for Claude Code's statusLine JSON payload. Prints a color-coded one-line summary, with optional currency conversion, cost tracking, and an HTML dashboard — all local, all plain JSON files you own.

[Claude Sonnet 5] (my-project) [####------] 42% | $0.1234 (~Rp 2.011) | +156/-23 | 45s | $9.87/hr | 5h: 24% 7d: 41%

Works identically on Linux, macOS, and Windows. MIT licensed.

Contents

Quick start

Requires Python 3.9+ (python3 on Linux/macOS, py on Windows). Two ways to get it:

# Option A: pip/pipx, no clone needed
pipx install git+https://github.com/gungunfebrianza/statusline-toolkit.git
statusline-toolkit --setup

# Option B: clone and run directly — no install step at all
git clone https://github.com/gungunfebrianza/statusline-toolkit.git
cd statusline-toolkit
python statusline_toolkit.py --input sample_statusline_data.json --idr
python statusline_toolkit.py --setup

Both are equivalent — it's zero-dependency either way. The rest of this README uses python statusline_toolkit.py ...; swap in statusline-toolkit ... if you installed via pip/pipx.

Usage

# Live: pipe whatever JSON Claude Code sends on stdin
some_producer_of_json | python statusline_toolkit.py

# Offline: inspect a saved payload
python statusline_toolkit.py --input sample_statusline_data.json --all   # full JSON
python statusline_toolkit.py --input sample_statusline_data.json --list # just the field names
python statusline_toolkit.py --input sample_statusline_data.json --field cost.total_cost_usd

# Currency conversion (any ISO 4217 code)
python statusline_toolkit.py --input sample_statusline_data.json --currency EUR

# No colors (for logging, or a terminal that mangles ANSI)
python statusline_toolkit.py --input sample_statusline_data.json --no-color

Flag reference

Flag Description
-i, --input PATH Read the JSON payload from a file instead of stdin.
-a, --all Print the entire payload as formatted JSON.
-l, --list List every available field path, without values.
-f, --field DOT.PATH Print just this field; repeatable.
--currency CODE Show cost converted to CODE (e.g. EUR, JPY, IDR).
--idr Shorthand for --currency IDR (backward compatible).
--rate RATE Override the conversion rate for this run only.
--rate-file PATH Use a different exchange-rate file.
--no-color Disable ANSI colors (also honors NO_COLOR).
--width N Override the detected terminal width for adaptive layout.
--no-adapt Never drop segments to fit the width — always the full line.
--setup Install as your Claude Code statusLine, then exit.
-y, --yes With --setup, skip the overwrite confirmation.
--settings-file PATH With --setup, target a different settings.json.
--track Record this session's cost to history, for --stats/--dashboard.
--stats Print a cost report from tracked history, then exit.
--by-project / --by-model With --stats, group by project/model instead of day.
--history-file PATH Use a different history file.
--dashboard Render an HTML usage dashboard from tracked history, then exit.
--dashboard-file PATH Where to write the dashboard (default: next to the history file).
--open With --dashboard, open it in your browser.
--config PATH Use a different personal defaults file.
--plugins-dir PATH / --no-plugins Custom plugin directory / skip loading plugins.
--version Print the version and exit.

Run --help any time for the same reference from the source.

Reading the summary line

[Claude Sonnet 5] (my-project) [####------] 42% | $0.1234 (~Rp 2.011) | +156/-23 | 45s | $9.87/hr | 5h: 24% 7d: 41%
Segment Meaning
[Claude Sonnet 5] Model name.
(my-project) Current project folder — helps tell sessions apart.
[####------] 42% Context window used, color-coded green→amber→red.
$0.1234 (~Rp 2.011) USD cost, plus a converted estimate if --currency/--idr is passed.
+156/-23 Lines added/removed, colored git-style (green/red).
45s Session duration.
$9.87/hr Burn rate — cost extrapolated to an hourly pace (a derived number, not a raw field).
5h: 24% 7d: 41% 5-hour / 7-day rate-limit usage.

Any segment just disappears if the payload doesn't have that data — nothing errors.

Colors blend smoothly from green (low) to amber to red (high) on terminals with 24-bit color support, and fall back to plain green/yellow/red otherwise. --no-color or NO_COLOR=1 turns all of it off.

Adaptive width: if the full line wouldn't fit your terminal, the least essential segments drop first — rate limits, then burn rate, duration, lines, project, currency — until it fits, or down to just [model] [bar] % | $cost if space is very tight. Use --width N to set the width explicitly (handy since Claude Code runs this headless, so there's often nothing real to detect) or --no-adapt to always print the full line.

Installing as your Claude Code status line

python statusline_toolkit.py --setup                       # default: IDR
python statusline_toolkit.py --setup --currency EUR         # a different currency
python statusline_toolkit.py --setup --currency EUR --track # also track cost history

This detects your OS and writes a statusLine entry into ~/.claude/settings.json, backing up any existing config first. It's idempotent (safe to re-run) and asks before overwriting a different statusLine (skip with -y). Restart Claude Code afterward to see it take effect.

Currency conversion

exchange_rate.json holds manually maintained rates you control — no network calls, no API keys:

{
  "rates": { "IDR": 16300, "EUR": 0.92 },
  "updated_at": "2026-07-06"
}

Add a currency to rates and pass --currency CODE, or use --currency CODE --rate <value> for a one-off conversion without touching the file. If a currency isn't configured, the script tells you exactly what to add rather than guessing. If updated_at is over 30 days old, you'll get a one-line reminder to refresh it.

(Older single-currency files — {"usd_to_idr": 16300, ...} — still work unchanged.)

Cost tracking: history, stats, and a dashboard

--track records each session's cost to usage_history.json (keyed by session, so re-renders don't double-count). Then:

python statusline_toolkit.py --input sample_statusline_data.json --track
python statusline_toolkit.py --stats                 # grouped by day
python statusline_toolkit.py --stats --by-project     # or by project / --by-model
python statusline_toolkit.py --dashboard --open       # visual HTML report

--stats prints a per-group cost/session breakdown with a grand total. --dashboard renders the same data as a self-contained HTML file — summary cards plus cost-by-day/project/model bar charts, no JS framework, no CDN, light/dark aware — and only opens a browser if you pass --open.

Everything here is opt-in and local: nothing is tracked or rendered unless you ask, and usage_history.json is plain JSON you can inspect or delete anytime.

Personal defaults file

Tired of retyping the same flags? Put them in ~/.claude/statusline-toolkit.json:

{
  "currency": "EUR",
  "track": true,
  "width": 100
}

Every key is optional and mirrors a CLI flag (no_color, by_project, by_model, no_adapt, rate_file, history_file, plugins_dir, no_plugins are all supported too). CLI flags always override the file. Use --config PATH for a different file (e.g. separate personal/work profiles).

Plugin segments

Add your own segment (git branch, whatever) without touching the script: drop a .py file into ~/.claude/statusline-plugins/ defining one function.

# ~/.claude/statusline-plugins/git_branch.py
import subprocess

def segment(data: dict, use_color: bool) -> str | None:
    cwd = data.get("workspace", {}).get("current_dir") or data.get("cwd")
    try:
        branch = subprocess.run(
            ["git", "branch", "--show-current"], cwd=cwd, capture_output=True, text=True, timeout=1,
        ).stdout.strip()
    except Exception:
        return None
    return f"({branch})" if branch else None

The filename becomes the segment's name; return None/"" to hide it for a render. An optional PRIORITY: int (default 0) controls drop order among plugins — but plugin segments always drop before any built-in one. A broken plugin (syntax error, exception, bad return type) is silently skipped, never crashes the statusline. Disable loading with --no-plugins, or point elsewhere with --plugins-dir.

Security note: a plugin is a regular Python file that runs with full permissions on every render — there's no sandboxing. Only put plugins in this folder that you wrote yourself or fully trust, the same way you'd treat any script before running it. Never copy a plugin from an untrusted source without reading it first.

Project layout

File Purpose
statusline_toolkit.py The CLI, including the --setup installer.
exchange_rate.json Your USD→currency rates.
sample_statusline_data.json Example payload for trying the tool offline.
test_statusline_toolkit.py Unit tests.
CHANGELOG.md What changed, release by release.
LICENSE MIT license.
pyproject.toml Packaging metadata, for pip/pipx install.
.github/workflows/test.yml CI: runs the test suite on Linux/macOS/Windows for every push and PR.

usage_history.json, usage_dashboard.html, settings.json.bak, and ~/.claude/statusline-toolkit.json are all generated on demand — not part of a fresh checkout, safe to delete anytime.

Tests

python -m unittest test_statusline_toolkit.py -v

Standard library unittest only — no test runner to install.

Troubleshooting

"No input JSON received" / "Input is not valid JSON"

Pass --input sample_statusline_data.json (or your own file), or pipe valid JSON into stdin.

Colors look garbled, or the gradient looks banded instead of smooth

Your terminal doesn't support ANSI/truecolor — use --no-color, or run in a modern terminal (Windows Terminal, a current PowerShell, most Linux/macOS terminal apps).

Windows: "python is not recognized..."

Use the py launcher instead (py statusline_toolkit.py ...), or reinstall Python with "Add python.exe to PATH" checked.

`--setup` didn't seem to take effect

Restart Claude Code — statusLine config is only read at session start. Check ~/.claude/settings.json for a statusLine block pointing at statusline_toolkit.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

statusline_toolkit-1.0.0.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

statusline_toolkit-1.0.0-py3-none-any.whl (21.8 kB view details)

Uploaded Python 3

File details

Details for the file statusline_toolkit-1.0.0.tar.gz.

File metadata

  • Download URL: statusline_toolkit-1.0.0.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for statusline_toolkit-1.0.0.tar.gz
Algorithm Hash digest
SHA256 27ccffafc8226c9c431c87cc9179a8a26cf1116708ab75b3faeb701ff50fc13e
MD5 2bed805f24ae64a054b9db5eab44df55
BLAKE2b-256 d86af2eff742c3db5f4eaae17cb81e4386ef8e54358ed703e17a3ddcf19ddf9d

See more details on using hashes here.

File details

Details for the file statusline_toolkit-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for statusline_toolkit-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 670a64501d762ae03af1d275958a168791e1a258b3811f083a764c1f3a040265
MD5 bf535896b469b5d030517b7d0971a0ca
BLAKE2b-256 2759504d82ff82af977a422a1060e3829d3723f9ff70e612a925bffb98cf456b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page