Skip to content

Rewrite in Rust: self-installing binary, facelift, memory gauge#2

Merged
gvonness-apolitical merged 6 commits into
mainfrom
rust-rewrite
Jun 17, 2026
Merged

Rewrite in Rust: self-installing binary, facelift, memory gauge#2
gvonness-apolitical merged 6 commits into
mainfrom
rust-rewrite

Conversation

@gvonness-apolitical

Copy link
Copy Markdown
Contributor

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:

  • Single self-installing binaryquotaline (stdin → status line), quotaline report [--window N], and quotaline install / uninstall that merge/remove the statusLine block in ~/.claude/settings.json directly: cross-platform (incl. Windows), order-preserving, backed up first, and refusing to overwrite invalid JSON. No interpreter path to detect; ~400 KB native binary.
  • Bar facelift — smooth sub-cell fill (fractional eighth-blocks) in a slim frame, closer to Claude Code's compaction bar; reset readout tightened to the duration.
  • Memory gaugemem N% (Xln) for the project's MEMORY.md vs Claude Code's 200-line / 25,000-char head-truncation cap (green → amber at the 190 / 23,500 margin → red once truncating).
  • Release pipeline + Rust CI — a v* tag cross-compiles macOS/Linux/Windows binaries to the Release; CI runs fmt + clippy -D warnings + test on ubuntu/macOS/Windows.
  • README repositioned around the real differentiator (official limits read from stdin, zero credentials/network) vs the log-parser and token-reuse/scraper tools in the field.

The on-disk usage-history.json schema 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 locally
  • Output parity vs the Python verified on real payloads; report is byte-identical
  • install/uninstall verified against a temp settings file (merge, key-order, idempotent, invalid-JSON refusal); memory gauge verified against a real MEMORY.md
  • No unix-only APIs (portable to Windows); CI exercises Windows
  • CI green on this PR (fmt + clippy + test across ubuntu/macOS/Windows)
  • After merge: tag v1.0.0 to build the release binaries, then the curl | bash install works end-to-end

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.
@gvonness-apolitical gvonness-apolitical merged commit 8859048 into main Jun 17, 2026
3 checks passed
@gvonness-apolitical gvonness-apolitical deleted the rust-rewrite branch June 17, 2026 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant