# thoughtbot/dotfiles: an opinionated zsh, vim, git and tmux setup managed by rcm

> thoughtbot's dotfiles are not a general dotfile manager. They are one team's working configuration, installed by symlinking the repo into your home directory with rcm and extended through a separate dotfiles-local overlay.

**thoughtbot/dotfiles** — A set of vim, zsh, git, and tmux configuration files.

- Repository: https://github.com/thoughtbot/dotfiles
- Website: https://thoughtbot.com
- Stars: 8,170 · Forks: 1,767
- Language: Shell
- License: NOASSERTION
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/thoughtbot-dotfiles

## The problem thoughtbot/dotfiles solves, and for whom

Most people who publish dotfiles are publishing a personal setup. This repository is a team setup. It carries the zsh, vim, git and tmux configuration that thoughtbot uses, and its real subject is not the aliases or the color scheme but the override mechanism: how one shared baseline can be installed on many machines without anyone editing the shared files. That is why the README spends as much space on ~/dotfiles-local as it does on installation.

The audience is narrow and specific. You need zsh as your login shell, since the first documented requirement is changing it with chsh. You need to be comfortable with vim as an editor rather than merely tolerant of it, because the vim configuration is opinionated: the leader key is bound to a single space, and space-space switches between the last two files. You need tmux, git and a Unix-like machine. If you are assembling a desktop environment for a Wayland compositor, this repository has nothing for you; the top-level entries are shell, editor and version control configuration, not compositor configuration.

The value is in the defaults being someone's actual daily defaults. The zsh history block is a good example: hist_ignore_all_dups, hist_ignore_space, inc_append_history and share_history are all set, with history size at 8,192 entries. Those four options together mean duplicates are dropped, commands prefixed with a space are never recorded, history is written as commands run rather than at shell exit, and multiple zsh sessions see each other's history. That is a considered set of choices, not a template.

## How rcm turns the repository into your home directory

The mechanism is symlinking, driven by rcm. You clone the repository, then run rcup with the RCRC environment variable pointing at the rcrc file inside the clone. rcup reads that file and creates symlinks in your home directory for the config files the repository ships.

The rcrc file does two jobs. It excludes files that live in the repository but should not be linked into your home directory, namely README.md, README-ES.md and LICENSE. It also sets precedence so that files in ~/dotfiles-local win over the repository's own files. On the first run, rcup symlinks the repository's rcrc to ~/.rcrc, which is why the RCRC variable is described as one-time: later runs find the configuration on their own.

The repository layout matches that promise. Top-level entries include aliases, gitconfig, gitignore, gitmessage, psqlrc, railsrc, tmux.conf, vimrc, vimrc.bundles, zprofile, zshenv and zshrc, along with directories for zsh, vim, git_template and hooks. Each of those is a file rcup can link, and each has a documented .local counterpart. The naming convention is the whole extension model: aliases.local, gitconfig.local, tmux.conf.local, vimrc.local, vimrc.bundles.local, zshrc.local, and psqlrc.local, the last of which the repository supplies blank so that psql does not error before you write your own.

Two details in the zsh layer are worth knowing before you install. Files under ~/dotfiles-local/zsh/configs are loaded automatically, and two subdirectory names are special: pre for files that must load first, post for files that must load last. The README's own examples show why the distinction is real rather than decorative. A virtualenv wrapper script goes in pre because it depends on shell features that later settings may change. A chpwd function goes in post. Key bindings go in a plain file inside configs. The README also notes that zshrc.local loads after the configs directory, which gives you a final say.

## Installing thoughtbot/dotfiles and making a first override

The README's requirements section starts with the login shell. Run this and then start a new session, because the rest of the setup assumes zsh is what you land in.

```bash
chsh -s $(which zsh)
```

Clone the repository into your home directory and install rcm. The README gives the SSH clone URL and Homebrew for rcm on macOS.

```bash
git clone git@github.com:thoughtbot/dotfiles.git ~/dotfiles
brew install rcm
```

Then run rcup with RCRC set. This is the step that creates the symlinks, and it is the only time you need the variable.

```bash
env RCRC=$HOME/dotfiles/rcrc rcup
```

After that, create the override directory and put something in it. The README's example is an alias, which is the least invasive way to confirm the precedence rule works.

```bash
mkdir ~/dotfiles-local
printf "alias todo='$EDITOR ~/.todo'\n" >> ~/dotfiles-local/aliases.local
rcup
```

Run rcup again and open a new shell. The todo alias should exist, and the file it came from lives outside the clone, so pulling updates will not touch it. If you later add vim plugins through ~/dotfiles-local/vimrc.bundles.local, remember the README's warning that rcup must be run after pulling so that plugins are properly installed.

## UnPlug, and the limits of overriding vim plugins

The vim layer uses vim-plug, and the repository exposes a small extension vocabulary on top of it. In ~/.vimrc.bundles.local you can call UnPlug with a plugin name to drop it from the default set. The README's example removes vim-scripts/tComment by writing UnPlug 'tComment', noting that the username portion is stripped. UnPlug also serves as a prerequisite for replacement: you UnPlug a plugin and then Plug a fork or a differently configured version in its place. The README shows both patterns, one installing a personal fork from a local path and one loading vim-coffee-script only for coffee buffers.

That is a clean design, and it has a cost. You are editing a bundle list in a second file and re-running rcup to reconcile it, rather than running a plugin manager command directly. If a plugin misbehaves, the failure surface includes the override file as well as the plugin. And the mechanism only covers plugins declared through the bundle list. Anything installed outside vim-plug is outside the model.

