CLI tool
yadm-dev/yadm avatar
yadm-dev/yadm

yadm: a Git wrapper for dotfiles, with alternates, templates and encryption

Yet Another Dotfiles Manager

6,432 stars200 forksPythonGPL-3.0

At a glance

What is it?
yadm keeps dotfiles in a Git repository without symlinking them into place. This article covers what it does, how the alternates and template mechanisms work, how to install it, and where it stops being the right tool.
Who is it for?
Adopt yadm if you already think in Git and want your dotfiles tracked in place, with per-OS alternates and optional GPG or OpenSSL encryption of private files, and you are willing to read the yadm.io documentation for the parts the README only links to. Do not adopt it if you want a declarative, package-manager-style setup where the tool owns the whole machine state, or if you need a GUI.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 169 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem yadm solves for people with more than one machine

Dotfiles are ordinary files that happen to live in your home directory. Versioning them with Git normally means either moving them into a repository and symlinking back, or writing a script that copies them around. Both approaches add a second source of truth: the symlink or the copy is what your shell actually reads, and the repository is what you edit. yadm removes that split by treating $HOME as the Git working tree. The README describes it as "a tool for managing dotfiles" that is "based on Git, with full range of Git's features", so the files stay where applications expect them and the repository tracks them in place.

The audience is narrow but real: engineers who run the same shell, editor and SSH configuration across a laptop, a work desktop and a server, and who want the history, branching and diffing of Git for those files. It is not a configuration management system. It does not install packages, does not describe a machine declaratively, and does not reconcile drift. It versions files you have already decided to keep.

How yadm works: a Git wrapper over your home directory

yadm is a single executable, listed in the repository as the top-level file yadm, alongside yadm.1 and yadm.md for the man page and its markdown source. The repository also contains a bootstrap script, a completion directory for shell completion, and a contrib directory. The primary language is Python, though the shipped artifact is the yadm script itself.

The core mechanism is a Git repository whose work tree is your home directory and whose Git directory lives elsewhere, under ~/.config/yadm. The README's quick tour shows the consequence: yadm init creates a new repository, yadm clone <url> clones an existing one, and yadm add plus yadm commit behave like their Git counterparts. Because the work tree is $HOME, a file added as .ssh/config is tracked at that path, and no symlink is created.

On top of that base, yadm adds three mechanisms the README names explicitly. Alternates let one logical file have several variants selected by conditions; the tour shows yadm add path/file.cfg##os.Linux and yadm add path/file.cfg##os.Darwin, where the suffix after ## describes when that variant applies. Templates let a file be generated from a template, and the project lists Jinja2 among its topics. Encryption covers private data using GnuPG, OpenSSL, transcrypt or git-crypt, chosen by the user. Hooks run before and after operations, and bootstrapping is customizable.

The README itself is short. It states that "complete features, usage, examples and installation instructions can be found on the yadm.io website" and links separate documentation pages for alternates, bootstrap, hooks, encryption and templates. That is a deliberate split, and it means the README alone is not enough to operate the advanced features.

Installing yadm and running a first real use

The README does not contain installation steps. It points to the yadm.io website for them, and the repository carries a bootstrap script at its top level plus packaging files such as yadm.spec. The badges in the README reference Homebrew, the Arch extra repository, and an openSUSE Build Service package, so those are the distribution channels the project advertises. If you install from one of those, the command is the package manager's own, and what you should see afterwards is yadm on your PATH responding to yadm --version.

Once installed, the first real use is either initializing a fresh repository or cloning an existing one. The README gives both forms:

bash
yadm init
yadm clone <url>

After yadm init, yadm has created its repository and you can start adding files. The README's tour shows the add and commit pair:

bash
yadm add <important file>
yadm commit

What you should see is a Git commit containing that file at its home-directory path, with no symlink introduced. From here the alternates mechanism is the first feature worth trying, because it is the one that differs most from plain Git. The README shows how to register two OS-specific variants of the same configuration file:

bash
yadm add path/file.cfg##os.Linux
yadm add path/file.cfg##os.Darwin

Both variants live in the repository, and yadm selects the matching one for the machine it runs on. The exact matching rules are on the alternates documentation page, not in the README, so read that page before relying on the suffix syntax for anything beyond the two examples shown.

Encrypting private files, and what the README leaves unsaid

The tour covers encryption in four lines. You write the paths you want protected into an encrypt file, then run yadm encrypt, and later yadm decrypt restores them:

bash
echo '.ssh/id_rsa' > ~/.config/yadm/encrypt
yadm encrypt
yadm decrypt

That is the whole documented workflow in the README. What it does not state is how the backend is selected, where the encrypted archive is stored, what happens when a file listed in the encrypt file is missing, or how decryption behaves on a machine that lacks the key. The README links to an encryption documentation page for the details, and the project lists GnuPG, OpenSSL, transcrypt and git-crypt as supported options. Those four have materially different trust models: git-crypt and transcrypt integrate with Git's filter mechanism and keep ciphertext in the repository history, while GnuPG and OpenSSL operate on a bundle. Choosing one is a decision the README does not help you make.

There is a second gap worth naming. The README does not document rollback, does not describe what happens if yadm encrypt is interrupted, and does not say whether the encrypted output is committed automatically. Treat the encryption feature as something to test on a throwaway key before you put a real private key behind it.

Where yadm is the wrong tool

