CLI tool
anishathalye/dotbot avatar
anishathalye/dotbot

Dotbot: a dotfiles bootstrapper that links, creates and cleans

A tool that bootstraps your dotfiles ⚡️

8,012 stars319 forksPythonMIT

At a glance

What is it?
Dotbot is a small Python tool that reads a YAML or JSON config and turns it into symlinks, directories and shell commands. It is for people who already keep their dotfiles in Git and want the install step to be one command.
Who is it for?
Adopt Dotbot if your dotfiles already live in Git and you want the install step to be a single idempotent command with a readable YAML file. Skip it if you need templating, per-host variable interpolation or secret decryption out of the box, because none of that is in the core directives.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 81 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

What Dotbot actually does, and what it refuses to do

Dotbot is a [Dot]files [bo]o[t]strapper. The README states the design goal plainly: it does less than you think, because version control systems do more than you think. That sentence is the whole product thesis. Dotbot does not store your dotfiles, does not version them, and does not sync them between machines. Git does that. Dotbot only takes a config file and performs the operations listed in it.

The intended user is someone who already has a dotfiles repository and is tired of a hand-written install shell script that breaks halfway through. Dotbot replaces that script with a declarative file. The README describes it as lightweight and self-contained, with no external dependencies and no installation required, and notes it can act as a drop-in replacement for another dotfiles tool. It is VCS-agnostic, so Mercurial users are not excluded.

The refusal is deliberate and has a cost. Anything beyond linking, creating, cleaning and running shell commands has to come from a plugin, and the README lists third-party plugins for secrets management, package management and application configuration. If your dotfiles need per-machine templating, that is not a core directive.

How the config file drives the installer

Configuration is YAML or JSON, conventionally named install.conf.yaml, with JSON files named install.conf.json. The README notes JSON is a subset of YAML, so both go through the same parser. The file is a list of directives, and each directive is a mapping from a directive name to its arguments.

The core directives are link, create, shell, clean and defaults. Link maps a target path to a source path, create makes directories, shell runs commands, clean removes broken symbolic links from directories you name, and defaults supplies options that apply to later directives of a given type. The full example in the README sets relink under defaults for link, cleans the home directory, links three paths, creates two directories, and runs one shell command with a description string.

Execution is sequential over that list. Idempotence is a stated expectation rather than an enforced property: the README says bootstrap configurations should ideally be idempotent, meaning the installer can run multiple times without causing problems. Dotbot does not detect whether your shell commands are safe to repeat. That is on you.

Installing Dotbot and running a first install

There are two supported routes. The first bundles Dotbot inside your dotfiles repository as a submodule or subrepo. Start in your dotfiles directory, initialize the repository if needed, add Dotbot as a submodule, tell Git to ignore dirty commits in it, and copy the shim install script into place.

bash
cd ~/.dotfiles # replace with the path to your dotfiles
git init # initialize repository if needed
git submodule add https://github.com/anishathalye/dotbot
git config -f .gitmodules submodule.dotbot.ignore dirty # ignore dirty commits in the submodule
cp dotbot/tools/git-submodule/install .

The install script is a shim that checks out the appropriate version of Dotbot and calls the full installer. By default it expects the config at install.conf.yaml and the submodule at dotbot. Both are editable variables inside the script. Mercurial users follow the equivalent sequence with .hgsub and tools/hg-subrepo/install, and PowerShell users copy install.ps1 instead.

The second route installs Dotbot as a standalone command-line program. The README shows uv tool install dotbot, and notes that some systems package it natively, giving brew install dotbot as an example. Once it is on your PATH, you invoke it with dotbot -c <path to configuration file>.

A minimal config to try first looks like the README's example. Write it to install.conf.yaml, then run the install script and check that the symlinks appear in your home directory.

yaml
- defaults:
    link:
      relink: true

- clean: ['~']

- link:
    ~/.tmux.conf: tmux.conf
    ~/.vim: vim
    ~/.vimrc: vimrc

On a new machine the README's sequence is git clone of your dotfiles repository into ~/.dotfiles, cd into it, then ./install. To update an existing installation, git pull and ./install again.

Upgrading Dotbot when it is pinned as a submodule

Bundling Dotbot as a submodule or subrepo locks it to the current version, which is the point: your dotfiles keep working even if upstream changes. Upgrading is still possible. With a submodule the README gives git submodule update --remote dotbot, substituting the real submodule path. With a subrepo, run git fetch && git checkout origin/master inside the Dotbot directory.

