# paulmillr's dotfiles treat the local machine as hostile and the network as absent

> This dotfiles repository is a dependency free configuration set for Mac, Linux and BSD with zsh completion, a themed vim, terminal colours and a security posture that assumes branch names and archives are attacker controlled. It is MIT licensed, and the last push was on 2026-09-09.

**paulmillr/dotfiles** — Colourful & robust configuration files and utilities for Mac, Linux & BSD

- Repository: https://github.com/paulmillr/dotfiles
- Website: https://dotfiles.github.io/inspiration/
- Stars: 1,243 · Forks: 177
- Language: Vim Script
- License: not declared
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/paulmillr-dotfiles

## The install step checks the commit signature before running anything

The README's install sequence is unusual, and the reason is that the project treats the machine as untrusted.

```sh
git clone https://github.com/paulmillr/dotfiles.git "$HOME/Developer/personal/dotfiles"
cd "$HOME/Developer/personal/dotfiles"

curl -s https://github.com/paulmillr.gpg | gpg --import
[ "$(git log -1 --format=%GP)" = "78A89CD10959782E23FF8447697079DA6878B89B" ] || { echo 'commit is not signed with the expected key'; exit 1; }
git show --stat --oneline HEAD

./install.sh
```

The order matters. The public key is fetched and imported first, then the check compares the GPG signer fingerprint of the tip commit against a hardcoded value, and the script exits if it does not match. Only then does the user look at what the commit actually contains with git show --stat, and only after that does the installer run.

So the trust model is explicit: you are not trusting the repository because it is on GitHub, you are trusting it because the tip commit is signed by a key whose fingerprint you can check against the one printed in the README, and then you read the diff before installing it. The stat output is there so that the person running it has a chance to see what is about to be installed.

The README then states two facts about the installer itself. The installer performs no network requests, and it invokes ./scripts/link.sh from its own checkout. The second point is what makes the first one meaningful, because a link script that fetched a remote archive would be a network request, and one that ran something from your home directory would be a supply chain problem. The installer works from the checkout you just verified.

And it is reversible, in a specific way. Displaced paths are preserved as .bak, .bak.1, and so on, so re-running the installer does not destroy what it replaced, it renames it and increments the suffix.

## The threat model is stated as a list of assumptions

The security section of the README is the most distinctive part of this project, and it works by listing what it assumes to be hostile.

The branch names, archives, directory names, and other local users are assumed hostile. That is a precise and unusual threat model. A branch name is a string that ends up in a shell prompt, in a directory path, in a git log line, and if your tooling interpolates any of those unquoted, a repository you clone can run code on your machine. The archives assumption is about downloaded tarballs with paths that escape the extraction directory, or entries that overwrite your configuration. The local users assumption is about a shared machine, where another account on the same system is not on your side.

Three concrete mechanisms follow from that model. The installer doesn't do network and is verifiable and reversible. git offers exactly ONE key to git hosts via IdentitiesOnly=yes, which stops a repository's own config from nominating a different key for signing on your behalf. And git log shows signature status, so you can see at a glance in the log whether a commit was signed.

The telemetry line is a nice detail. Telemetry is disabled to known scripts via env vars like DO_NOT_TRACK=1, which is a convention some tools honour, and applying it to known scripts means the dotfiles themselves turn it off for you rather than leaving you to remember.

Taken together, this is a coherent position. The tools a developer runs are executed in a directory they did not write, on strings they did not control, so the configuration layer is where the defences go. It is also why the project is dependency free, since every dependency is another thing that runs on your machine.

## No dependencies, which is the point

The first feature bullet says no external dependencies, with a comparison to oh-my-zsh and prezto.

That comparison sets the stakes. Those two projects are the standard way to get a rich shell configuration, and they both work by pulling in a large tree of plugins, each with its own upstream, each of which can execute code in your shell at startup. The result is a configuration whose behaviour depends on dozens of repositories you did not write, and it changes when any of them changes.

This project does the opposite. Everything is in the repository, so the surface you trust is the surface you can read, and the plugin-free model means there is nothing to update underneath you. The auto-completion and syntax highlighting for zsh are part of the configuration rather than a plugin dependency.

The vim configuration is described in the README as turning vim into a full-fledged mini-IDE, with tree view and other plugins. The word plugins here is doing different work than in the oh-my-zsh comparison, since these are vendored in the repository rather than fetched at runtime.

The directory layout follows the same logic. The home directory has tiny files installed into $HOME, namely zshrc, bashrc and gitconfig. The config/ directory has all the important parts, with shell/ holding zsh and bash setup plus extra helper functions, git/ holding git log formatting, vim/ holding the editor setup, terminal-themes/ holding the colour scheme for Apple Terminal, iTerm and Ghostty, where it is shipped by default, plus ghostty/ and vscode/ directories for terminal and editor settings.

