# dotfiles: a Dotbot setup for a whole development machine

> This repository is a personal dotfiles setup that installs Vim, Emacs, shells, tmux, screen, Git, Mercurial and a pile of language tooling onto a new machine with a single command. The part worth borrowing is the escape hatch: nine documented local override files that let one person keep the tracked configuration shared while their own machine-specific settings stay out of git.

**anishathalye/dotfiles** — ~anish • powered by https://github.com/anishathalye/dotbot 💾

- Repository: https://github.com/anishathalye/dotfiles
- Stars: 756 · Forks: 265
- Language: Shell
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/anishathalye-dotfiles

## One command, and a promise that it can be run twice

After cloning this repo, run `install` to automatically set up the development environment. The note that follows is the one that distinguishes this from most dotfiles: the install script is idempotent, it can safely be run multiple times.

That property is what makes a dotfiles repository usable in practice. A setup script that blindly copies files over the top of your own configuration is a one-shot thing that you run once on a fresh machine and then never touch again, because the second run breaks the machine you have already customised. A script that can be run again, on a new machine or on the same one after a change, becomes something you return to.

The build badge in the title points at a GitHub Actions workflow, so the configuration is at least checked on every push, which is how a large set of shell and editor files avoids rotting into something that only works on the original author's machine.

The scope is broad, and the repository listing gives the full picture. There is a vim/ directory with a vimrc at the root, an emacs directory with an emacs.d/ inside it, a zsh/ directory with a zshrc, a bash/ directory with bashrc and bash_profile, a shell/ directory, a tmux.conf, a screenrc, a gitconfig, an hgrc for Mercurial, an inputrc for readline, an editrc, a pythonrc and an ipython/ directory, a haskeline, a gnupg/ directory, a bin/ directory, a claude/ directory, and two ignore files in the global form, gitignore_global and agignore.

So this is not a shell configuration. It is an entire workstation, and the presence of an emacs.d/ directory alongside a vim/ directory tells you the author maintains both.

The licence is MIT, and the copyright is Anish Athalye.

## Dotbot is the installer, and it is the author's own project

Dotfiles uses Dotbot for installation, and the repository description credits the whole setup as powered by a specific project, https://github.com/anishathalye/dotbot.

That is the same author, and it is the point of the design. Dotbot is a separate project from this one, and it is what performs the installation, so the interesting question for an adopter is how the two are wired together.

The repository carries the answer in two entries. There is a.dotbot directory, whose name matches the installer, and there is a.install.conf.yaml file at the root, which is the configuration Dotbot reads. Both are readable before you run anything, which is the property that matters when a script is going to write into your home directory.

That declarative shape is a very different thing from a Makefile with a hundred cp commands, and it is the difference that makes idempotency achievable. The configuration declares the desired state, Dotbot works out the current state, and it only changes what is different, so a second run changes nothing.

The.gitmodules file at the root records that parts of the setup are submodules, which is consistent with the split described below. And the small.github/ directory holds the CI workflow that the badge points at.

The practical takeaway for anyone reading this as a template: the install step is declarative, and the declarations are in YAML files you can read before running anything.

## The local override convention, which is the genuinely reusable idea

Making Local Customizations is a section of its own, and it is the part of this repository that generalises beyond one person's machine.

You can make local customizations for some programs by editing specific files, and the list is explicit about which programs support it and what the file is called:

```
* `vim` : `~/.vimrc_local`
* `emacs` : `~/.emacs_local`
* `zsh` / `bash` : `~/.shell_local_before` run first
* `zsh` : `~/.zshrc_local_before` run before `.zshrc`
* `zsh` : `~/.zshrc_local_after` run after `.zshrc`
* `zsh` / `bash` : `~/.shell_local_after` run last
* `git` : `~/.gitconfig_local`
* `hg` : `~/.hgrc_local`
* `tmux` : `~/.tmux_local.conf`
```

The ordering is the part that needs thought. The shell hooks come in four slots, and the sequence is: shell_local_before runs first, then zshrc_local_before runs before .zshrc, then zshrc_local_after runs after .zshrc, and finally shell_local_after runs last. That gives you a place to put a setting that must be in effect before anything else, a place to prepend to the zsh configuration, a place to append to it, and a place to run after everything is loaded.

The names are also chosen to sort. The zsh and bash files are named so that a shell that sources a glob of them picks them up in the right order, and the fact that the local file for zsh comes before the local file for bash in the list is a reminder that both shells are supported, not just one.

The reason this convention exists is stated in the README. For the color scheme to look right, you also need terminal-specific support, and the configuration for that, along with a whole bunch of other machine-specific configuration, is located in a separate repository called dotfiles-local.

