stout-install
Fast, reliable package installation for Homebrew-compatible packages — bottles, source builds, symlinks, and INSTALL_RECEIPT generation.
Keywords: package-installation, homebrew, bottle, source-build, symlink, cellar, rust, package-manager, formula
Why stout-install?
Installing packages means more than just downloading a file. You need to extract archives, verify integrity, handle dependencies, create symlinks, and record what was installed so it can be updated or removed later. stout-install handles all of this with a clean async API, producing Homebrew-compatible installations that work alongside existing brew setups.
This crate powers the stout install, stout uninstall, and stout upgrade commands, but it's designed as a reusable library for any Rust project that needs to install pre-built binaries or build from source.
Features
- Bottle Installation — Extract and install pre-built binaries (.tar.gz, .tar.zst)
- Source Builds — Build from source with configurable parallelism and compiler selection
- Archive Extraction — Handle tar.gz, tar.zst, zip, and other archive formats
- Symlink Management — Create and remove symlinks in the installation prefix
- Homebrew Compatibility — Generate
INSTALL_RECEIPT.jsonfiles that brew understands - Dependency Installation — Automatically install required dependencies first
- Atomic Operations — Install to a staging area, then atomically move into place
- Rollback Support — Restore previous versions on failed upgrades
- Prefix Isolation — Install to custom prefixes for multi-environment setups
Installation
Or in your Cargo.toml:
[]
= "0.2"
Quick Start
use ;
use Index;
// Open the index and create an installer
let index = open_default?;
let config = InstallConfig ;
let installer = new?;
// Install a package (resolves dependencies, downloads bottle, extracts, links)
let result = installer.install.await?;
println!;
API Overview
Creating an Installer
use ;
// Default configuration (uses system Homebrew paths)
let config = default;
let installer = new?;
// Custom prefix (isolated environment)
let config = InstallConfig ;
let installer = new?;
Installing Packages
use InstallOptions;
// Basic install (uses bottle if available, falls back to source)
let result = installer.install.await?;
// Force source build
let options = InstallOptions ;
let result = installer.install_with_options.await?;
// Install specific version
let options = InstallOptions ;
let result = installer.install_with_options.await?;
// Install without dependencies (use with caution)
let options = InstallOptions ;
let result = installer.install_with_options.await?;
Batch Installation
// Install multiple packages, resolving dependencies across the entire set
let results = installer.install_batch.await?;
for result in results
Uninstalling Packages
// Remove a package and its symlinks
installer.uninstall.await?;
// Uninstall but keep the downloaded archive (for quick reinstall)
installer.uninstall_keep_cache.await?;
// Uninstall and remove unused dependencies
installer.uninstall_with_autoremove.await?;
Upgrading Packages
// Upgrade a single package to the latest version
let result = installer.upgrade.await?;
println!;
// Upgrade all outdated packages
let results = installer.upgrade_all.await?;
for result in results
// Upgrade with rollback on failure
let result = installer.upgrade_with_rollback.await?;
Symlink Management
// Link an installed package to the prefix
installer.link.await?;
// Unlink (remove symlinks but keep installed)
installer.unlink.await?;
// Relink (useful after prefix changes)
installer.relink.await?;
// Check linking status
let is_linked = installer.is_linked?;
Pinning and Version Management
// Pin a package to prevent upgrades
installer.pin.await?;
// Unpin to allow upgrades again
installer.unpin.await?;
// Check if pinned
let is_pinned = installer.is_pinned?;
// Switch between installed versions
installer.switch.await?;
Installation Inspection
// Get info about an installed package
let info = installer.installed_info?;
println!;
println!;
println!;
println!;
// List all installed packages
let installed = installer.list_installed?;
for pkg in installed
// Check if a package is installed
let is_installed = installer.is_installed?;
// Find which package owns a file
let owner = installer.owner_of?;
Receipt Generation
Every installation generates a Homebrew-compatible INSTALL_RECEIPT.json:
Performance
Installation performance is dominated by I/O:
| Operation | Typical Time | Notes |
|---|---|---|
| Small bottle (jq, ~1MB) | 100-300ms | Download + extract + link |
| Medium bottle (node, ~50MB) | 2-5s | Mostly extraction time |
| Large bottle (rust, ~200MB) | 10-20s | Extraction of many files |
| Source build (small) | 30s-2min | Depends on build system |
| Source build (large) | 5-30min | Parallel compilation helps |
Atomic staging means installations are all-or-nothing — you'll never have a partially-installed package.
Integration with the Stout Ecosystem
stout-install is the execution engine of stout's package management:
- stout-index provides package metadata (URLs, checksums, dependencies)
- stout-resolve computes the installation order
- stout-fetch downloads bottles and source tarballs
- stout-state tracks what's installed, pinned, and linked
- stout-cask extends installation to macOS applications
You can use stout-install standalone if you have your own source of package metadata, or combine it with the full stout stack for a complete Homebrew-compatible solution.
License
MIT License — see the repository root for details.