Manage your dotfiles with symlinks and Git. No intermediary tools, no special workflows — edit your files normally and let the sync happen automatically.
- Your config files stay where they are, as symlinks pointing into a Git repo
- A background watcher detects changes and pushes them automatically (with debounce)
- On a new machine: clone your dotfiles repo, run
restore, done
Two separate repositories by design:
- dotfiles-cli (this repo): the tool, shareable, no personal config
- your dotfiles repo: your actual configs + the
links.tomlmanifest
- Python 3.11+
- Git
- systemd (for the background watcher)
git clone https://github.com/your-user/dotfiles-cli.git ~/.dotfiles-cli
~/.dotfiles-cli/install.shThe install script creates a symlink at ~/.local/bin/dotfiles. Make sure ~/.local/bin is in your PATH.
With an existing local repo:
dotfiles init --repo ~/dotfilesCloning from GitHub (new machine):
dotfiles init --clone git@github.com:your-user/dotfiles.gitinit does three things: saves the config, installs the systemd user service, and starts the watcher. After this you can forget the tool exists.
dotfiles add ~/.zshrc
dotfiles add ~/.config/nvimThe CLI suggests a destination inside the repo based on the name. You can override it interactively.
Source: ~/.config/nvim
Target: ~/dotfiles/nvim/
Confirm? [Y/n/other path]:
What happens: the file moves into the repo, a symlink is created at the original path, and it's registered in links.toml.
dotfiles restore
dotfiles restore --tag editor # only entries with that tag
dotfiles restore --force # overwrite existing files (used automatically by init --clone)Idempotent — safe to run multiple times.
dotfiles unlink ~/.zshrcRemoves the symlink, moves the file back to its original location, removes from manifest.
dotfiles status[OK] ~/.zshrc
[OK] ~/.config/nvim
[BROKEN] ~/.config/alacritty → target missing in repo
[DRIFT] repo has 2 unpushed commits
~/.config/dotfiles-cli/config.toml (created by init):
repo = "/home/user/dotfiles"
debounce_seconds = 30debounce_seconds controls how long the watcher waits after the last file change before committing. Increase it if you use autosave heavily.
links.toml lives inside your dotfiles repo and is versioned with it:
[[links]]
source = "~/.zshrc"
target = "zsh/.zshrc"
tags = ["shell"]
[[links]]
source = "~/.config/nvim"
target = "nvim/"
tags = ["editor"]The watcher runs as a systemd user service (dotfiles-watch.service). It:
- Watches the dotfiles repo directory for any changes
- Waits for inactivity (debounce) before committing
- Commits and pushes automatically
- Logs all activity to the systemd journal
journalctl --user -u dotfiles-watch -fPush failures (no network, conflicts) are logged but do not crash the watcher. It retries on the next cycle.
# One-time setup
dotfiles init --repo ~/dotfiles
# Track something new
dotfiles add ~/.config/alacritty
# Edit normally — watcher handles the rest
nvim ~/.config/alacritty/alacritty.toml
# New machine — restore runs automatically after clone
dotfiles init --clone git@github.com:you/dotfiles.git
MIT