So there are two repositories. The one you are reading holds the shared configuration. The other holds the parts that belong to one terminal, one machine, one set of colours. The local files in your home directory are the seam between them, and they are the only files you are expected to edit by hand.

## What is actually in the tree, and what a Dotbot install probably does with it

The top level of the repository is worth reading as a list of decisions, because each entry is a tool the author uses daily.

The editor story is doubled up, with vim/ and vimrc, then emacs and emacs.d/. The shell story is tripled, with bash/, bashrc and bash_profile, then zsh/ and zshrc, and then a shell/ directory that is likely the shared configuration both source. The terminal story covers tmux.conf and screenrc, which is a rare combination and suggests someone who moves between a local terminal, a remote machine over SSH and a screen session on a server.

For version control there is gitconfig and hgrc for Mercurial, with a gnupg/ directory next to the Mercurial config, which is the natural pairing since Mercurial has its own signing and encryption preferences separate from Git's.

The language tooling is present in small doses: a pythonrc and an ipython/ directory, a haskeline for the Haskell shell, an inputrc for readline behaviour, and an editrc for the editline library.

There is a bin/ directory for scripts, and a claude/ directory, which for a configuration repository is a relatively recent addition and tells you the author uses an AI coding assistant and has chosen to version its configuration alongside everything else.

The two global ignore files are worth a note. gitignore_global is a Git configuration file that sets core.excludesFile, and agignore does the same job for ag, the Silver Searcher. Putting both in the repository means a fresh clone gets the same ag-based ignore behaviour as the author's, which is the kind of small consistency that only matters to someone who has set it up before and missed it on a new machine.

## Maintenance, and what the state of the repository tells you

The maintenance picture is modest and worth being precise about.

The last push to the repository was on 2026-08-26, the repository is not archived, and there are no GitHub releases. So the configuration is still being worked on, and the way it is distributed is a clone plus the install script rather than a packaged artefact.

That is the right model for dotfiles and it also means there is no version history you can pin to. The git history of the repository is the version history, so a machine that installs from master is installing whatever was on master that day. If you want a stable machine, you fork it and you let your own commits accumulate, which is what most people actually do with a dotfiles repository even when the original author published theirs.

The CI workflow is the other quality signal. A dotfiles repository that only works on the author's machine is a common failure mode, and the way to catch it is to build the configuration on every push in a clean environment. A badge for that workflow, with a workflow that runs on every commit, is the difference between a configuration you can trust on a second machine and one you cannot.

The dotfiles-local repository is the other half of the maintenance story, and it is where the terminal-specific configuration and other machine-specific configuration live. Its separation is what keeps the shared repository free of anything that only works on one desk, and it is the part of the design that transfers most cleanly to a setup of your own.

If you are going to reuse any of this, that convention and the two-repository split are worth copying, and the specific list of editors is not.

## Conclusion

Adopt this dotfiles setup if you want a working editor, shell, terminal and Git configuration on a new machine in one command and you are willing to read a hundred files before changing anything. Do not adopt it as a template for your own dotfiles without reading the local override convention first, because the trick that makes it usable is that the machine-specific parts live in a second repository rather than in yours. Before you run the install script, read the .install.conf.yaml and the .dotbot configuration, and check the dotfiles-local repository, because that is where the parts you will actually want to change will end up.

## FAQ

### How do I install this dotfiles setup?

Clone the repository and run the install script, which sets up the development environment automatically. The script is idempotent, so it can safely be run multiple times, and it uses Dotbot for the installation.

### How do I keep my own machine-specific settings out of the shared dotfiles?

Each supported program has a local override file that is read at a documented point in the shell configuration, such as ~/.vimrc_local, ~/.emacs_local, ~/.gitconfig_local and ~/.tmux_local.conf. The zsh and bash hooks come in four ordered slots, from ~/.shell_local_before through to ~/.shell_local_after.

### What is Dotbot and why is it used here?

Dotbot is the installer this repository uses, written by the same author. The setup is described as powered by it, with a.dotbot directory holding the plugins and a.install.conf.yaml declaring what gets installed where, which is what makes the install script idempotent.

### Which programs does this dotfiles setup configure?

The tree covers Vim, Emacs, Bash, Zsh, tmux, screen, Git, Mercurial, GnuPG, Python and IPython, haskeline, readline, editrc and a bin directory of scripts. The README also notes that the colour scheme needs terminal-specific support configured separately in the dotfiles-local repository.

## Sources

- [anishathalye/dotfiles on GitHub](https://github.com/anishathalye/dotfiles)
- [Issues](https://github.com/anishathalye/dotfiles/issues)
- [License: MIT](https://github.com/anishathalye/dotfiles/blob/master/LICENSE)
- [README](https://github.com/anishathalye/dotfiles/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/anishathalye-dotfiles
