Skip to content

Add Rust toolchain installers and shell-detection hardening#228

Open
kigster wants to merge 2 commits into
mainfrom
kig/rust-tools
Open

Add Rust toolchain installers and shell-detection hardening#228
kigster wants to merge 2 commits into
mainfrom
kig/rust-tools

Conversation

@kigster
Copy link
Copy Markdown
Owner

@kigster kigster commented May 16, 2026

Add Rust toolchain installers and shell-detection hardening

Summary

Adds two new user-facing executables — bin/rust-install and bin/rust-install-tools — that provide an opinionated, idempotent installation flow for the Rust toolchain (rustup + cargo) and a curated set of modern Rust-based CLI/TUI tools (installed via cargo-binstall so users don't compile everything from source). Also hardens shell detection in lib/color.sh and removes a pair of stray aliases (find, ls) in init.sh that could leak from a user's interactive shell into sourced scripts.

Description

New executables

  • bin/rust-install — bootstraps rustup and the stable Rust toolchain. Self-installs Bashmatic if it isn't present, re-execs under modern Bash when invoked from macOS's stock Bash 3, and uses Bashmatic's run/output primitives for consistent, colorful progress reporting.
  • bin/rust-install-tools — installs a curated set of Rust CLI/TUI tools, skipping anything already present. For each missing tool, prints an h2bg banner describing what the tool does and then installs it via cargo-binstall (with a source-build fallback for tools without prebuilt artifacts).

Both scripts follow the Bashmatic conventions documented in CLAUDE.md:

  • No .sh extension on bin/ files.
  • Re-exec under Bash 4+ when run on macOS's /bin/bash (Bash 3).
  • Source init rather than poking at internals.
  • Defensive on missing prerequisites — bootstraps Bashmatic itself if absent.

Library changes

  • lib/color.sh — replaces ${SHELL}-based shell detection (which reads the login shell, not the currently executing shell) with ${ZSH_VERSION} / ${BASH_VERSION} detection. Picks the correct typeset -gx / declare -g / declare form for the actual runtime. Avoids exec'ing into a different shell from a sourced library, which would break both bin/* scripts and interactive zsh sessions.
  • init.sh — adds unalias find 2>/dev/null and unalias ls 2>/dev/null near the top of the main flow so user aliases (commonly ls=eza, find=fd) don't poison Bashmatic's internal command invocations.

Incidental

  • .vscode/settings.json — adds RUSTUP to the cSpell dictionary.
  • CLAUDE.md — minor heading tweak.

Motivation

The Rust ecosystem now hosts a number of best-in-class replacements for traditional Unix tools (e.g. ripgrep, fd, bat, eza, zoxide, bottom, dust, procs, delta, tokei). Bashmatic already ships installers for Ruby, Node, and PostgreSQL tooling; adding a Rust installer rounds out the developer-bootstrap story so a fresh machine can be brought to a "Bashmatic + a useful CLI toolbelt" state with two commands.

The color.sh and init.sh fixes are prerequisites surfaced while developing the new scripts: without correct shell detection in color.sh the new scripts fail when invoked from zsh, and without the unalias calls in init.sh an aliased find or ls in the user's environment causes confusing failures inside the installers.

Testing

  • Ran bin/rust-install on a clean macOS account; verified rustup, cargo, and the stable toolchain installed correctly and the script is idempotent on a second run.
  • Ran bin/rust-install-tools after rust-install; confirmed all listed tools install via cargo-binstall, the per-tool banner renders, and re-running the script reports each tool as already present and exits cleanly.
  • Ran the Bats suite via bin/specs — no regressions from the lib/color.sh / init.sh changes.
  • Verified bin/rust-install and bin/rust-install-tools both correctly re-exec under Bash 4+ when launched from /bin/bash on macOS.

Backwards Compatibility

  • lib/color.sh: the new detection path is strictly broader — it now correctly handles zsh and Bash 3, where the old ${SHELL} check could pick the wrong declare form. Callers that previously set ${GLOBAL} themselves are unaffected (the new code unconditionally sets it based on detected runtime, matching prior intent).
  • init.sh: the two unalias calls are scoped to the script's own subshell and run with 2>/dev/null, so users with no such aliases see no behavior change.
  • New bin/ executables don't shadow any existing command names.

Scalability & Performance Impact

None — the library changes are constant-time and run once at source time. The new executables are user-invoked installers; their cost is dominated by network and disk operations from rustup/cargo-binstall.

Code Quality Analysis

  • Both new scripts follow the project's house style: dotted public-namespace conventions where applicable, run-mediated command execution, usage-style help, and use of Bashmatic's output helpers (h1, h2bg, inf, ok:/not-ok:).
  • lib/color.sh now carries a short comment explaining why ${SHELL} is the wrong knob and why this library must not exec, addressing a subtle bug class that would otherwise reappear.
  • No abbreviations in new public-facing names; no .sh extensions on bin/ executables.

- bin/rust-install: bootstraps rustup + stable Rust toolchain
- bin/rust-install-tools: installs curated Rust CLI/TUI tools via cargo-binstall
- lib/color.sh: detect runtime shell via $ZSH_VERSION/$BASH_VERSION instead of $SHELL (login shell), and stop exec'ing from a sourced library
- init.sh: unalias find/ls in main flow so user aliases don't leak into Bashmatic internals
- .vscode/settings.json: add RUSTUP to cSpell dictionary
- CLAUDE.md: minor heading tweak
@kigster kigster self-assigned this May 16, 2026
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