Rewrite in Rust: self-installing binary, facelift, memory gauge#2
Merged
Conversation
Port statusline.py + burn.py to a single `quotaline` binary (Rust, serde + serde_json only) at computational parity with the Python: identical percentages, durations, burn rate and cap-ETA, and a byte-identical report. The on-disk usage-history.json schema is unchanged, so an existing history carries over. Also gives the bars a facelift — smooth sub-cell fill (fractional eighth blocks) in a slim frame — and tightens the reset readout to the duration, closer to Claude Code's own compaction bar. Defensive throughout (catch_unwind around render and logging, no unwraps on payload data) so the live line can never break; history writes use a per-process temp file + atomic rename (lock-free, corruption-free). 14 unit tests, clippy-clean, ~400 KB release binary. The Python files stay in place and live until the binary is wired up and verified (later phase).
`quotaline install` / `uninstall` merge or remove the statusLine block in ~/.claude/settings.json directly: cross-platform (works on Windows), order-preserving (shift_remove + serde_json preserve_order), idempotent, backed up first, and refusing to overwrite invalid JSON. The binary wires its own absolute path, so there is no interpreter to detect. The header gains a memory gauge — `mem N% (Xln)` for the current project's MEMORY.md, located via the stdin transcript_path and measured against Claude Code's head-truncation cap (200 lines / 25,000 UTF-16 code units): green below the `dream --refine` budget (190 / 23,500), amber approaching, red once it truncates and memory silently stops loading. Adds --help/usage and a terminal guard so a bare invocation prints usage instead of blocking on stdin. 16 unit tests; clippy-clean.
- release.yml: on a v* tag, cross-compile macOS (arm64/x64), Linux (x64/arm64) and Windows (x64) and attach the binaries to the GitHub Release. - ci.yml: replace ruff + Python smoke test with cargo fmt --check, clippy -D warnings and cargo test across ubuntu / macOS / Windows. - install.sh / install.ps1: download the right release binary into ~/.local/bin (or %LOCALAPPDATA%\quotaline) and run `quotaline install`. Replaces the old Python settings-merging install.sh. The Python files still drive the live status line until the cutover commit.
The status line now runs the quotaline binary (wired via `quotaline install`), so remove statusline.py, burn.py, and the Python smoke test. Their behaviour is covered at parity by the Rust crate and its unit tests, with the new Rust CI.
Lead with the real differentiator surfaced by surveying the field — official limits (read from stdin) vs the log-parsers' estimates, with zero credentials or network vs the token-reusing / claude.ai-scraping tools. Document the single-binary install (curl | bash, PowerShell, from source), the subcommands, the smooth-fill facelift, the memory gauge, and the new state location. Drop all Python references.
A multi-agent review of the branch surfaced issues an inline self-review missed:
- memory.rs: the live render did an unbounded read_to_string of a path derived
from stdin — a FIFO there would hang the status line forever (catch_unwind
cannot catch a hang) and a huge file would OOM it. Now stat-guarded to regular
files with a bounded (1 MiB) read; line count uses split('\n') to match the JS
count Claude Code truncates on.
- install.rs: backup was best-effort — a backup failure still overwrote
settings.json with no backup. Now aborts. write_atomic used a fixed temp name
(concurrent-clobber); now per-process + cleanup on failure. Backup names use
nanoseconds; quote_cmd escapes an embedded quote.
- release.yml: the Windows zip embedded the full target/.../release path so the
installer could not find the exe; now packs a bare binary. All matrix jobs ran
action-gh-release concurrently (release-creation race); now build -> artifact
with a single publish job.
- burn.rs: guard sum_session_delta and the $/% conversion against non-finite
values (no more $NaN headroom). history.rs: clean up the temp on rename failure.
- Add .gitattributes (LF) to keep rustfmt --check stable on Windows CI.
clippy-clean; 16 tests; FIFO-no-hang, memory gauge and install/uninstall verified.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reimplements quotaline as a single self-contained Rust binary (replacing
statusline.py+burn.py) at computational parity, plus the enhancements from this round of work:quotaline(stdin → status line),quotaline report [--window N], andquotaline install/uninstallthat merge/remove thestatusLineblock in~/.claude/settings.jsondirectly: cross-platform (incl. Windows), order-preserving, backed up first, and refusing to overwrite invalid JSON. No interpreter path to detect; ~400 KB native binary.mem N% (Xln)for the project'sMEMORY.mdvs Claude Code's 200-line / 25,000-char head-truncation cap (green → amber at the 190 / 23,500 margin → red once truncating).v*tag cross-compiles macOS/Linux/Windows binaries to the Release; CI runsfmt+clippy -D warnings+teston ubuntu/macOS/Windows.The on-disk
usage-history.jsonschema is unchanged, so existing history carries over. The live status line has already been cut over to the binary.Test plan
cargo fmt --check,clippy -D warnings, 16 unit tests — green locallyreportis byte-identicalinstall/uninstallverified against a temp settings file (merge, key-order, idempotent, invalid-JSON refusal); memory gauge verified against a realMEMORY.mdv1.0.0to build the release binaries, then thecurl | bashinstall works end-to-end