dotbot-go is a small command-line tool that helps you set up a computer from a dotfiles repository.
You write one config file that says:
- create these folders
- link these files into my home directory
- remove broken old symlinks
- run these setup commands
Then you run dotbot-go, preview the changes, and apply them.
This project is a Go implementation of the core Dotbot workflow. It keeps the familiar config style while shipping as a single binary.
Use dotbot-go when you keep configuration files in a Git repository and want to install them on a new machine or keep multiple machines in sync.
Common examples:
- link
~/.vimrctovimrcin your dotfiles repo - link
~/.tmux.conftotmux.conf - create folders like
~/.config/nvimor~/.local/bin - run setup commands such as
git submodule update --init --recursive
Install a prebuilt release with:
curl --proto '=https' --tlsv1.2 -sSf https://github.com/worxbend/dotbot-go/releases/latest/download/install.sh | shSet DOTBOT_VERSION to pin a specific release tag, or DOTBOT_INSTALL_DIR to install elsewhere. The script also adds the install directory to PATH in ~/.bashrc and ~/.zshrc if it's missing.
From this repository:
just buildThis creates:
bin/dotbot
If you do not have just, you can build with Go directly:
mkdir -p bin
go build -buildvcs=false -o bin/dotbot ./cmd/dotbot-goCreate install.conf.yaml in your dotfiles repository:
- defaults:
link:
create: true
relink: true
- clean:
- "~"
- create:
- "~/.config"
- "~/.local/bin"
- link:
~/.vimrc: vimrc
~/.tmux.conf: tmux.conf
~/.config/nvim:
path: nvim
- shell:
- [git submodule update --init --recursive, Installing submodules]In plain English, this means:
- use sensible defaults for links
- clean broken symlinks in your home directory
- create a couple of folders
- link files from the repo into your home directory
- update Git submodules
Check that the config file can be parsed and only uses supported directive shapes:
./bin/dotbot validate -c install.conf.yamlValidation also reports how many operations would be planned. It does not create directories, links, or run shell commands.
Print the operations that the config expands into:
./bin/dotbot plan -c install.conf.yamlUse JSON when another tool needs to consume the plan:
./bin/dotbot plan -c install.conf.yaml --output jsonAlways run a dry run first:
./bin/dotbot -c install.conf.yaml --dry-runDry run prints what would happen without changing your filesystem.
When the preview looks correct:
./bin/dotbot -c install.conf.yamlA typical dotfiles repository looks like this:
dotfiles/
├── install.conf.yaml
├── vimrc
├── tmux.conf
└── nvim/
Run dotbot-go from that repository:
cd ~/.dotfiles
dotbot-go -c install.conf.yamlOr point to the repository explicitly:
dotbot-go -d ~/.dotfiles -c ~/.dotfiles/install.conf.yamlThe -d option sets the base directory. Relative paths in your config, such as vimrc or nvim, are resolved from that directory.
dotbot-go supports these file formats:
| Format | Extensions | Best For |
|---|---|---|
| YAML | .yaml, .yml |
Most dotfiles users |
| JSON | .json |
Strict machine-generated config |
| JSON5 | .json5 |
JSON with comments and trailing commas |
| TOML | .toml |
Users who prefer TOML syntax |
Complete examples:
YAML, JSON, and JSON5 can use a top-level task list. TOML should put the task list under tasks.
More detail: Config Formats Guide
Directives are the actions in your config file. They run in the order you write them.
| Directive | What It Does |
|---|---|
defaults |
Sets default options for later directives |
clean |
Removes broken symlinks from selected directories |
create |
Creates directories |
link |
Creates symlinks or hardlinks |
shell |
Runs shell commands |
More detail: User Guide
Validate without applying changes:
dotbot-go validate -c install.conf.yamlThis reports whether the configuration is valid and how many operations would be planned.
Print planned operations:
dotbot-go plan -c install.conf.yamlPrint planned operations as JSON:
dotbot-go plan -c install.conf.yaml --output jsonPreview without changing files:
dotbot-go -c install.conf.yaml --dry-runRun only link tasks:
dotbot-go -c install.conf.yaml --only linkSkip shell commands:
dotbot-go -c install.conf.yaml --except shellShow more output:
dotbot-go -vv -c install.conf.yamlDisable color:
dotbot-go -c install.conf.yaml --no-colorForce color when piping output:
dotbot-go -c install.conf.yaml --force-colorStop after the first failed directive:
dotbot-go -c install.conf.yaml --exit-on-failuredotbot-go will not overwrite a normal file or directory by default.
If a destination already exists:
- use
backup: trueto rename the existing file before linking - use
force: trueonly when you intentionally want to remove the existing path - use
relink: trueto replace an existing symlink
Example:
- link:
~/.vimrc:
path: vimrc
backup: trueIf something looks wrong, start here:
dotbot-go -c install.conf.yaml --dry-run -vvCommon problems:
| Problem | What To Check |
|---|---|
unsupported config file format |
File extension must be one of the supported extensions |
configuration file must be a list of tasks |
YAML/JSON/JSON5 should be a list, TOML should use tasks |
| Link target does not exist | Make sure the source file exists in your dotfiles repo |
| Existing file blocks a link | Add backup: true, move the file manually, or intentionally use force: true |
| Shell command fails | Run with -vv to see command output |
More detail: Troubleshooting Guide
Useful commands:
just --list
just verify
just vulncheckWithout just:
gofmt -w .
go mod tidy
golangci-lint run ./...
go test ./...
go test -race ./...
go vet ./...
GOTOOLCHAIN=go1.26.4+auto go run golang.org/x/vuln/cmd/govulncheck@latest ./...
go build -buildvcs=false -o bin/dotbot ./cmd/dotbot-goGitHub Actions tests and builds the project on pushes and pull requests. To publish a release from the GitHub UI, run the Test, Build, and Release workflow manually, enter the version, and choose release or prerelease. The workflow creates the v tag, tests and builds that tag, and publishes the GitHub Release with Linux and macOS archives plus checksums.
Tags pushed directly still publish releases. When you push a tag that starts with v, for example v0.2.1, the workflow publishes a stable GitHub Release. Tags with prerelease suffixes, such as v0.2.1-rc.1, are published as prereleases.
Example:
git tag v0.2.1
git push origin v0.2.1