@dahch/heimdall
v1.1.0
Published
Heimdall: resilient validator and updater for system and global packages
Maintainers
Readme
Heimdall (hmd)
A dynamic, resilient, and modern CLI to inspect, validate, and update system packages, runtimes, and global tools across macOS and Linux.
✨ Features
- 🔍 Dynamic Discovery: Automatically identifies which package managers are installed on the host operating system without requiring static machine configuration.
- 🛡 Extremely Resilient: Network timeouts, missing binaries, or individual package build errors are isolated gracefully. If one package or manager encounters an issue, all other managers continue uninterrupted.
- 📋 Two-Phase Workflow:
- Detection & Bounded Scan: Available package managers are checked concurrently using an internal worker pool (concurrency limit of 4) to query pending updates without overloading CPU or network.
- Aggregated Review & Confirmation: Shows an interactive tabular overview comparing current and latest package versions across all managers, prompting for confirmation before modifying the system.
- 🧪 True Simulated Dry-Run (
--dry-run): Traverses the full engine lifecycle, formats outdated packages, and executes mock update routines step-by-step with real-time feedback without touching system files. - ⚡ High-Speed Registry Queries: Yarn and pipx bypass heavy CLI subprocess spawning by querying the npm Registry and PyPI JSON APIs directly over HTTP with strict 3-second abort timeouts.
- 🔐 Non-Interactive Sudo Pre-Checks: Privileged managers (MacPorts, Linux APT, Linux DNF) verify cached credentials using
sudo -n truebeforehand, preventing terminal lockups and password prompt hangs. - 🎨 Modern Minimalist UX: Terminal interface powered by
@clack/prompts, micro-border tabular layouts with directional version transitions (current → latest), persistent real-time step progression with elapsed durations, and actionable error extraction. - 🏷 Dynamic Version Resolution: Reads package name and version dynamically from
package.jsonat runtime viaimport.meta.url, ensuring banners and--versionflags remain in sync with repository releases. - ⚙ Flexible Targeting: Run interactively, execute non-interactively with
--yes, or filter target managers using--onlyand--exclude.
📦 Supported Package Managers
Heimdall (hmd) supports 14 package managers across system, runtime, language, and application store categories:
| Manager | Icon | Category | Detection Strategy | Update Routine & Resilience Rules |
| :--- | :---: | :---: | :--- | :--- |
| Homebrew | 🍺 | system | brew outdated --json=v2 (JSON parsing with raw text fallback) | 1. brew update2. Selective upgrade based on pending item types: brew upgrade --cask (if only casks), brew upgrade --formula (if only formulae), or full brew upgrade (if both)3. brew cleanup |
| npm (global) | 📦 | runtime | npm outdated -g --json (tolerates exit code 1) | 1. Targeted install: npm install -g --legacy-peer-deps -- <targets> (batched if multiple, direct if single)2. Fallback: If batch install hits peer conflicts, falls back to isolated per-package installs.3. Script Resilience: Retries failing packages with --ignore-scripts -- <target> if install lifecycle hooks fail (e.g. only-allow pnpm). |
| pnpm (global) | ⚡ | runtime | pnpm outdated -g --format json (extracts embedded JSON chunks) | pnpm update -g --latest |
| Bun | 🍞 | runtime | bun outdated -g (ASCII table column parser) | 1. bun add -g <pkg>@latest (bypasses global semver pin lockouts)2. bun update -g3. bun upgrade (automatically skipped if Bun is managed via Homebrew) |
| Yarn (global) | 🧶 | runtime | yarn global list --depth=0 + native npm registry HTTP checks | 1. yarn global add <pkg>@latest (bypasses global semver lockouts)2. yarn global upgrade |
| Python (pip user) | 🐍 | language | pip3 list --user --outdated --format=json (targets user site-packages) | pip3 install --user --upgrade <pkgs> (complies with PEP 668 externally managed environment protections) |
| pipx | 📦 | language | pipx list --json + native PyPI JSON API lookups | pipx upgrade-all |
| Rust (Cargo & Rustup) | 🦀 | language | rustup check (toolchains) + cargo install-update -l (crates) | 1. rustup update (if rustup exists)2. cargo install-update -a (if cargo-update is installed) |
| Ruby Gem | 💎 | language | gem outdated (skips deprecated Apple System Ruby /usr/bin/gem) | 1. gem update --user-install2. gem cleanup |
| MacPorts | ⚓ | system | port outdated + non-interactive sudo -n true verification | 1. sudo port selfupdate2. sudo port upgrade outdated |
| Mac App Store (mas) | 🍎 | appstore | mas outdated | mas upgrade |
| APT (Debian/Ubuntu) | 🐧 | system | apt list --upgradable + non-interactive sudo -n true check | 1. sudo apt-get update -y2. sudo apt-get upgrade -y3. sudo apt-get autoremove -y |
| DNF (Fedora/RHEL) | 📦 | system | dnf check-update -y (exit code 100 signals updates) + sudo -n true check | 1. sudo dnf upgrade -y --refresh2. sudo dnf autoremove -y (prompted interactively with confirmation prompt, auto-approved with --yes or --dry-run) |
| Flatpak | 📦 | system | flatpak remote-ls --updates | flatpak update -y --noninteractive |
🚀 Installation & Setup
Global Installation
npm install -g @dahch/heimdall
# or
bun add -g @dahch/heimdall
# or
pnpm add -g @dahch/heimdallPrerequisites
- Node.js >= 20.0.0
- Bun or pnpm or npm
Local Development Setup
# Clone repository
git clone https://github.com/dahch/heimdall.git
cd heimdall
# Install dependencies
bun install
# or: pnpm install
# Build binary with tsup
bun run build
# or: pnpm build
# Link binary globally
npm linkAfter linking, both hmd (primary short command) and heimdall (canonical alias) will be available in your terminal.
💻 CLI Usage
hmd [options]
# Or using the canonical alias:
heimdall [options]Options Reference
| Flag | Long Flag | Description | Default |
| :--- | :--- | :--- | :--- |
| -y | --yes | Skip confirmation prompt and apply all detected updates automatically | false |
| -d | --dry-run | Inspect outdated packages and simulate update execution without modifying the host | false |
| -o | --only <mgrs> | Comma-separated list of managers to include (e.g. brew,npm,bun) | All available |
| -x | --exclude <mgrs> | Comma-separated list of managers to exclude (e.g. gem,macports) | None |
| -t | --timeout <ms> | Network/subprocess timeout per check phase in milliseconds | 25000 |
| -v | --verbose | Output detailed diagnostic messages and skipped manager listings | false |
| -h | --help | Display command help and option summary | — |
| -V | --version | Output CLI version (dynamically resolved from package.json) | Dynamic |
Usage Examples
# 1. Standard Interactive Workflow
# Discovers managers, scans updates, presents color table, prompts for choice
hmd
# 2. Dry-run Mode
# Discovers managers, scans updates, runs simulated steps through the engine
hmd --dry-run
# 3. Automated Routine (ideal for CI, cron jobs, or shell scripts)
hmd --yes
# 4. Target Specific Package Managers
hmd --only brew,npm,bun
# 5. Exclude Slow or Privileged Managers
hmd --exclude macports,apt
# 6. Adjust Check Timeout & Enable Verbose Diagnostic Logging
hmd --timeout 40000 --verbose
# 7. Using the Canonical Alias
heimdall --dry-run🧪 Testing
The test suite is powered by Vitest and provides comprehensive unit coverage for parser routines, engine concurrency, timeout isolation, and manager fallback logic:
# Run test suite (Vitest)
bun run test # or: pnpm test
# Run static typecheck
bun run typecheckTest coverage includes:
- JSON and text parser edge cases (npm exit code 1, mixed pnpm CLI output, bun table formats).
- Error extraction and sanitization (
extractErrorMessage) handling npm warnings, command failure chains, and clean truncation. - Concurrency pool bounds and error isolation in
UpdaterEngine. NpmManagertargeted batch installation, fallback trigger handling, and--ignore-scriptsresilience.HomebrewManagerselective formula vs. cask execution branches.- Pre-check behaviors (skipping
/usr/bin/gem, sudo privilege checks for MacPorts and APT). - HTTP registry lookup error handling for Yarn and pipx.
- Formatting renderers (micro-border table, directional version diffs, execution summary metrics).
🚀 Release & Publishing Pipeline
Heimdall employs an automated GitHub Actions CI/CD workflow (.github/workflows/publish.yml) for publishing to npm:
- Tag-Driven Trigger: Releases trigger on git tag pushes matching
v*(e.g.v1.0.0). - Version Verification: Verifies tag name strictly matches the
versionfield inpackage.json. - Reproducible Build: Installs dependencies with
bun install --frozen-lockfileand builds the bundle viabun run build. - Verification Gates: Runs the test suite and static typecheck via
bun run test && bun run typecheck. - NPM Provenance: Publishes to npm under
@dahch/heimdallwith cryptographic provenance attestations (npm publish --provenance) via OpenID Connect (OIDC).
📄 Documentation
- SPEC.md: Technical specification, CLI contract, data models, and exit codes.
- DESIGN.md: System architecture, Two-Phase workflow, Engine concurrency pool, and Mermaid diagrams.
- ADR.md: Architectural Decision Records (ADR-001 through ADR-010) documenting key engineering decisions.
- AGENTS.md: Developer and AI agent reference manual for maintaining and extending the codebase.
📜 License
MIT © Daniel Hernández
