Alternatives β
Most tools here do part of what a developer machine needs. This collection's niche is the whole of it: packages, system config, repositories, and dotfiles, for one laptop or a fleet, from one repo. It straddles two categories, so it's compared against each on its own terms: dotfiles managers and provisioners.
TLDR
Only syncing files in $HOME? chezmoi is simpler, use it. Want packages, system state, and repositories managed alongside your dotfiles? That's this collection. The gap is scope, not capability: chezmoi's file engine and Ansible's template/copy under --diff do the same thing, they part ways on everything around the file.
Prefer a focused, one-on-one comparison? See Dotfiles Pro vs chezmoi, yadm, GNU Stow, Dotbot, bare git, Nix Home Manager, Salt, Puppet, Chef, MDM, devcontainers, or golden images.
- β supported
- π‘ partial, or via scripts/add-ons
- β not supported / out of scope
When to choose what β
- chezmoi, if files in
$HOMEare all you'll manage; add packages or system state and it falls back to run scripts, so now you maintain two tools. - Nix, when reproducibility and rollback matter more to you than the learning curve.
- Landscape or another MDM, once the company has to enforce state; personal setup is out of scope there.
- Devcontainers solve per-project toolchains, and they run with this collection rather than instead of it.
- Dotfiles Pro for an Ubuntu, macOS, or WSL machine (or twenty) that needs packages, system state, repositories, and dotfiles managed together, in tech the team already reads, adoptable role by role.
Dotfiles managers β
On the files themselves this holds its own against a dedicated dotfiles manager, and the difference starts at the Machine state rows, where file-focused tools fall back to setup.sh-style hooks and community plugins. The trade runs the other way further down the table: you install Ansible instead of one binary, you get Ubuntu, macOS, and WSL instead of every platform, and chezmoi's re-add has no equivalent here yet.
| Feature | Dotfiles Pro | chezmoi | yadm | Stow / Dotbot / bare git |
|---|---|---|---|---|
| Website | dotfiles.pro | chezmoi.io | yadm.io | Stow Β· Dotbot |
| Stars | n/a | |||
| Approach | ||||
| Mechanism | local Ansible run | binary + file source | git in $HOME | symlink farm |
| Primary scope | whole machine | home-dir files | home-dir files | home-dir files |
| Learning curve | low (YAML) | low | low | minimal |
| Configuration files | ||||
| Dotfile management | β | β | β | β |
| Per-machine templating | β | β | β | β |
| Key-level changes to software-written files | β | π‘ | β | β |
| Secrets integration | β | β | π‘ | β |
| Machine state | ||||
| Package installation | β | π‘ | π‘ | π‘ |
| System configuration (services, sysctl, wsl.conf) | β | π‘ | π‘ | π‘ |
| Repository cloning | β | π‘ | β | β |
| Operations | ||||
| Idempotent drift repair | β | β | β | π‘ |
| Targeted partial runs (tags) | β | β | π‘ | β |
| Minimal bootstrap (single binary/script) | β | β | β | β |
| Team & fleet | ||||
| Shared baseline + personal overrides | β | π‘ | β | β |
| Fleet-wide rollout without reimaging | β | β | β | β |
| Platforms | ||||
| Ubuntu | β | β | β | β |
| Other Linux distributions | β | β | β | β |
| WSL with Windows-side integration | β | β | β | β |
| Windows (native) | β | β | π‘ | π‘ |
| macOS | π‘ | β | β | β |
Only Dotfiles Pro also manages the machine itself, not just the files in $HOME.
Reading the table, key-level edits, secrets, machine state, platforms
- chezmoi keeps its own comparison table of dotfiles-only tools, with no rows for packages or system state, which is the scope gap. Its design FAQ draws the same line from the other side: past "a handful of files outside your target system⦠Puppet, Chef, Ansible, and Salt are much better suited", and the focus of chezmoi "will always be personal home directory management", their words for the scope-not-capability framing.
- Config files have three authors: you, the software's defaults, and the software at runtime (credential helpers, kubeconfig token refreshes). Commit the whole file and you pin stale defaults and fight runtime writes; key-level management owns only the keys you declare (chezmoi reaches this partially via
modify_scripts). The trade-off: whole-file repos give yougit diffover every change at the price of churn; key-level moves the diff to apply time (diff: true) and leaves churn to the software. - Key-level is the default, not a mandate. Files happiest committed whole (a hand-tuned
starship.toml, a long.bashrc,AGENTS.md) go through thedotfilesrole, which links, copies, or templates them into$HOME. The two approaches coexist on one path: the config roles write through a symlinked target (follow: true, andgit confignatively), so you can link a file with thedotfilesrole and still let a role drive its keys, picking settings-driven or verbatim per file. - Capturing existing config is where chezmoi's
re-addearns its keep, at the cost of re-importing the whole file (current defaults, churn, and any secrets); the planneddotpro capture(roadmap) extracts the reviewed, structured delta as vars, the key-level answer to "but chezmoi canre-addand you can't." Until it ships, that row goes to chezmoi. - One source directory or many is chezmoi's edge: it mandates a single source, sidestepping "which source does
addwrite to?", while Dotfiles Pro accepts multiple sources (collection / personal / company) for modularity and pays that ambiguity, most concretely in wherecapturelands. - yadm scores partial on secrets because it has built-in encryption but no password-manager integration.
- The partial marks in the Stow/Dotbot/bare-git machine-state column belong to Dotbot alone, its
shelldirective and apt/brew plugins reach packages; Stow and a bare repo do not. - Platforms are Ubuntu, macOS (the
macosrole, Homebrew), and WSL, and the β on other distributions is real: the install paths are guarded onansible_facts.os_familybeingDebianorDarwin, so on Fedora or Arch the tool roles skip rather than install. A Debian-family cousin passes the same guard, but only Ubuntu is tested in CI. Running on Windows without WSL is out of scope by design, yet a WSL machine's Windows half is managed: thewslrole bridges WSL tools into Windows and thewindowsrole applies winget apps, registry values, and virtual desktops over interop.
Provisioners β
Against machine-level tools the comparison flips: everyone installs packages. What sets Dotfiles Pro apart is the personal layer, gradual adoption, and pull-based developer ownership.
| Feature | Dotfiles Pro | Home Manager / NixOS | Salt / Puppet | Landscape / MDM | Devcontainers | Golden image |
|---|---|---|---|---|---|---|
| Website | dotfiles.pro | nixos.org | saltproject.io Β· puppet.com | ubuntu.com/landscape | containers.dev | autoinstall docs |
| Stars | n/a | n/a | n/a | |||
| Approach | ||||||
| Mechanism | local Ansible run | declarative build | masterless CM | agent + server | container image | one-shot installer |
| Primary scope | whole machine | OS + home | whole machine | fleet policy | per project | day-0 OS |
| Learning curve | low (YAML) | very high | medium | n/a (product) | low | low |
| Configuration files | ||||||
| Dotfile management | β | β | β | β | π‘ | π‘ |
| Per-machine templating | β | β | β | β | β | β |
| Key-level changes to software-written files | β | β | β | π‘ | β | β |
| Secrets integration | β | π‘ | β | π‘ | π‘ | β |
| Machine state | ||||||
| Package installation | β | β | β | β | π‘ | β |
| System configuration (services, sysctl, wsl.conf) | β | β | β | β | β | β |
| Repository cloning | β | π‘ | β | β | π‘ | π‘ |
| Operations | ||||||
| Idempotent drift repair | β | β | β | β | β | β |
| Reproducible builds / atomic rollback | β | β | β | β | π‘ | π‘ |
| Targeted partial runs (tags) | β | β | β | β | β | β |
| No agent or server required | β | β | π‘ | β | β | β |
| Team & fleet | ||||||
| Shared baseline + personal overrides | β | β | β | π‘ | π‘ | β |
| Fleet-wide rollout without reimaging | β | β | β | β | π‘ | β |
| Central enforcement & compliance | β | β | π‘ | β | β | β |
| Gradual adoption on existing machines | β | β | π‘ | π‘ | β | β |
| Platforms | ||||||
| Ubuntu | β | β | β | β | β | β |
| Other Linux distributions | β | β | β | π‘ | β | π‘ |
| WSL with Windows-side integration | β | β | β | β | π‘ | β |
| Windows (native) | β | β | β | β | β | π‘ |
| macOS | π‘ | β | β | π‘ | β | β |
Only Dotfiles Pro and Nix Home Manager genuinely belong to both categories.
Reading the table, devcontainers, golden images, MDM, Home Manager
- Devcontainers manage everything inside the container but leave the machine unmanaged, they compose with Dotfiles Pro, not compete.
- A golden image does real machine setup, but once: every partial mark means "at install time only."
- Landscape/MDM is the only push model, the company owns machine state, not the developer.
- Home Manager is the strictest file owner (whole files generated, often read-only): maximally declarative, but it fights software that writes its own config.
- Salt/Puppet can template files into
$HOMEbut have no personal dotfiles workflow, hence the partial mark.
One machine is one job β
"Use the right tool for each job" is good advice, but a developer machine is one job, not four. Packages, config, repositories, and shell state interlock: an alias is useless without its tool, a kubeconfig stanza needs its CLI. Split that across a dotfiles manager, an installer, and glue scripts, and the integration lands on an untested setup.sh.
This collection takes one engine built from the specialists: apt still installs, git still clones, Starship owns the prompt; roles declare them, not reimplement them. Compose at the real boundaries instead: project (devcontainers), enforcement (MDM), secrets (your password manager).
The wall isn't a missing feature, it's the first time a config has to do something instead of just be a file: take a value that differs per machine, live in a format with nowhere to hang a symlink directive (JSON), trigger the install of the tool it configures, or pull a secret. A symlink farm or a comment-parsing script has no answer to any of those, that's where managing files turns into provisioning a machine.
The four families
- Dotfiles-only managers (chezmoi, yadm, Stow, Dotbot, bare git) are simpler than Ansible, but they manage files, not machines. The gap fills with
setup.sh: chezmoi's own feature list bills run scripts as the way "to handle everything else", and projects like install.doctor bolt a full Ansible provisioner onto chezmoi, the scope gap, externalized. The imperative remainder roles fold in. - Masterless Salt, Puppet, and Chef are the same idea in another DSL, with a smaller laptop community.
ansible-pullis a cron variant; central-push products (AWX, MDM) flip ownership to the company. - Treating the OS as the artifact (NixOS, Home Manager, Fedora Silverblue) buys stronger guarantees, reproducible builds and atomic rollback, at the cost of the steepest learning curve and an all-or-nothing migration.
- Moving up the stack (devcontainers, Codespaces, Gitpod) standardizes the project, not the machine; those compose, since the laptop still needs git, Docker, SSH, identity, and shell setup.
Migrating in β
Coming in is incremental, by design. Adopt one role at a time; whatever you haven't migrated keeps working, because nothing here touches files it doesn't manage. Run your old tool and the playbook side by side until the playbook owns everything, then retire the old one. Whichever tool you're coming from, you gain what it couldn't reach: the packages, system config, and repositories around those files, managed in the same run.
From chezmoi β
Your source directory is the inventory of what to move. Structured config (git identity, aliases, tool settings) becomes role vars (the key-level model), so roles own those keys instead of whole files; per-machine .tmpl files become host_vars / group_vars plus the roles' Jinja; files chezmoi only copies verbatim map to a role's files/ or a ~/.profile.d/ drop-in.
There's no automatic importer yet (dotpro capture is on the roadmap), so it's a one-time, reviewable translation, done role by role.
From Stow or bare git β
Replace the symlink farm with roles that write real files: a Stow package becomes a role (or a ~/.profile.d/ snippet), and the symlinks become templated or copied files, so nothing dangles when the source moves. Packages you only ever stowed unchanged are easiest: drop them into a role's files/ and you're done.
Getting out β
Leaving costs nothing, by design. No agent, no daemon, no symlinks into a source repo; roles write ordinary files, install ordinary packages, clone ordinary repos. Stop running the playbook and the machine keeps working exactly as last applied; it just stops applying. Your configuration survives as portable YAML. (Stow's symlinks dangle, Home Manager's files live in /nix/store, MDM needs unenrollment, none of that here.)
One caveat: vars you remove leave their artifacts on disk until you clean them up by hand; automating that is a roadmap item.