understatus 0.2.0

A calm, unobtrusive macOS statusline addon for AI coding CLIs (Claude Code): CPU/memory/disk/network + session info with a quiet glyph theme.
# HANDOFF — understatus

> Handoff doc for a fresh agent/session. Product was originally codenamed **statusticon** and renamed to **understatus** before publishing. The on-disk project directory is still `statusticon/` but the product/crate/repo/binary are all **understatus**.

## Goal

A **calm, unobtrusive macOS statusline addon** for AI coding CLIs (primarily Claude Code). It renders one line at the bottom of the terminal showing live system + AI-session info, designed to sit there permanently **without drawing attention**. Now **publicly published** so anyone can install it.

## Key Facts / Coordinates

- **GitHub (public):** https://github.com/ictechgy/understatus — default branch `main`, account `ictechgy` (gh CLI authed).
- **Homebrew tap repo:** https://github.com/ictechgy/homebrew-understatus (`Formula/understatus.rb`, builds from source).
- **Local project dir:** `/Users/jinhongan/Desktop/status_ticon/statusticon` (dir name is legacy; product = understatus).
- **Plan / design rationale (READ THIS FIRST):** `.omc/plans/statusticon.md` (v4) — full ralplan consensus, ADR, design decisions, why reactive double-sample over loadavg, chaining, calm theme. `.omc/` is gitignored (internal).
- **Open Design artifact:** project `status_ticon``statusticon-design.html` (calm design lab; also `docs/design-lab.html` + `docs/understatus-calm-preview*.png`).
- **Language/platform:** Rust 2021, **macOS only** (Apple Silicon + Intel). build.rs links IOKit + CoreFoundation frameworks.

### Published channels (ALL LIVE + verified end-to-end)
| Channel | Version | Install |
|---|---|---|
| crates.io | 0.1.0 | `cargo install understatus` |
| Homebrew | 0.1.0 | `brew install ictechgy/understatus/understatus` |
| npm (wrapper) | **0.1.1** | `npm install -g understatus` |
| GitHub Release | v0.1.0 (arm64 + x64 tarballs + .sha256) ||

> **Version note (intentional):** npm wrapper is **0.1.1** but the native binary is **0.1.0**. The first npm launcher (`npm/bin/understatus.js`) had a rename bug, so only the wrapper was patched to 0.1.1; `npm/install.js` pins the binary download to GitHub release **v0.1.0** (`const VERSION = '0.1.0'`). `understatus --version` prints `0.1.0` (the binary). When cutting a new binary release, update that pin.

### Currently INSTALLED on this machine
`~/.claude/settings.json` → `statusLine.command` = `…/target/release/understatus`, `refreshInterval: 5`. The pre-existing OMC HUD (`node $HOME/.claude/hud/lterm-omc-hud.mjs`) is preserved as `chain_command` in `~/.config/understatus/config.toml` and chained. Backup at `~/.claude/settings.json.understatus.bak`. `understatus uninstall` restores exactly.

## Current Progress

- **P0–P2 complete**, **94 tests passing**, clippy clean, release build green.
  - P1: reactive in-render double-sample CPU% (~25ms, host_processor_info; loadavg fallback clamped 0–100), memory%, calm theme, non-destructive install/chaining, refreshInterval roundtrip.
  - P2: battery (IOKit `IOPSCopyPowerSourcesInfo` + 30s TTL cache), disk (statfs), network (getifaddrs cross-render delta). CPU temperature **excluded from v1** (private/fragile Apple Silicon IOKit keys).
- **Calm design applied** (the headline UX work): glyph ramp `○ ▁ ▄ ▆ ◆` (emoji restorable via `load_glyphs` config), color **only on the glyph** (numeric values uncolored), cool blue-grey band tints + single terracotta critical, **terracotta brightness "breath"** (no red/orange swing) at ≥90% with hysteresis (on ≥90 / off <80), dimmed labels + middot separators, **no BOLD**, HUD seam ``. Config: `~/.config/understatus/config.toml`.
- **Published to all 4 channels** + CI set up (`.github/workflows/ci.yml`, `release.yml`).
- Git: on `main`, clean tree, latest commit `84fe27f`.

## What Worked

