statusline-toolkit 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,312 @@
1
+ Metadata-Version: 2.4
2
+ Name: statusline-toolkit
3
+ Version: 1.0.0
4
+ Summary: A small, dependency-free CLI for inspecting Claude Code's statusLine JSON payload, with currency conversion, cost tracking, and an HTML dashboard.
5
+ Author: gungunfebrianza
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/gungunfebrianza/statusline-toolkit
8
+ Project-URL: Changelog, https://github.com/gungunfebrianza/statusline-toolkit/blob/main/CHANGELOG.md
9
+ Keywords: claude-code,statusline,cli
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # statusline-toolkit
22
+
23
+ [![Tests](https://github.com/gungunfebrianza/statusline-toolkit/actions/workflows/test.yml/badge.svg)](https://github.com/gungunfebrianza/statusline-toolkit/actions/workflows/test.yml)
24
+
25
+ A small, dependency-free Python CLI for Claude Code's [`statusLine`](https://code.claude.com/docs/en/statusline)
26
+ JSON payload. Prints a color-coded one-line summary, with optional currency
27
+ conversion, cost tracking, and an HTML dashboard — all local, all plain
28
+ JSON files you own.
29
+
30
+ ```
31
+ [Claude Sonnet 5] (my-project) [####------] 42% | $0.1234 (~Rp 2.011) | +156/-23 | 45s | $9.87/hr | 5h: 24% 7d: 41%
32
+ ```
33
+
34
+ Works identically on **Linux**, **macOS**, and **Windows**. [MIT licensed](LICENSE).
35
+
36
+ ## Contents
37
+
38
+ - [Quick start](#quick-start)
39
+ - [Usage](#usage)
40
+ - [Reading the summary line](#reading-the-summary-line)
41
+ - [Installing as your Claude Code status line](#installing-as-your-claude-code-status-line)
42
+ - [Currency conversion](#currency-conversion)
43
+ - [Cost tracking: history, stats, and a dashboard](#cost-tracking-history-stats-and-a-dashboard)
44
+ - [Personal defaults file](#personal-defaults-file)
45
+ - [Plugin segments](#plugin-segments)
46
+ - [Project layout](#project-layout)
47
+ - [Tests](#tests)
48
+ - [Troubleshooting](#troubleshooting)
49
+
50
+ ## Quick start
51
+
52
+ Requires Python 3.9+ (`python3` on Linux/macOS, `py` on Windows). Two ways to get it:
53
+
54
+ ```bash
55
+ # Option A: pip/pipx, no clone needed
56
+ pipx install git+https://github.com/gungunfebrianza/statusline-toolkit.git
57
+ statusline-toolkit --setup
58
+
59
+ # Option B: clone and run directly — no install step at all
60
+ git clone https://github.com/gungunfebrianza/statusline-toolkit.git
61
+ cd statusline-toolkit
62
+ python statusline_toolkit.py --input sample_statusline_data.json --idr
63
+ python statusline_toolkit.py --setup
64
+ ```
65
+
66
+ Both are equivalent — it's zero-dependency either way. The rest of this
67
+ README uses `python statusline_toolkit.py ...`; swap in `statusline-toolkit
68
+ ...` if you installed via pip/pipx.
69
+
70
+ ## Usage
71
+
72
+ ```bash
73
+ # Live: pipe whatever JSON Claude Code sends on stdin
74
+ some_producer_of_json | python statusline_toolkit.py
75
+
76
+ # Offline: inspect a saved payload
77
+ python statusline_toolkit.py --input sample_statusline_data.json --all # full JSON
78
+ python statusline_toolkit.py --input sample_statusline_data.json --list # just the field names
79
+ python statusline_toolkit.py --input sample_statusline_data.json --field cost.total_cost_usd
80
+
81
+ # Currency conversion (any ISO 4217 code)
82
+ python statusline_toolkit.py --input sample_statusline_data.json --currency EUR
83
+
84
+ # No colors (for logging, or a terminal that mangles ANSI)
85
+ python statusline_toolkit.py --input sample_statusline_data.json --no-color
86
+ ```
87
+
88
+ ### Flag reference
89
+
90
+ | Flag | Description |
91
+ |---|---|
92
+ | `-i, --input PATH` | Read the JSON payload from a file instead of stdin. |
93
+ | `-a, --all` | Print the entire payload as formatted JSON. |
94
+ | `-l, --list` | List every available field path, without values. |
95
+ | `-f, --field DOT.PATH` | Print just this field; repeatable. |
96
+ | `--currency CODE` | Show cost converted to `CODE` (e.g. `EUR`, `JPY`, `IDR`). |
97
+ | `--idr` | Shorthand for `--currency IDR` (backward compatible). |
98
+ | `--rate RATE` | Override the conversion rate for this run only. |
99
+ | `--rate-file PATH` | Use a different exchange-rate file. |
100
+ | `--no-color` | Disable ANSI colors (also honors `NO_COLOR`). |
101
+ | `--width N` | Override the detected terminal width for adaptive layout. |
102
+ | `--no-adapt` | Never drop segments to fit the width — always the full line. |
103
+ | `--setup` | Install as your Claude Code `statusLine`, then exit. |
104
+ | `-y, --yes` | With `--setup`, skip the overwrite confirmation. |
105
+ | `--settings-file PATH` | With `--setup`, target a different `settings.json`. |
106
+ | `--track` | Record this session's cost to history, for `--stats`/`--dashboard`. |
107
+ | `--stats` | Print a cost report from tracked history, then exit. |
108
+ | `--by-project` / `--by-model` | With `--stats`, group by project/model instead of day. |
109
+ | `--history-file PATH` | Use a different history file. |
110
+ | `--dashboard` | Render an HTML usage dashboard from tracked history, then exit. |
111
+ | `--dashboard-file PATH` | Where to write the dashboard (default: next to the history file). |
112
+ | `--open` | With `--dashboard`, open it in your browser. |
113
+ | `--config PATH` | Use a different [personal defaults file](#personal-defaults-file). |
114
+ | `--plugins-dir PATH` / `--no-plugins` | Custom [plugin](#plugin-segments) directory / skip loading plugins. |
115
+ | `--version` | Print the version and exit. |
116
+
117
+ Run `--help` any time for the same reference from the source.
118
+
119
+ ## Reading the summary line
120
+
121
+ ```
122
+ [Claude Sonnet 5] (my-project) [####------] 42% | $0.1234 (~Rp 2.011) | +156/-23 | 45s | $9.87/hr | 5h: 24% 7d: 41%
123
+ ```
124
+
125
+ | Segment | Meaning |
126
+ |---|---|
127
+ | `[Claude Sonnet 5]` | Model name. |
128
+ | `(my-project)` | Current project folder — helps tell sessions apart. |
129
+ | `[####------] 42%` | Context window used, color-coded green→amber→red. |
130
+ | `$0.1234 (~Rp 2.011)` | USD cost, plus a converted estimate if `--currency`/`--idr` is passed. |
131
+ | `+156/-23` | Lines added/removed, colored git-style (green/red). |
132
+ | `45s` | Session duration. |
133
+ | `$9.87/hr` | **Burn rate** — cost extrapolated to an hourly pace (a derived number, not a raw field). |
134
+ | `5h: 24% 7d: 41%` | 5-hour / 7-day rate-limit usage. |
135
+
136
+ Any segment just disappears if the payload doesn't have that data — nothing errors.
137
+
138
+ **Colors** blend smoothly from green (low) to amber to red (high) on
139
+ terminals with 24-bit color support, and fall back to plain green/yellow/red
140
+ otherwise. `--no-color` or `NO_COLOR=1` turns all of it off.
141
+
142
+ **Adaptive width:** if the full line wouldn't fit your terminal, the least
143
+ essential segments drop first — rate limits, then burn rate, duration,
144
+ lines, project, currency — until it fits, or down to just
145
+ `[model] [bar] % | $cost` if space is very tight. Use `--width N` to set
146
+ the width explicitly (handy since Claude Code runs this headless, so
147
+ there's often nothing real to detect) or `--no-adapt` to always print the
148
+ full line.
149
+
150
+ ## Installing as your Claude Code status line
151
+
152
+ ```bash
153
+ python statusline_toolkit.py --setup # default: IDR
154
+ python statusline_toolkit.py --setup --currency EUR # a different currency
155
+ python statusline_toolkit.py --setup --currency EUR --track # also track cost history
156
+ ```
157
+
158
+ This detects your OS and writes a `statusLine` entry into
159
+ `~/.claude/settings.json`, backing up any existing config first. It's
160
+ idempotent (safe to re-run) and asks before overwriting a different
161
+ `statusLine` (skip with `-y`). Restart Claude Code afterward to see it
162
+ take effect.
163
+
164
+ ## Currency conversion
165
+
166
+ `exchange_rate.json` holds manually maintained rates you control — no
167
+ network calls, no API keys:
168
+
169
+ ```json
170
+ {
171
+ "rates": { "IDR": 16300, "EUR": 0.92 },
172
+ "updated_at": "2026-07-06"
173
+ }
174
+ ```
175
+
176
+ Add a currency to `rates` and pass `--currency CODE`, or use
177
+ `--currency CODE --rate <value>` for a one-off conversion without
178
+ touching the file. If a currency isn't configured, the script tells you
179
+ exactly what to add rather than guessing. If `updated_at` is over 30 days
180
+ old, you'll get a one-line reminder to refresh it.
181
+
182
+ (Older single-currency files — `{"usd_to_idr": 16300, ...}` — still work unchanged.)
183
+
184
+ ## Cost tracking: history, stats, and a dashboard
185
+
186
+ `--track` records each session's cost to `usage_history.json` (keyed by
187
+ session, so re-renders don't double-count). Then:
188
+
189
+ ```bash
190
+ python statusline_toolkit.py --input sample_statusline_data.json --track
191
+ python statusline_toolkit.py --stats # grouped by day
192
+ python statusline_toolkit.py --stats --by-project # or by project / --by-model
193
+ python statusline_toolkit.py --dashboard --open # visual HTML report
194
+ ```
195
+
196
+ `--stats` prints a per-group cost/session breakdown with a grand total.
197
+ `--dashboard` renders the same data as a self-contained HTML file — summary
198
+ cards plus cost-by-day/project/model bar charts, no JS framework, no CDN,
199
+ light/dark aware — and only opens a browser if you pass `--open`.
200
+
201
+ Everything here is opt-in and local: nothing is tracked or rendered unless
202
+ you ask, and `usage_history.json` is plain JSON you can inspect or delete
203
+ anytime.
204
+
205
+ ## Personal defaults file
206
+
207
+ Tired of retyping the same flags? Put them in
208
+ `~/.claude/statusline-toolkit.json`:
209
+
210
+ ```json
211
+ {
212
+ "currency": "EUR",
213
+ "track": true,
214
+ "width": 100
215
+ }
216
+ ```
217
+
218
+ Every key is optional and mirrors a CLI flag (`no_color`, `by_project`,
219
+ `by_model`, `no_adapt`, `rate_file`, `history_file`, `plugins_dir`,
220
+ `no_plugins` are all supported too). **CLI flags always override the
221
+ file.** Use `--config PATH` for a different file (e.g. separate
222
+ personal/work profiles).
223
+
224
+ ## Plugin segments
225
+
226
+ Add your own segment (git branch, whatever) without touching the script:
227
+ drop a `.py` file into `~/.claude/statusline-plugins/` defining one function.
228
+
229
+ ```python
230
+ # ~/.claude/statusline-plugins/git_branch.py
231
+ import subprocess
232
+
233
+ def segment(data: dict, use_color: bool) -> str | None:
234
+ cwd = data.get("workspace", {}).get("current_dir") or data.get("cwd")
235
+ try:
236
+ branch = subprocess.run(
237
+ ["git", "branch", "--show-current"], cwd=cwd, capture_output=True, text=True, timeout=1,
238
+ ).stdout.strip()
239
+ except Exception:
240
+ return None
241
+ return f"({branch})" if branch else None
242
+ ```
243
+
244
+ The filename becomes the segment's name; return `None`/`""` to hide it for
245
+ a render. An optional `PRIORITY: int` (default `0`) controls drop order
246
+ among plugins — but plugin segments always drop before any built-in one.
247
+ **A broken plugin (syntax error, exception, bad return type) is silently
248
+ skipped, never crashes the statusline.** Disable loading with
249
+ `--no-plugins`, or point elsewhere with `--plugins-dir`.
250
+
251
+ > **Security note:** a plugin is a regular Python file that runs with full
252
+ > permissions on every render — there's no sandboxing. Only put plugins in
253
+ > this folder that you wrote yourself or fully trust, the same way you'd
254
+ > treat any script before running it. Never copy a plugin from an untrusted
255
+ > source without reading it first.
256
+
257
+ ## Project layout
258
+
259
+ | File | Purpose |
260
+ |---|---|
261
+ | `statusline_toolkit.py` | The CLI, including the `--setup` installer. |
262
+ | `exchange_rate.json` | Your USD→currency rates. |
263
+ | `sample_statusline_data.json` | Example payload for trying the tool offline. |
264
+ | `test_statusline_toolkit.py` | Unit tests. |
265
+ | `CHANGELOG.md` | What changed, release by release. |
266
+ | `LICENSE` | MIT license. |
267
+ | `pyproject.toml` | Packaging metadata, for `pip`/`pipx install`. |
268
+ | `.github/workflows/test.yml` | CI: runs the test suite on Linux/macOS/Windows for every push and PR. |
269
+
270
+ `usage_history.json`, `usage_dashboard.html`, `settings.json.bak`, and
271
+ `~/.claude/statusline-toolkit.json` are all generated on demand — not
272
+ part of a fresh checkout, safe to delete anytime.
273
+
274
+ ## Tests
275
+
276
+ ```bash
277
+ python -m unittest test_statusline_toolkit.py -v
278
+ ```
279
+
280
+ Standard library `unittest` only — no test runner to install.
281
+
282
+ ## Troubleshooting
283
+
284
+ <details>
285
+ <summary><strong>"No input JSON received" / "Input is not valid JSON"</strong></summary>
286
+
287
+ Pass `--input sample_statusline_data.json` (or your own file), or pipe
288
+ valid JSON into stdin.
289
+ </details>
290
+
291
+ <details>
292
+ <summary><strong>Colors look garbled, or the gradient looks banded instead of smooth</strong></summary>
293
+
294
+ Your terminal doesn't support ANSI/truecolor — use `--no-color`, or run in
295
+ a modern terminal (Windows Terminal, a current PowerShell, most
296
+ Linux/macOS terminal apps).
297
+ </details>
298
+
299
+ <details>
300
+ <summary><strong>Windows: "python is not recognized..."</strong></summary>
301
+
302
+ Use the `py` launcher instead (`py statusline_toolkit.py ...`), or
303
+ reinstall Python with "Add python.exe to PATH" checked.
304
+ </details>
305
+
306
+ <details>
307
+ <summary><strong>`--setup` didn't seem to take effect</strong></summary>
308
+
309
+ Restart Claude Code — `statusLine` config is only read at session start.
310
+ Check `~/.claude/settings.json` for a `statusLine` block pointing at
311
+ `statusline_toolkit.py`.
312
+ </details>
@@ -0,0 +1,7 @@
1
+ statusline_toolkit.py,sha256=GNT3WIHFY9BWS7wgS1-qa5PAJlk2_M5rBMwmPzr0EsI,44784
2
+ statusline_toolkit-1.0.0.dist-info/licenses/LICENSE,sha256=trdJLnU38r6Js0hKaZDTLE4pQdUM9rGpqHefMLXkFhU,1072
3
+ statusline_toolkit-1.0.0.dist-info/METADATA,sha256=g_S5LVoWrVrZY_peQylcBZZPvBDcuVxUUvxZvUHrPLE,13092
4
+ statusline_toolkit-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
5
+ statusline_toolkit-1.0.0.dist-info/entry_points.txt,sha256=Sb7uJBFjmkIdt7pBEdm-7zXH9lAJpB4ujsVhmQ7S50Q,63
6
+ statusline_toolkit-1.0.0.dist-info/top_level.txt,sha256=m0WGh14vs5N8s0gjVzQPd2CH9PVl3i8bBUQUcVMZdZM,19
7
+ statusline_toolkit-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ statusline-toolkit = statusline_toolkit:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gungunfebrianza
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ statusline_toolkit