yadm assumes your dotfiles are already the thing you want to manage. If your actual problem is that a new laptop takes a day to set up because of packages, language runtimes and system services, yadm does not address it. The bootstrap feature runs a customizable initialization, but the README describes it as initialization, not as package installation, and the project does not present itself as a provisioning tool.

The second limit is the working-tree model itself. Because $HOME is the Git work tree, a yadm add of a directory can sweep in files you did not intend to track, and yadm status will show untracked files across your entire home directory unless the repository's ignore rules are written carefully. Users coming from a symlink-based setup where the repository contains only curated files will notice the difference immediately.

The third limit is platform. The topics list dotfiles-linux and dotfiles-macos, and the tour's alternates example covers Linux and Darwin. Windows is not among the listed topics, and nothing in the README suggests native Windows support. If your fleet includes Windows machines, yadm is not the tool for them.

Finally, the project is a single script with documentation living on a separate site. The README is a pointer, not a manual. Anyone who needs a self-contained reference in the repository will be frustrated.

yadm vs chezmoi: two different answers to the same question

The most common comparison for yadm is chezmoi, and the difference is architectural rather than cosmetic. yadm exposes Git directly: the commands are yadm init, yadm clone, yadm add and yadm commit, and the mental model is a Git repository whose work tree happens to be your home directory. chezmoi takes the opposite approach. It keeps a source directory of its own, applies that source to your home directory, and gives you its own command set for inspecting and applying changes. You do not run Git commands against your home directory; you edit the source and let chezmoi write the targets.

That difference shows up in day-to-day work. With yadm, a file you edit in place is immediately visible as a modification, and yadm diff shows it, because the file and the tracked copy are the same file. With chezmoi, the source and the target are separate, and you reconcile them through chezmoi's own commands. yadm's alternates and templates are the project's answer to per-machine variation; chezmoi addresses the same problem through its source-state model and templating. Neither is strictly better, but the choice is really about whether you want Git to be the interface or a layer above it.

One practical consequence: because yadm is a Git wrapper, the full range of Git features is available, including branches, rebase and partial staging, as the README states. A tool that owns its own source directory has to reimplement or expose those separately.

Maintenance, licence and what to check before adopting

The repository is not archived, and the last push to the develop branch was on 2026-04-13. That is roughly five months before the date of this article, which is recent enough that the project cannot be described as abandoned, but the README offers no release cadence and no versioning policy, and no recent release information was available to check. The CHANGES file at the repository root is where the project records what moved between versions; read it for the version you intend to install rather than assuming the README reflects it.

Upgrade cost is low by construction. yadm is a single script, so upgrading means replacing that file or letting your package manager do it. There is no daemon, no background service and no database. The risk sits in the repository format and the configuration under ~/.config/yadm, which is where alternates, templates, hooks and the encrypt file live. A change to how those are interpreted would be the thing that breaks an existing setup, and the CHANGES file is the place that would say so.

The licence is GPL-3.0, per the LICENSE file and the repository metadata. For most users running yadm on their own machines this is unremarkable. If you intend to redistribute yadm inside a product, or to modify and ship it, the copyleft terms apply to the distributed work. That is a question for your legal team, not something this article can settle.

For contributors, the repository is set up for Python tooling: pyproject.toml configures pytest with a cache directory of /tmp, pylint limits such as max-line-length = 120, and black and isort both at line length 120. The Makefile defines make test, per-file test targets, make testhost for an ephemeral container, and make scripthost for producing a repeatable reproduction script. That is a more complete contributor setup than many single-script projects carry.

Editorial conclusion

Adopt yadm if you already think in Git and want your dotfiles tracked in place, with per-OS alternates and optional GPG or OpenSSL encryption of private files, and you are willing to read the yadm.io documentation for the parts the README only links to. Do not adopt it if you want a declarative, package-manager-style setup where the tool owns the whole machine state, or if you need a GUI. Before committing, verify three things on your own machine: that yadm is available from your distribution or Homebrew rather than only from the repository script, that your Git version satisfies what the installed yadm expects, and that your encryption backend of choice is present, since yadm encrypt with no configured backend cannot protect anything. The repository's last push was on 2026-04-13, so check the CHANGES file for what moved since the release you install.

Frequently asked questions

How do I install yadm?

The README does not include installation steps; it states that installation instructions are on the yadm.io website. The README's badges point to Homebrew, the Arch extra repository and an openSUSE Build Service package, and the repository also contains a bootstrap script.

Does yadm create symlinks for my dotfiles?

No. yadm uses your home directory as the Git working tree, so tracked files stay at their normal paths. The README's quick tour shows yadm add and yadm commit operating on files directly, with no linking step.

How does yadm handle different settings on Linux and macOS?

Through alternates. The README's tour shows yadm add path/file.cfg##os.Linux and yadm add path/file.cfg##os.Darwin, keeping both variants in the repository and selecting the matching one. The full matching rules are on the alternates documentation page rather than in the README.

What encryption options does yadm support for private files?

The README lists GnuPG, OpenSSL, transcrypt and git-crypt. The documented workflow is to write paths into ~/.config/yadm/encrypt, run yadm encrypt, and later run yadm decrypt. The README does not explain how the backend is selected.

Does yadm work on Windows?

Nothing in the README or the repository topics indicates native Windows support. The listed topics cover dotfiles-linux and dotfiles-macos, and the alternates example in the README uses Linux and Darwin.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. Project website
  4. README
  5. yadm-dev/yadm on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/yadm-dev-yadm.svg)](https://hysenlabs.com/projects/yadm-dev-yadm)