Chezmoi vs yadm for Dotfiles: When Two Homelab Boxes Disagree on PATH
Tobias Keller
August 25, 2026
The first time two homelab boxes share a dotfiles repo, PATH is where the friendship ends. The Mac has Homebrew in /opt/homebrew/bin. The Debian box has ~/.local/bin and a mise shim directory you forgot existed. The Pi has neither, and it still sources the same .zshrc because you were proud of a single repo.
yadm will let you pretend this is still just Git. Chezmoi will make you admit it is a template problem. Both are right on a Tuesday. Only one stays honest after the third machine.
yadm is Git with a costume
yadm is a thin, disciplined wrapper. Your home directory is a work tree. You yadm add, yadm commit, yadm push. Anyone who already lives in Git can read the history without learning a new object model. Alternate files — .zshrc##os.Darwin, .zshrc##hostname.nas — are the official way to split worlds. Encryption is a bolt-on you choose: yadm encrypt, git-crypt, transcrypt. The tool does not want to be your password manager.
That is a strength on a pair of similar Linux boxes. It is a pile of alternate files when PATH differs in five places and the prompt differs in two and SSH config differs in one. You start with one ##os file. You add a hostname file. You then need “Debian but not the Pi.” Alternate files are not a programming language. They are a naming scheme. Naming schemes rot.
I ran yadm for three years on a laptop and a VPS that were both Ubuntu-ish. It was fine. The day I added the Mac Mini that builds iOS Shortcuts experiments, I had four PATH blocks and a comment that said “do not source this on the Pi.” The Pi sourced it anyway because I copied the wrong alternate.

Chezmoi is a compiler for your home directory
Chezmoi keeps a source state that is not your live home directory. You edit the source, then chezmoi apply. Templates use Go’s text/template. Hostname, OS, architecture, and arbitrary data from a config file are first-class. {{ if eq .chezmoi.os "darwin" }} is ugly and explicit. I can read it six months later. I cannot say the same for a file named .zprofile##os.Darwin##hostname.studio that I forgot to keep in sync with .zprofile##os.Darwin.
PATH becomes a template function, not a social contract. One .zshrc template prepends Homebrew only on Darwin, mise shims if the directory exists, and ~/.local/bin if that exists. The Pi gets a short PATH. The NAS gets the same file and skips the GUI junk. There is one source of truth. Apply is a dry-runnable compile.
The cost is conceptual. New people will try to edit ~/.zshrc and lose the change on the next apply. You have to teach “edit the source.” yadm lets you edit the file in place because the file is the git work tree. Chezmoi fights that instinct on purpose. I like the fight now. I hated it the first week.
Secrets, and the file you should not have committed
Dotfiles repos become secret graveyards. API tokens in .zshrc, a .netrc, an old ngrok.yml. yadm encrypt is a list of files and a dance at clone time. Chezmoi talks to 1Password, Bitwarden, pass, age, and a few others, and can template a secret into a file that never sits in Git in the clear.
If your threat model is “GitHub private repo and a household,” yadm encrypt is enough. If your threat model is “I will paste a token once and forget,” Chezmoi’s password-manager hooks are the feature that pays for the extra binary. I moved a Tailscale ACL helper token out of a yadm-encrypted file and into a 1Password reference. The repo got boring. Boring is the goal.
Neither tool fixes the secret that is already in history. Rotate it. Then pick a tool that makes the next one harder to commit.
PATH disagreements that are really machine classes
The useful model is not “one file per host.” It is classes: workstation, server, appliance. Workstations get editors and completion. Servers get tmux and a tight PATH. Appliances get almost nothing because you should not be interactive on them.
Chezmoi data files make classes cheap. A .chezmoi.yaml on the NAS says class: appliance. The template branches on class, then on OS. yadm can fake this with a bootstrap script that writes a local file. You will write that script. You will forget to run it on the next box. Chezmoi runs the logic every apply.
Concrete PATH bugs I have hit:
- Homebrew on Apple Silicon versus Intel leftovers after a migration. The template checks the directory, not the marketing name.
- mise versus asdf shims both on PATH, so the NAS ran a Node that the laptop had specified in a different
.tool-versions. Class “server” no longer adds shims. - root on a Proxmox box sourcing a user
.profilethat prepended~/binthat did not exist, which is harmless, until a cron used bash -l and warned into mail. Appliance class: no user PATH games.

Bootstrap and the chicken-and-egg
yadm clone is a git clone with extra steps. If you have Git and a key, you are in. Chezmoi install is a one-liner that fetches a binary, then init from a repo. On a fresh Debian box with nothing, I still need curl or wget. On a locked-down NAS, I copy the chezmoi binary in by hand like it is the 1990s. That has happened twice. yadm would have needed Git, which the NAS also lacked. The binary was easier to scp than a Git install.
Idempotency matters more than poetry. chezmoi apply is meant to be repeated. yadm pull plus a hook can be repeated if you wrote the hook. Chezmoi wins when you treat apply as the thing you run after every bootstrapping change. yadm wins when you treat the machine as a git working copy and you live in commits.
When I still use yadm
A single workstation, maybe a similar VPS, and a desire to stay in Git porcelain: yadm. Teaching a friend who already understands branches and not templates: yadm. A repo that is mostly .config files that are identical everywhere: yadm. The PATH problem has not shown up yet because the machines are clones.
The moment you have a Mac and a Linux box and a Pi, I stop recommending yadm as the long-term home. You can keep it. You will invent Chezmoi inside a shell script.
When Chezmoi is extra
If you refuse templates and you like alternate files, Chezmoi is a heavier git. If you need Windows and you already have Chezmoi, it is one of the few dotfile tools that is not a bash joke. If you need Windows and you are a yadm person, you are about to learn MSYS or WSL, which is a different article.
Chezmoi also wants you to adopt its source layout. That is a migration afternoon from yadm. I migrated by leaving yadm in place, copying files into Chezmoi source, applying to a third test account, then cutting over. Do not apply to your only interactive user on the first try. PATH mistakes log you into a shell that cannot find git.
Diffs, drift, and the file you edited in production
Homelab boxes get “just this once” edits. A PATH line for a one-off compiler. A umask change after a backup scare. yadm status will show it if you remember to look. Chezmoi git-status and diff show destination versus source in a way that is harder to ignore, because apply is a habit. I run chezmoi diff after any SSH session that lasted more than twenty minutes. If I changed a file in place, I either discard it or add it to source. yadm people do the same with yadm diff. The difference is cultural: Chezmoi users expect apply to overwrite. yadm users expect commit to capture. Drift is worse when you mix the cultures on one machine.
Hooks exist in both. I keep a hook that asserts command -v git after apply. It has saved me from a template that dropped Homebrew on a Mac because I typed darwin wrong. A broken PATH is a lockout if your editor and git live in that PATH. Test apply in a container or a spare user. It sounds precious. It is cheaper than a console cable.
The rule that ended the argument
If PATH, prompts, or SSH differ by machine class, use Chezmoi and write the class down. If the machines are the same role and you want Git and nothing else, use yadm. Do not share one untemplated .zshrc across a laptop and an appliance and then ask why mise is “broken” on the NAS.
Two boxes that disagree on PATH are not a Git problem. They are two programs that happen to share a filename. Chezmoi treats that as data. yadm will let you hide it in a filename suffix until the suffixes are the data model. I still love yadm. I apply Chezmoi on the network that has more than one personality.