Packages, not just
dotfiles.
Your shell config is only half the story — the other half is the CLI tools it expects to find. dotstate tracks packages per profile and installs what's missing in one command.
How it works
A package is a tuple: a name, a manager (how to install it), and optionally a
binary name (how to detect it, if different from the package name — e.g. Homebrew's ripgrep ships rg).
Each profile keeps its own list. Inheritance applies: a child profile automatically
includes its parent's packages.
Supported managers
Homebrew
macOS and Linux. brew must be on the $PATH.
Cargo
Rust packages from crates.io. cargo install <pkg>.
npm
Global npm packages. npm install -g <pkg>.
pip
Python packages. pip install --user <pkg>.
apt · dnf · pacman
System packages on common Linux distributions.
Custom
Any shell command. Use for tools with bespoke installers (mise, rustup, nvm, …).
Adding a package
From the TUI, open Packages, choose a manager, and type the name. From the command line:
# Interactive — prompts for manager and binary name:
$ dotstate packages add
# Or inline:
$ dotstate packages add -n ripgrep -m brew -b rg
$ dotstate packages add -n eza -m cargo
$ dotstate packages add -n prettier -m npm Checking what's missing
On a fresh machine, check everything the current profile expects:
$ dotstate packages check
→ brew · ripgrep (rg) ✓ installed
→ cargo · eza ✗ missing
→ npm · prettier ✓ installed
→ 1 package missing. Installing in bulk
install only touches packages that are actually missing — it's safe to run repeatedly.
$ dotstate packages install
→ cargo install eza
→ done · 1 package installed. Custom packages
When a tool doesn't fit a standard manager, register a custom package with its own install command and a detection command:
$ dotstate packages add \
-n mise -m custom \
--install-command "curl https://mise.run | sh" \
--existence-check "command -v mise" The existence check is anything that exits 0 when the tool is present. The install command is run in a subshell — not interpreted by your login shell — so there's no shell-injection surface.
Security note. dotstate never runs install commands automatically. You explicitly opt in by running
dotstate packages install. Before install, the exact commands that will run are printed, and you can cancel.
Next
See the CLI reference for all package commands, or profiles for how per-profile package lists inherit.