Skip to content

Package management

Manifests declare ownership; installers reconcile them idempotently. Find the owner before adding a tool, then run its installer or the normal bootstrap.

OwnerManifestInstallerUse for
Homebrewpackages/Brewfileinstall/homebrew.shsystem tools, libraries, casks
Cargopackages/cargo.txtinstall/rust.shRust CLIs with suitable releases
uvpackages/python.txt, pip*.txtinstall/python.shPython libraries and isolated CLIs
npm/nvmpackages/npm*.txtinstall/node.shNode CLIs
Gopackages/go.txtinstall/go.shGo CLIs
agents/editorspackage lists plus home/dot_*matching installerplugins, skills, MCP, extensions, config

Use one owner per executable. A duplicate Homebrew/npm, pip/uv, or Cargo/tap install produces ambiguous upgrades and PATH behavior. See package ownership for the contract.

  1. Prefer the language-native list when it owns the tool: Cargo, npm, uv, or Go.
  2. Use Homebrew for system dependencies, GUI apps, SDKs, and tools without a suitable native path.
  3. Add a focused installer only when neither list expresses its lifecycle.

Before editing, search all ownership sources and identify a probe:

Terminal window
cd ~/dotfiles
rg -n '(^|/)tool-name([ @#]|$)' packages install home
# edit the selected manifest, then run its installer
bash install/rust.sh # example for packages/cargo.txt
command -v tool-name && tool-name --version

The source manifests are the current inventory. Comments in each list carry platform and exception rules.

Add a crate name to packages/cargo.txt. install/rust.sh uses cargo-binstall when a compatible release binary exists, otherwise compiles from source. On Linux it prefers musl candidates to avoid a too-new glibc; a failing binary is retried from a compatible source path. A macOS source build needs a normal terminal because Sequoia’s linker provenance rules can reject sandboxed builds.

Source installs use the installed Homebrew openssl@3 keg through a command-local OPENSSL_DIR; older locked openssl-sys dependencies reject OpenSSL 4. packages/Brewfile keeps OpenSSL 3 installed alongside the global version. Explicit OPENSSL_DIR, OPENSSL_LIB_DIR, or OPENSSL_INCLUDE_DIR settings (including target-prefixed variants) take precedence. Without that keg, Cargo keeps its normal discovery behavior. This applies to installer source builds; ordinary project builds keep their own environment. On Linux, the installer also adds that keg’s library directory to the executable’s runtime search path so it loads the same OpenSSL it built against; existing Rust compiler flags are preserved.

After installing the Brewfile dependencies, retry with:

Terminal window
bash ~/dotfiles/install/rust.sh

Expect source fallbacks to report the OpenSSL 3 path and the final tool count to show zero failures. See the OpenSSL mismatch recovery and upstream rust-openssl build configuration.

Add global CLIs to packages/npm.txt. nvm owns Node and its global prefix under $NVM_DIR; do not set npm prefix or globalconfig in ~/.npmrc. packages/npm-allow-scripts.txt is the reviewed lifecycle-script allowlist. Codex’s package is npm-owned while install/codex.sh owns configuration and its health check.

packages/python.txt feeds the managed interactive python; pip.txt and pip-full.txt declare isolated CLI environments. Put project dependencies in the project pyproject.toml and lockfile instead:

Terminal window
uv init example && cd example
uv add numpy
uv run python -c 'import numpy; print(numpy.__version__)'

Installers and managed Google/Gemini launchers default UV_CACHE_DIR to $DF_STATE_ROOT/uv/cache when host-local state is configured, otherwise to $LOCAL_PLAT/uv/cache. An explicit UV_CACHE_DIR takes precedence. Installed Python and CLI environments remain under $LOCAL_PLAT; the cache location keeps script-environment locks off a shared NFS tool root.

With host-local state configured, check the resolved path and prepare the locked transport without authentication:

Terminal window
bash -c 'source ~/dotfiles/install/_lib.sh; printf "%s\n" "$UV_CACHE_DIR"'
df-google-mcp --check-runtime

Expect the configured local state path followed by Google MCP runtime ready. The first preparation downloads dependencies. Existing processes retain their old cache; this does not relocate installed tool environments or repair a broken NFS lock service. See NFS cache waits and upstream uv cache configuration.

4. Homebrew — non-language-specific tools and C libraries

Section titled “4. Homebrew — non-language-specific tools and C libraries”

Use packages/Brewfile for formulae, casks, SDKs, and shared libraries. Bootstrap owns brew bundle; use the manifest rather than brew install for a durable addition. Linux uses its rootless managed prefix, while macOS uses the standard Homebrew prefix.

Bundle runs with --verbose so package build and download output appears as it runs. Its Using ... inventory can precede a batched install; those lines do not establish completion. See silent Bundle output.

On Linux, bootstrap checks that Homebrew’s sha256sum computes the known digest of abc before and after Bundle. A broken installed Coreutils is rebuilt from the managed formula before download-verifying installers such as uv run. The formula patch declares its OpenSSL dependency explicitly; see checksum loader failures for recovery commands, limits, and patch switches.