The README adds a warning that matters in practice: commit your changes before running ./install, otherwise the old version of Dotbot will be checked out by the install script. The shim re-checks out the pinned revision, so uncommitted submodule movement is discarded. That is a real failure mode, and it is easy to hit when you upgrade and immediately re-run the installer.

If you install from PyPI or a system package manager instead, the shim is not involved and upgrades follow that tool's own commands. The trade-off is that your dotfiles no longer carry their own pinned copy, so a machine with an older packaged version behaves differently from a machine with a newer one. The README does not document a rollback procedure beyond checking out a different revision in the submodule directory.

Where Dotbot is the wrong tool

Dotbot assumes your dotfiles are already in version control and that the installer runs on a machine where you can create symbolic links. On Windows, the README states that Dotbot supports Python 3.8 or newer and requires that your account is allowed to create symbolic links. If that permission is unavailable, linking fails and the tool has no fallback, because linking is the core operation.

The second boundary is templating. A config that needs the same file rendered differently on a laptop and a server has to solve that with shell commands or a plugin. Dotbot's own directives do not interpolate variables.

The third is scope. Clean removes broken symbolic links from directories you list; it is not a general garbage collector, and it will not notice files you stopped managing. If you want a tool that owns the whole lifecycle of your configuration, including package installation and secrets, Dotbot's core is too small and you will be assembling plugins to get there.

Dotbot compared with GNU Stow

GNU Stow is the closest comparison, and the difference is in the data model. Stow infers links from directory structure: you place files in a package directory mirroring the target tree and Stow creates the symlinks for you. Dotbot makes the mapping explicit. Every link is a line in install.conf.yaml naming target and source, and the README's example shows exactly that with ~/.tmux.conf mapped to tmux.conf.

Explicit mapping costs more typing and buys two things. You can link a file to a name that does not match its location in the repository, and you can mix in create and shell directives in the same file, in a defined order. Stow has no equivalent of the shell directive, so post-link commands need a wrapper script. Conversely, Stow needs no install step in your repository and no shim script, while Dotbot's submodule route adds a submodule, a .gitmodules setting and a copied install script.

If your repository already mirrors the home directory layout and you only ever create symlinks, Stow is less machinery. If your install has steps beyond linking, Dotbot's directive list is the reason to pick it.

Licence, release cadence and what that means for a dotfiles repo

Dotbot is MIT licensed, and the pyproject.toml declares the MIT classifier alongside Development Status 5 - Production/Stable. MIT is permissive, so vendoring it as a submodule inside your dotfiles repository is straightforward; the LICENSE.md file at the repository root carries the terms. This is a description of the licence, not legal advice, and if you redistribute Dotbot inside a product you should read the file yourself.

The only runtime dependency declared in pyproject.toml is PyYAML, constrained to >=6.0.1,<7, and the package requires Python 3.7 or newer. The test matrix in pyproject.toml covers CPython 3.7 through 3.14 plus PyPy 3.9 and 3.10, which tells you the maintainers are testing across interpreter versions rather than a single one. The last push to the repository was on 2026-07-12, and the most recent release listed is v1.24.0 from 2025-11-29.

For a dotfiles repository the upgrade cost is low in either installation mode, but the pinned-submodule route means an upgrade is a deliberate commit rather than something that happens behind your back. That is usually the behaviour you want for a file that decides where your shell configuration points.

Editorial conclusion

Adopt Dotbot if your dotfiles already live in Git and you want the install step to be a single idempotent command with a readable YAML file. Skip it if you need templating, per-host variable interpolation or secret decryption out of the box, because none of that is in the core directives. Before committing, verify three things: that your install script points at the right config path and submodule directory, that relink is set under defaults if you expect changed links to be replaced, and that your platform can create symbolic links, since Windows requires that permission and Python 3.8 or newer.

Frequently asked questions

How do I use Dotbot?

Write a YAML or JSON config, conventionally install.conf.yaml, listing directives such as link, create and shell, then run the install script from your dotfiles directory. The README's sequence is git clone of your dotfiles repository into ~/.dotfiles, cd into it, then ./install.

What is Dotbot?

It is a dotfiles bootstrapper written in Python. It reads a configuration file and performs the operations listed there: linking files and folders, creating directories, running shell commands and cleaning broken symbolic links. It does not manage or version your dotfiles itself.

What is a Dotbot alternative?

GNU Stow takes a different approach: it infers symlinks from a directory tree that mirrors the target layout, so there is no config file naming each link. Dotbot instead makes every mapping explicit in install.conf.yaml and can also create directories and run shell commands in the same file.

Official sources

  1. anishathalye/dotbot on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
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/anishathalye-dotbot.svg)](https://hysenlabs.com/projects/anishathalye-dotbot)