Skip to content

feat(cli): polish installation and upgrade progress UI - #66

Open
yan-ad wants to merge 1 commit into
Blankeos:mainfrom
yan-ad:feat/install-upgrade-ui
Open

yan-ad wants to merge 1 commit into
Blankeos:mainfrom
yan-ad:feat/install-upgrade-ui

Conversation

@yan-ad

@yan-ad yan-ad commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Beautify installation and crabcode upgrade output using the supplied terminal reference: compact current/target version labels, whitespace, and an amber block/dotted progress row. Based directly on upstream main (bf5c111), independent of plugin PR #25.

  • Shell/npm downloads show measured progress when size is known; unknown duration upgrades show Working rather than a fabricated percentage.
  • Respect terminal width, NO_COLOR, TERM=dumb, and redirected output. Diagnostics stay on stderr; no alternate screen or cursor hiding.
  • Keep in-app background upgrades captured and silent.
  • Replace the stale Bash/cargo-first root install.sh with a POSIX prebuilt installer using real release archive names, SHA256 verification, staged atomic binary replacement, and installation receipts.
  • Preserve flat/custom install destinations and historical cargo-dist cargo-home layouts. Reject mismatched receipts and invalid versions, and never silently substitute the latest release for a requested version.
  • Drain npm download streams correctly, report truncation/write errors, and close progress on failure.
  • Add just test-upgrade-ui; extend just test-release with shell installer coverage.

UI preview (plain-text structure)

Installed version: 0.0.14

Installing crabcode version: 0.0.15
████████..........................................  17%

This is a layout illustration, not a claim that v0.0.15 was installed. Package-manager upgrades use an indeterminate Working row because those tools do not expose a reliable end-to-end completion percentage. Existing cargo-dist-generated release installer assets are not rewritten.

Validation

  • cargo fmt --all -- --check, git diff --check, cargo check: pass.
  • cargo test --bin crabcode upgrade:: -- --test-threads=1: 25 pass.
  • bun test --timeout 30000 scripts/release-workflow.test.ts scripts/install-ui.test.ts npm/install.test.js: 80 pass. An initial final rerun hit Bun's default 5-second test deadline under concurrent builds; the bounded 30-second rerun passed.
  • cargo build --bin crabcode + bun test scripts/upgrade-ui.test.ts: 13 pass; exercises the compiled CLI in real PTYs and isolated install fixtures.
  • node --test npm/install.test.js: 13 pass.
  • Prettier check for changed JS/TS and sh -n install.sh: pass.
  • Real GitHub v0.0.14 release installed in a disposable directory, checksum verified, and --version confirmed. Host installation untouched.

Full serial Rust unit suite: 1,844 passed, 1 failed, 3 ignored. The failure is ui::components::chat::tests::test_edit_tool_renders_codex_style_diff_summary, which hardcodes /Users/carlo/Desktop/Projects/crabcode/README.md and expects a relative filename on this checkout. The chat source is unchanged in this PR; the same failure was reproduced on unmodified upstream bf5c111 in a separate worktree. Not claiming a globally green suite.

Design audit and limits

Audited after implementation as requested. No further design changes requiring approval: inherited terminal theme, one amber accent, no panels/badges/decorative emoji, actual loading/error/no-op states, and bounded progress widths. Terminal palettes are user-controlled, so universal color contrast cannot be guaranteed; NO_COLOR is supported.

Runtime tested on macOS. Linux/Windows execution and OS-signal cancellation during a download were not specifically exercised. No dependencies added. Do not merge automatically.

@Blankeos

Blankeos commented Nov 7, 2026

Copy link
Copy Markdown
Owner

feat/install-upgrade-ui → main
Model: claude-sonnet-5-5, effort unknown

Confidence: 4/5

Behavior works end to end on macOS (real v0.0.14 install, real upgrade, failure paths), checks pass apart from environmental/pre-existing failures. Held back from 5 by size (about 1.7k lines, rewrites the public install.sh) and no Linux or Windows run.

Checks run (worktree of PR head 71a8cb6, separate target dir):

  • cargo fmt --check: clean.
  • cargo build: ok.
  • cargo test (whole suite): 1842-1843 passed, 2-3 failed, 3 ignored, integration tests ok. Failures: chat::test_edit_tool_renders_codex_style_diff_summary (hardcoded /Users/carlo/... path, also fails on main, as the author says) and under parallel load model::discovery::...custom_endpoint_failure... and chat::...billed_output.... Neither is in code this PR touches, and the discovery one passes alone. cargo test --bin crabcode upgrade::: 25 passed.
  • cargo clippy --all-targets -D warnings: nothing located in lines this PR adds (the only two hits in src/upgrade.rs, lines 247 and 250, are pre-existing || load_shell_install_receipt() closures).
  • bun test scripts/install-ui.test.ts npm/install.test.js: 69 passed. bun test scripts/upgrade-ui.test.ts: 13 passed, after copying the binary to ./target/debug/crabcode (the suite hardcodes that path, see Regressions). scripts/release-workflow.test.ts (unchanged file): 11 fail here because this machine's python3 is 3.9 with no tomllib. Environmental, not caused by the PR. sh -n install.sh: ok.
  • Real behavior, scratch HOME/XDG under /tmp/pr66-demo, no credentials:
    • install.sh 0.0.14 against the real GitHub release: downloaded, checksum verified, installed to the custom CRABCODE_INSTALL_DIR, wrote a flat receipt, crabcode --version = 0.0.14. Re-run with latest works. ../x is rejected before any network call. 9.9.9 returns 404 on .tar.gz, tries .tar.xz, fails with "Legacy archive download failed" and leaves no partial files behind.
    • crabcode upgrade 0.0.13 with the PR binary and a flat receipt: used the embedded install.sh, took the xz legacy fallback, exit 0, receipt updated.
    • Merge check: git merge-tree against current main is clean (PR is 14 commits behind, no conflicts).
  • Screenshots (Ghostty, real terminal):