The vim configuration directory has a smaller extension surface than the zsh one, and the README says so directly: files in ~/dotfiles-local/vim/plugin are loaded automatically, but there is no pre or post subdirectory support as there is for zsh. If load order matters to you, the vim side gives you less control than the shell side.

## What the repository does not do

This is not a dotfile manager. It is a set of dotfiles that happens to be installed by one. If you want a tool that manages arbitrary dotfiles across machines with per-host configuration, rcm is the thing you would evaluate, and this repository is an example of using it, not a replacement for it. The README points at rcm's own repository for that.

It is also not a general-purpose environment. Nothing in the top-level layout addresses a window manager, a status bar, a terminal emulator's own configuration, or a desktop theme. Searches for dotfiles tied to Hyprland, Niri, Arch or KDE land on this repository by name and find nothing that applies. The same goes for a bare git repository workflow, where you keep dotfiles in a git repo and check files out directly into $HOME with no symlink layer. That approach has no rcm dependency and no override directory, and it also has no story for excluding README.md or giving a separate directory precedence. The trade-off is real in both directions.

One more boundary: the repository ships a git_template directory and hooks, and the README explains that git hook extensions go in ~/dotfiles-local/git_template.local/hooks as executable scripts. That is a documented extension point, but the README does not describe rollback, nor does it describe what happens to existing files in your home directory that collide with a link rcup wants to create. If you already have a hand-written ~/.zshrc, that question is yours to answer before running the install command, not after.

## Maintenance, licensing and what an upgrade actually costs

The repository is not archived, and the last push was on 2026-09-03. The release tags are old by comparison: 20171006 and 20170915, both from 2017. That combination tells you something practical. Work continues on the main branch, but there is no recent tagged release to pin against, so an upgrade means pulling the branch, not moving between versions. If you need reproducible installs across machines, you would have to pin a commit yourself.

The upgrade procedure is documented and short: pull, then run rcup. The README is emphatic that rcup must run after pulling so that new vim plugins are installed, and notes that running it repeatedly is safe. Because your customizations live in ~/dotfiles-local and take precedence, a pull mostly changes the baseline underneath you. The exceptions are the files you have chosen not to override: if you rely on the repository's zshrc, aliases or vimrc directly, a pull can change your shell behaviour without any action on your part beyond the rcup you were told to run.

Licensing needs care. The repository's LICENSE file is present at the top level, and the GitHub metadata reports the license as NOASSERTION, meaning no standard licence identifier was detected. The README does not restate the terms. Read the LICENSE file itself before you copy this configuration into anything you distribute, and note that the rcrc excludes LICENSE from being symlinked, so it will not appear in your home directory after installation. Nothing here is legal advice; the point is simply that the licence text is in the repository and the metadata does not classify it.

## Conclusion

Adopt this if you already work in zsh, vim and tmux and want a maintained baseline you can override file by file in ~/dotfiles-local rather than a framework you configure from scratch. Do not adopt it if you use Hyprland, Niri or another Wayland compositor, if you expect a window manager configuration, or if you want your dotfiles stored in a bare git repository with no extra tool. Verify two things before rcup touches your home directory: the contents of the rcrc file in the repository, which sets the exclusions and gives precedence to ~/dotfiles-local, and whether you are willing to run rcup again after every git pull, since the README states that new vim plugins are only installed on that second run.

## FAQ

### How do I install thoughtbot/dotfiles?

Set zsh as your login shell with chsh, clone the repository to ~/dotfiles, install rcm (the README uses brew install rcm), then run env RCRC=$HOME/dotfiles/rcrc rcup. That last command creates the symlinks, and after it runs you can use rcup without setting RCRC again.

### How do I use thoughtbot/dotfiles after installing it?

You work in the shell, editor and tmux sessions the configuration sets up, and you put your own changes in ~/dotfiles-local using the .local naming convention, such as aliases.local or zshrc.local. Files there take precedence over the repository's versions, and you run rcup again to link any new files.

### Can I use thoughtbot/dotfiles on Linux or Ubuntu?

The README's install steps use Homebrew to install rcm, which is the macOS path it documents. The configuration itself is shell, vim, git and tmux, so the parts that matter are not macOS-specific, but the README does not give a Linux package command for rcm and you would need to get rcm another way.

### How do I put my own customizations into thoughtbot/dotfiles?

Create ~/dotfiles-local and add files with the .local suffix, for example aliases.local, gitconfig.local, tmux.conf.local, vimrc.local or zshrc.local. The rcrc file gives that directory precedence over the repository, so your versions win. For zsh, files under ~/dotfiles-local/zsh/configs load automatically, with pre and post subdirectories for load order.

### What is a dotfile?

A dotfile is a configuration file whose name begins with a dot, such as .zshrc or .gitconfig, which is how Unix-like systems mark files as hidden by default. thoughtbot/dotfiles is a collection of them for zsh, vim, git and tmux, installed by symlinking them into your home directory.

## Sources

- [Issues](https://github.com/thoughtbot/dotfiles/issues)
- [Project website](https://thoughtbot.com)
- [README](https://github.com/thoughtbot/dotfiles/blob/main/README.md)
- [Releases](https://github.com/thoughtbot/dotfiles/releases)
- [thoughtbot/dotfiles on GitHub](https://github.com/thoughtbot/dotfiles)

---

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