STATUS: CONNECTED
LATENCY: 42ms

dots


dots is a Go command-line tool for managing dotfiles across machines and contexts. It borrows Homebrew’s organizational model — where a repository is just a list of packages — and chezmoi’s ability to bootstrap itself onto a fresh system. The result is a dotfile manager that handles multiple independent sets of configuration (public, personal, work) without them stepping on each other.

Why another dotfile manager

Most dotfile approaches boil down to a single Git repo with a script that symlinks everything into place. That works fine until you have configuration that can’t be public, or you need different setups for different machines. Stow gets you halfway there, but it doesn’t handle multiple repos, platform differences, or the bootstrapping problem — getting the tool itself installed on a new machine.

dots treats each Git repository as a tap (borrowed from Homebrew’s terminology). A tap can contain multiple packages, each with its own Dotfile.yaml manifest declaring what files go where and what hooks to run. You can maintain a public tap for your shell and editor config, a private tap for credentials and SSH keys, and a work tap for company-specific tooling — all managed by the same tool.

Core concepts

Taps are named pointers to Git repositories. Any Git repo can be a tap — public or private, on GitHub or anywhere else. Each tap holds one or more packages.

Packages are directories within a tap containing a Dotfile.yaml manifest and the configuration files to install. The manifest declares links (where files go), hooks (scripts to run at install/upgrade/remove), and platform-specific overrides.

Overlays layer on top of base packages, merging or replacing specific files. A work overlay on a personal zsh package can append company-specific aliases without forking the base config. Merged files get visible marker comments so you can always tell where each section came from.

Profiles are ordered collections of packages and overlays applied together. A work profile can extend a personal profile, adding work-specific packages on top of the personal baseline.

Cross-platform path resolution

Dotfiles land in different locations on different operating systems. dots solves this with path aliases@config resolves to ~/.config on Linux/macOS and %APPDATA% on Windows, @home resolves to $HOME or %USERPROFILE%, and so on. A link target of @config/nvim/init.lua does the right thing on every platform without requiring platform-specific sections in the manifest.

When platform differences go beyond paths, the manifest supports OS and OS-arch overrides that cascade from general to specific:

base settings → OS-only overrides → OS-arch-specific overrides

Self-bootstrapping

dots manages its own configuration — the dots config is itself a package in a tap. On a fresh machine:

dots init --from <git-url> --path <directory>

This clones the tap, applies the dots package (installing its own config), and establishes the initial state. From there, applying a profile pulls in everything else.

dots supports three ways to place files: symlink (default, changes propagate instantly), copy (manual sync via dots sync, for restricted filesystems), and hardlink (instant updates within the same filesystem). The strategy cascades from package-level settings down to global defaults, and on Windows the system auto-detects symlink capability and falls back to copy if needed.

Design constraints

The tool deliberately avoids template languages, registries, and magic. Configuration is plain YAML. Taps are just Git repos. Every operation is reversible through backups and lockfile tracking. The goal is a system where you can always read the manifest and understand exactly what will happen.

GitHub

View the source code on GitHub