install.sh progress
crabcode upgrade, in progress
crabcode upgrade, done

Confidence bumps: Linux and Windows/PowerShell runs (no hosts here) and a brew/npm/cargo-driven crabcode upgrade (would modify the real package managers) -> 4.5/5. Cancelling mid-download with a signal was not exercised either.

Summary

Replaces the Bash/cargo-first root install.sh with a POSIX prebuilt-release installer: SHA256-verified, staged atomic replace, writes an install receipt, rejects invalid versions, keeps the xz fallback for old releases. crabcode upgrade now prints compact "Installed / Upgrading" labels and an amber indeterminate "Working" row (stderr only, honours NO_COLOR, TERM=dumb, non-TTY). npm/install.js gets a measured progress bar with correct stream draining and truncation errors. Receipt matching is tightened so a stale or foreign receipt cannot redirect an upgrade. For flat/no-receipt installs the binary now runs the install.sh embedded at build time via include_bytes!, and Cargo.toml include is updated so crates.io packaging still compiles.

The code reads carefully and the offline tests exercise real code paths, with real PTYs for the CLI. The installer scripting is paranoid in a good way (validated version, tar inventory check, regular-file check, JSON escaping of the prefix).

Map

flowchart TD
  A[install.sh<br/>POSIX prebuilt installer] -->|embedded include_bytes| B[src/upgrade.rs]
  B --> C[src/upgrade/progress.rs<br/>Working row]
  B -->|receipt claims_path, flat vs cargo-home| A
  D[npm/install.js<br/>progress, drain, errors] --- E[npm/install.test.js]
  A --- F[scripts/install-ui.test.ts]
  B --- G[scripts/upgrade-ui.test.ts<br/>real PTY]
  H[Cargo.toml include, justfile, README]
Loading

Start at src/upgrade.rs (upgrade_install_script_captured, claims_path), then install.sh.

Regressions

No functional regressions found. Things a maintainer should know:

  • Scope. A "polish UI" PR that also rewrites the public installer, changes receipt-ownership rules and adds about 800 lines of test harness. npm/install.js also carries unrelated Prettier reflow of existing code (fetchResponse), which adds diff noise. Worth a deliberate decision rather than a rubber stamp.
  • Behavior change for curl | sh users: the old script ran cargo install when cargo was present; the new one always installs the prebuilt binary (cargo-first path is gone). Probably desirable, but it is a change.
  • crabcode upgrade never shows a measured percentage. The installer's output is captured, so only the indeterminate "Working" row appears. The measured bar is only in install.sh and npm postinstall. The PR text slightly oversells this.
  • crabcode upgrade output moved from stdout to stderr. Anything scripting around its stdout will see nothing.
  • Misleading "Installed version" in install.sh. When the target dir has no binary it falls back to whatever crabcode is on PATH, so a fresh install into a custom dir printed "Installed version: 0.0.14" (my real binary). Minor.
  • scripts/upgrade-ui.test.ts hardcodes target/debug/crabcode and ignores CARGO_TARGET_DIR, so it fails ("Missing compiled CLI") for anyone using a custom target dir. Also, bun test of release-workflow.test.ts needs python >= 3.11, which is not new, but just test-release now includes it.
  • The upgrade path for non-flat receipts no longer falls back to the latest installer asset (intended per the description), so a release missing crabcode-installer.sh now fails instead of silently installing a different version.

Migrations

Not needed. Existing cargo-dist receipts (cargo-home layout, <prefix>/bin) still match; unspecified/unknown layouts no longer claim a path, which I checked cannot occur in receipts written by the v0.0.14 installer (it always substitutes the layout).

Before merging

  • Decide whether the installer rewrite should be split from the upgrade UI change (or accepted as is)
  • Make scripts/upgrade-ui.test.ts honour CARGO_TARGET_DIR (or build to a known path)
  • Optional: don't fall back to a PATH crabcode for "Installed version" when the destination dir has none
  • Run install.sh once on Linux (x86_64 and aarch64) before announcing it in the README
  • Note the stdout -> stderr change in release notes

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.

2 participants