Splitting the tiny home files from the substantial config directory is a practical arrangement. The home files are the ones that get symlinked into place and need to be stable, and the config directory is the part you actually edit.

## Git configuration with one identity, a mailmap and signed commits

The git section is short and specific, and it is the part of a dotfiles repository that is easiest to copy and easiest to get wrong.

You set the author with the usual two git config --global commands, one for user.name and one for user.email.

Then there is the mailmap. To enable checkboxes in git logs, you add config/git/mailmap, where the format is a name followed by one or more addresses, so a single identity can be listed against every address it uses.

The mailmap is what makes the same human appear as one identity in the log, and it is also how you get those checkboxes, since git can only render a signature marker when it can resolve the commit to a known identity. A contributor with three email addresses across a personal and a work address would otherwise appear three times in a short log, and the signature display depends on that mapping.

Then GPG signing, which is enabled with git config --global commit.gpgsign true and git config --global tag.gpgSign true.

Both commit and tag signing are enabled globally. Combined with the IdentitiesOnly=yes setting from the security section, the picture is a git configuration where a commit is signed by a key you nominated and nothing else, and where a tag is signed the same way.

The log formatting in config/git/ is what turns those settings into something visible, since the README describes git log formatting as one of the things that directory holds, and the signature status display is the part that makes the signing worth the effort.

## Terminal colours for three terminals, and what the repository does not include

The terminal-themes/ directory holds a colour scheme for Apple Terminal, iTerm and Ghostty, and the README notes that Ghostty ships it by default. That last point matters more than it looks: a colour scheme that a terminal already knows about is one less thing for you to configure and one fewer place for the colours to drift out of sync.

The ghostty/ and vscode/ directories hold some settings for the terminal and the editor, described as some settings rather than a full configuration, which suggests the intent is to complement what those applications already do rather than replace them.

The top level of the repository is small. There is install.sh, a scripts/ directory, a config/ directory, a home/ directory, a tests/ directory, a .gitignore and the README. The presence of a tests/ directory next to install.sh is worth noting, since it suggests the install and link behaviour is covered by something rather than being a shell script nobody has run since the last change.

What the repository is not is a settings sync service. There is no account, no sync, no conflict resolution between machines, and the site linked in the homepage is an inspiration page at dotfiles.github.io/inspiration/, which suggests the project is a reference implementation others draw from rather than a product.

The primary language is listed as Vim Script, which is a reasonable label for a repository where the largest single component is a vim configuration, though the shell scripts in scripts/ and the install.sh are the parts you run. The licence situation has a wrinkle worth flagging: the licence field in the project listing is unknown, while the README states the MIT Licence with the standard text and a copyright line for Paul Miller dated 2011. The README is the authoritative statement here, and the metadata gap is likely a classification failure on GitHub's side rather than an ambiguity in the terms.

## Conclusion

paulmillr's dotfiles suit someone who wants a coherent shell, git, vim and terminal setup across several Unix systems and who cares about how their configuration behaves under a hostile repository. They are the wrong choice if you want a graphical settings sync, a large plugin ecosystem, or a configuration that assumes it runs on a machine you fully control. Before adopting them, read the install script rather than running it blindly, because the whole point of the design is that the installer makes no network requests and is reversible, and verifying that is what makes the rest trustworthy.

## FAQ

### What is paulmillr's dotfiles repository?

It is a collection of colour-robust, security-minded configuration files and utilities for Mac, Linux and BSD, with zsh auto-completion and syntax highlighting, a themed vim, terminal colour schemes for Apple Terminal, iTerm and Ghostty, and no external dependencies.

### How does the dotfiles installer verify what it installs?

The README's install sequence imports the maintainer's GPG key, checks that the tip commit's signer fingerprint equals a hardcoded value and exits if it does not match, shows the commit stat for review, and only then runs ./install.sh. The installer performs no network requests and invokes ./scripts/link.sh from its own checkout.

### What happens to files that are already in place when installing?

Displaced paths are preserved as .bak, .bak.1, and so on, so re-running the installer renames what it replaces rather than deleting it, which makes the install reversible.

### What security assumptions does the dotfiles project make?

The README says branch names, archives, directory names and other local users are assumed hostile, that the installer does no network and is verifiable and reversible, that git offers exactly one key to git hosts via IdentitiesOnly=yes, that git log shows signature status, and that telemetry is disabled to known scripts via env vars such as DO_NOT_TRACK=1.

### How do I enable git commit signing with these dotfiles?

The README asks you to set git config --global commit.gpgsign true and git config --global tag.gpgsign true, and to add config/git/mailmap so that identities map to one name in the log, which is also what enables the signature checkboxes.

## Sources

- [Issues](https://github.com/paulmillr/dotfiles/issues)
- [paulmillr/dotfiles on GitHub](https://github.com/paulmillr/dotfiles)
- [Project website](https://dotfiles.github.io/inspiration/)
- [README](https://github.com/paulmillr/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/paulmillr-dotfiles