- **ralplan consensus planning** (Planner→Architect→Critic, 4 iterations) caught the load-bearing flaw early: Claude Code statusLine is event-driven (not a fixed timer), which broke the original loadavg-delta CPU model → switched to reactive in-render double-sample.
- **Workflow (multi-agent) orchestration** for: design exploration (judge panel of 4 calm directions → "typographic dim hierarchy" won), release scaffolding (Cargo metadata/README/CI/npm/brew in parallel + consistency verify), and applying the calm theme (implement → adversarial review).
- **Direct file-copy into the Open Design project dir + a hand-written `.artifact.json` manifest** to add the 45KB design HTML (avoided reproducing a 45KB blob through a tool argument). Path: `~/Library/Application Support/Open Design/namespaces/release-stable/data/projects/<UUID>/`.
- **Local end-to-end `npm install` test** (into a temp `--prefix`) — this is what caught the broken launcher; always do this after any npm change.
- Using **curl on release asset URLs** to check build status instead of the GitHub REST API (avoids rate limits).

## What Didn't Work (don't repeat)

- **Local x86_64 cross-compile fails on this machine.** There's a Homebrew-rust (default `rustc`/`cargo` in PATH, aarch64-only std) vs rustup (`~/.cargo/bin`, has x86_64 std) conflict → persistent E0463 "can't find crate for core/std" even with `rustup run` / `RUSTUP_TOOLCHAIN` / explicit `+stable`. **Don't try to build x64 locally — use CI on macos-14.**
- **`macos-13` (Intel) GitHub runners are unavailable** — the original release.yml's x64 job queued for 2.5h. Fixed: `release.yml` now builds **both** targets on **macos-14** (arm64 runner) via cross-compile (`rustup target add x86_64-apple-darwin`), and supports `workflow_dispatch` (input `tag`) to rebuild an existing tag without moving it (so the brew source-tarball sha256 stays valid).
- **Global rename `statusticon→understatus` missed `npm/bin/statusticon.js`** (the launcher) — it referenced `../bin/statusticon`, so published npm 0.1.0 couldn't find the binary. Fixed in 0.1.1.
- **`.gitignore` `npm/bin/` was too broad** — it excluded the launcher *source* (`understatus.js`), not just the downloaded binary. Fixed to `/npm/bin/understatus` (binary only).
- **crates.io** publish requires a **verified email** on the account first. **npm** account uses a **passkey**`npm publish` prints a browser auth URL (NOT `--otp`); also must point at the `npm/` folder (`npm publish /…/npm`), not the repo root (root has no package.json).
- **GitHub REST secondary rate limits** hit the `actions/runs`, `releases`, and `topics` endpoints during bursts even with core quota left. Space out `gh` calls; prefer `git push`/`curl` which aren't REST-limited.

## Next Steps (all optional — product is fully shipped)

1. **(Optional) Deprecate broken npm 0.1.0:** `npm deprecate understatus@0.1.0 "broken launcher; use >=0.1.1"` (needs passkey auth; `latest` already points to 0.1.1 so new installs are fine).
2. **(Optional) Add `RELEASING.md`** documenting the multi-channel release flow (below).
3. **P3 (optional):** opt-in background daemon for higher-precision CPU% — *not needed*, reactive double-sample already responsive (~1–2s). See plan §F P3.
4. **P4 (optional):** extract `CliAdapter` trait + Gemini/Codex stub adapters. **Blocked upstream** — Gemini (`/footer`) and Codex (`[tui].status_line`) only expose fixed built-in items, no custom-command statusline yet. Forward-looking only.

### Future release process (for v0.1.x+)
1. Bump `Cargo.toml` version; commit on a branch → PR to `main` (don't commit straight to main except trivial release chores).
2. `git tag vX.Y.Z && git push origin vX.Y.Z``release.yml` builds arm64+x64 on macos-14 and attaches tarballs+sha256 to the GitHub Release.
3. `cargo publish` (crates.io; email verified).
4. Update `homebrew-understatus` `Formula/understatus.rb`: bump `url` to the new tag + recompute source sha256 (`curl -L <archive-url> | shasum -a256`).
5. npm: bump `npm/install.js` `VERSION` pin to the new release tag, bump `npm/package.json` version, then `npm publish /…/npm --access public` (passkey). Always run a local `npm install <folder> --prefix /tmp/test` end-to-end check first.

## Verify current state quickly
```bash
cd /Users/jinhongan/Desktop/status_ticon/statusticon
cargo test                         # 94 passing
cargo build --release              # green
npm view understatus version       # 0.1.1
COLORTERM=truecolor ./target/release/understatus < tests/fixtures/claude_full.json | cat -v
```