Quarto is owned by the unpinned macOS cask and by a checksum-verified release archive on Linux. The version audit accepts macOS releases at or above 1.10.18; Linux must match DF_QUARTO_VERSION (default 1.10.18) exactly. With the managed toolchains installed, inspect the policy and verify all required versions:

Terminal window
bash install/audit-versions.sh | jq '.[] | select(.tool == "quarto")'
bash install/audit-versions.sh --strict

Expect Quarto’s policy to be minimum on macOS or exact on Linux, and strict mode to exit zero only when all toolchains pass. DF_QUARTO_VERSION selects only the Linux archive; it does not pin the macOS cask. See the Quarto install guide and authoritative installer, audit, and Brewfile.

Add marketplace identifiers to packages/vscode-extensions.txt or packages/cursor-extensions.txt, then run the matching installer. Settings live under home/dot_config/; extensions and settings are separate state. See shell, terminal, and editor workflow.

When a tool needs its own lifecycle, add an idempotent install/<name>.sh, source _lib.sh, wire a documented bootstrap gate, and add a meaningful probe. Changing managed behavior also requires the feature entry described in documentation guidance.

ToolOwnerOperational boundary
OllamaBrewfileinstallation does not start or query its server
mlx-lm / mlx-openai-serverpip-full.txtApple Silicon-oriented optional workflow
OpenCodenpm.txt (opencode-ai) plus install/opencode.shnpm owns the binary; the installer reconciles configuration
local-model toolinginstall/local-llm.shvalidate model, license, and task separately

Use AI workbench for an end-to-end workflow; executable checks do not establish model quality or a running service.

Tool familyOwnerProject proof/result boundary
Leaninstall/lean.sh / elanproject lean-toolchain, lake build
TeX and Quartoinstaller plus Brewfile/TinyTeXsource and render command
JuliaBrewfile plus install/julia.shproject Pkg environment
solvers and research CLIsBrewfile, Cargo, or uv listsproject lockfiles and evidence

Read research tooling for concrete project commands and math workflows for proof claims.

Search before adding, retain one owner, and remove a duplicate only through its own manager after checking what currently resolves on PATH. This repository does not use a universal package lock because each manager has different platform and binary semantics.

Cargo-binstall can use upstream release artifacts and falls back to source, while keeping Rust CLIs in the Rust manifest. Prefer Homebrew where the package is a library, system dependency, or macOS application rather than a standalone Rust CLI.

The managed Linux prefix provides current formulae without sudo and keeps them inside the same runtime-root contract as other compiled state. It is not a replacement for a project’s pinned dependencies.

Managed CMake toolchain files are copied to the installer runtime root; in a managed login shell that is $_LOCAL_PLAT/cmake/toolchains. The login profile selects llvm-22.cmake on macOS when Homebrew LLVM is available; Linux prefers gcc-13.cmake. Each falls back to the other if its preferred compiler is unavailable. An existing CMAKE_TOOLCHAIN_FILE takes precedence. To choose LLVM explicitly:

Terminal window
ls "${_LOCAL_PLAT:?open a managed login shell first}/cmake/toolchains"
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="$_LOCAL_PLAT/cmake/toolchains/llvm-22.cmake"
cmake --build build

Set CMAKE_TOOLCHAIN_FILE per project or configure preset; do not rely on a global default for a reproducible project build. The profile defaults to gcc-13.cmake on Linux where available and llvm-22.cmake on macOS where available; an already-set CMAKE_TOOLCHAIN_FILE wins.

Clear the profile default for a command that needs its own compiler selection:

Terminal window
env -u CMAKE_TOOLCHAIN_FILE cmake -S . -B build-system

Or set the project file explicitly. Confirm cmake -LAH reports the expected compiler.

CUDA is overlay-specific. Enable the overlay and select its documented CMake toolchain only on a host with the required NVIDIA driver and toolkit.

The managed Brewfile installs sccache through rootless Homebrew. A shared profile/install helper and the GCC/LLVM toolchains select it for supported CMake languages and as the default Rust wrapper. A native configuration gives shell and non-login builds a 250 GiB local cache limit. Caches are disposable local derived state; a cache hit does not validate compiler correctness.

Read compiler caching for the configuration, runnable overrides, CMake reconfiguration for existing trees, NFS-local storage check, limits, and upstream references. The old ccache package and its existing on-disk cache are not removed automatically.

See build performance for per-language defaults, incremental-build choices, native cache boundaries, and measured tuning results.

Use the managed OpenSSH only when its path precedes the system client, then check ssh -V and ssh -G host. See shell workflow for the managed SSH policy.

The authoritative compiler inputs are install/cmake.sh, the shared compiler-cache.sh, install/_lib.sh, and the files in install/cmake/toolchains/.

Terminal window
~/dotfiles/bootstrap.sh update
~/dotfiles/bootstrap.sh upgrade # accepts managed upgrades

Keep the degradation summary and use updates when a selected tool fails to reconcile.