Symlink-based dotfiles manager with auto-sync
Project description
dotpilot
Symlink-based dotfiles manager. Your repo mirrors your home directory — no dot_ prefixes, no templates, no source state. Edit a file, it's already applied.
uvx dotpilot@latest
Requires uv. Install it with:
curl -LsSf https://astral.sh/uv/install.sh | sh
Why dotpilot?
Most dotfile managers copy files and require you to re-run a command after every edit. dotpilot symlinks — your dotfiles repo IS your home directory. Change a file in ~/dotfiles/.zshrc, and ~/.zshrc updates instantly because it's a symlink.
| dotpilot | chezmoi | GNU Stow | bare git | |
|---|---|---|---|---|
| Edits apply instantly | Yes (symlinks) | No (must re-apply) | Yes (symlinks) | Yes |
| Repo structure | Mirrors ~/ | dot_, private_, executable_ prefixes |
Mirrors ~/ | Mirrors ~/ |
| New machine setup | uvx dotpilot init |
chezmoi init |
Manual clone + stow | Manual clone |
| Dry-run by default | Yes | No | No | N/A |
| Tracks what you're NOT managing | dotpilot untracked |
No | No | No |
| Auto-sync from remote | Built-in cron | External | External | External |
| Auto-backup before apply | Yes | No | No | No |
| Templating | No | Yes (Go templates) | No | No |
| Secret management | No | Yes | No | No |
| Dependencies | Python (uv) | None (Go binary) | Perl | Git |
dotpilot trades templating and secrets for simplicity. If you need machine-specific config, use .localrc patterns or .overwrite files. If you need secrets, use a separate tool. Most people don't need either.
Quick start
# New machine — clone, then review before applying
uvx dotpilot init git@github.com:you/dotfiles.git
dotpilot apply # dry-run: shows what would change
dotpilot apply --apply # back up + symlink everything
# Day-to-day
dotpilot status # sync status (fetches from remote)
dotpilot track ~/.bashrc # start managing a file
dotpilot sync --apply # pull latest from origin
dotpilot diff # uncommitted changes
Commands
All commands default to ~/dotfiles. Override with --dotfiles DIR. Use -h on any command for help.
| Command | Description |
|---|---|
init <repo> |
Clone a dotfiles repo and dry-run apply |
apply |
Symlink dotfiles into ~/ (dry-run by default, auto-backs up on --apply) |
sync |
Fetch and fast-forward merge from origin |
track <path> |
Start tracking a file — moves it to repo, symlinks back |
untrack <path> |
Stop tracking — removes symlink, moves file back |
untracked |
List dotfiles in ~/ and ~/.config you're not managing |
status |
Git sync status — fetches remote, shows dirty/ahead/behind |
diff |
Show uncommitted changes in the dotfiles repo |
backup |
Back up all managed dotfiles from ~/ into a timestamped directory |
restore <dir> |
Restore dotfiles from a backup directory |
doctor |
Check git, repo, SSH keys, upstream config |
completion |
Install zsh completions |
uninstall |
Remove symlinks, restore files, delete the dotfiles repo |
cron |
Set up auto-sync every 30 minutes |
Every mutating command is dry-run by default. Pass --apply to execute. Add -v to apply for verbose output.
How it works
Your dotfiles live in a git repo (default ~/dotfiles). dotpilot creates symlinks from ~/ into that repo.
~/dotfiles/.zshrc ←symlink← ~/.zshrc
~/dotfiles/.config/nvim ←symlink← ~/.config/nvim
Special file conventions:
.overwritesuffix — copied instead of symlinked, for files that don't work as symlinks (e.g..config/git/gitk.overwrite).deletesuffix — removes the corresponding file from~/(e.g..vimrc.deleteremoves~/.vimrc).dotpilotignore— fnmatch patterns for files to skip (one per line,#comments)..gitignorepatterns are also respected.
Backup and restore
apply --apply automatically creates a backup before making changes. Backups are stored inside the dotfiles repo as dotfiles-backup-<timestamp>/.
dotpilot backup # manual backup
dotpilot backup -o /tmp # backup to custom location
dotpilot restore ./dotfiles-backup-* # dry-run: show what would change
dotpilot restore ./dotfiles-backup-* --apply # restore files
Restore is symlink-aware — if symlinks are still in place, it writes through them into the repo. If symlinks are gone (e.g. after uninstall), it copies directly to ~/.
Uninstall
dotpilot uninstall # dry-run: shows symlinks, cron, unpushed warnings
dotpilot uninstall --apply # restore files, remove cron, delete repo
Warns about uncommitted changes and unpushed commits before deleting anything. Removes the cron job if one is installed.
Auto-sync
The cron command installs a job that runs every 30 minutes (configurable with --schedule):
dotpilot cron # dry-run: shows what cron entry would be added
dotpilot cron --apply # install the cron job
dotpilot cron --apply --remove # remove it
The cron job runs uvx dotpilot@latest sync --apply --auto-apply, which fetches from origin, fast-forward merges, and re-applies symlinks if anything changed.
If the working directory is dirty or the merge isn't a fast-forward, sync bails out — it won't clobber your local changes.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dotpilot-0.2.0.tar.gz.
File metadata
- Download URL: dotpilot-0.2.0.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
382c64b55e99b65a71f8fffa07dd76fa9b322015e75204efa6a0435caa3a422b
|
|
| MD5 |
73f558fc4dfddeccf62282aee864eefd
|
|
| BLAKE2b-256 |
ebf112e6bfad9111c602b2627ced5e26d7c10735809c22a23e72c6cbfd9042b9
|
File details
Details for the file dotpilot-0.2.0-py3-none-any.whl.
File metadata
- Download URL: dotpilot-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
199236d5f41b5493fdb6cbe6fdb441b1e049b3d3693a1ff8b613092870acc284
|
|
| MD5 |
55f0942b01e0b3c2211e6f55a28025d2
|
|
| BLAKE2b-256 |
aefb2faaf7c36d69bceac860dda459f15d8ee19006937c2aaf88693cb35c5c98
|