Package management
Manifests declare ownership; installers reconcile them idempotently. Find the owner before adding a tool, then run its installer or the normal bootstrap.
The layers
Section titled “The layers”| Owner | Manifest | Installer | Use for |
|---|---|---|---|
| Homebrew | packages/Brewfile | install/homebrew.sh | system tools, libraries, casks |
| Cargo | packages/cargo.txt | install/rust.sh | Rust CLIs with suitable releases |
| uv | packages/python.txt, pip*.txt | install/python.sh | Python libraries and isolated CLIs |
| npm/nvm | packages/npm*.txt | install/node.sh | Node CLIs |
| Go | packages/go.txt | install/go.sh | Go CLIs |
| agents/editors | package lists plus home/dot_* | matching installer | plugins, 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.
Adding a package — priority order
Section titled “Adding a package — priority order”- Prefer the language-native list when it owns the tool: Cargo, npm, uv, or Go.
- Use Homebrew for system dependencies, GUI apps, SDKs, and tools without a suitable native path.
- Add a focused installer only when neither list expresses its lifecycle.
Before editing, search all ownership sources and identify a probe:
cd ~/dotfilesrg -n '(^|/)tool-name([ @#]|$)' packages install home# edit the selected manifest, then run its installerbash install/rust.sh # example for packages/cargo.txtcommand -v tool-name && tool-name --versionThe source manifests are the current inventory. Comments in each list carry platform and exception rules.
1. cargo — Rust crates
Section titled “1. cargo — Rust crates”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:
bash ~/dotfiles/install/rust.shExpect 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.
2. npm — npm-specific tools
Section titled “2. npm — npm-specific tools”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.
3. uv — Python libraries and CLI tools
Section titled “3. uv — Python libraries and CLI tools”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:
uv init example && cd exampleuv add numpyuv 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:
bash -c 'source ~/dotfiles/install/_lib.sh; printf "%s\n" "$UV_CACHE_DIR"'df-google-mcp --check-runtimeExpect 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:
bash install/audit-versions.sh | jq '.[] | select(.tool == "quarto")'bash install/audit-versions.sh --strictExpect 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.
5. VS Code / Cursor extensions
Section titled “5. VS Code / Cursor extensions”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.
6. Custom install script
Section titled “6. Custom install script”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.
Local AI tools
Section titled “Local AI tools”| Tool | Owner | Operational boundary |
|---|---|---|
| Ollama | Brewfile | installation does not start or query its server |
| mlx-lm / mlx-openai-server | pip-full.txt | Apple Silicon-oriented optional workflow |
| OpenCode | npm.txt (opencode-ai) plus install/opencode.sh | npm owns the binary; the installer reconciles configuration |
| local-model tooling | install/local-llm.sh | validate 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.
Research mathematics
Section titled “Research mathematics”| Tool family | Owner | Project proof/result boundary |
|---|---|---|
| Lean | install/lean.sh / elan | project lean-toolchain, lake build |
| TeX and Quarto | installer plus Brewfile/TinyTeX | source and render command |
| Julia | Brewfile plus install/julia.sh | project Pkg environment |
| solvers and research CLIs | Brewfile, Cargo, or uv lists | project lockfiles and evidence |
Read research tooling for concrete project commands and math workflows for proof claims.
Don’t duplicate across layers
Section titled “Don’t duplicate across layers”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.
Why cargo over Homebrew for Rust tools
Section titled “Why cargo over Homebrew for Rust tools”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.
Why Homebrew for Linux
Section titled “Why Homebrew for Linux”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.
Compiler toolchains
Section titled “Compiler toolchains”Default: LLVM (Homebrew clang)
Section titled “Default: LLVM (Homebrew clang)”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:
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 buildSwitching toolchains
Section titled “Switching toolchains”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.
Disabling the toolchain
Section titled “Disabling the toolchain”Clear the profile default for a command that needs its own compiler selection:
env -u CMAKE_TOOLCHAIN_FILE cmake -S . -B build-systemOr 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.
Compiler caching (sccache)
Section titled “Compiler caching (sccache)”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.
openssh from Homebrew
Section titled “openssh from Homebrew”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.
Source files
Section titled “Source files”The authoritative compiler inputs are install/cmake.sh,
the shared compiler-cache.sh,
install/_lib.sh, and the files in
install/cmake/toolchains/.
Updating all packages
Section titled “Updating all packages”~/dotfiles/bootstrap.sh update~/dotfiles/bootstrap.sh upgrade # accepts managed upgradesKeep the degradation summary and use updates when a selected tool fails to reconcile.