Documentation

Everything you need to know about running dotkeeper.

Why dotkeeper?

If you work on multiple machines, you know the friction: code edited on the laptop but not pushed, config files that drift, dotfiles that only exist on one machine. You can solve pieces of this with git, Syncthing, or cloud sync — but each has gaps.

dotkeeper combines Syncthing's real-time P2P sync with git's versioned history into a single tool. Files sync instantly between machines. Git auto-commits on a schedule so nothing is ever lost.

Compared to alternatives

Without dotkeeperWith dotkeeper
Git aloneMust remember to commit and push. Uncommitted work doesn't sync.All files sync instantly. Git runs on autopilot.
Syncthing aloneNo version history. Deletions propagate everywhere.Git history for every change. Roll back anytime.
Cloud syncThird-party server. File locking. No git. Costs money.Peer-to-peer. No accounts. Free forever.
rsync / UnisonManual or cron-only. No real-time. No history.Real-time sync + scheduled versioned backup.

Architecture

dotkeeper embeds the Syncthing library as a Go dependency. The entire sync engine compiles into a single binary — no separate Syncthing installation needed.

Dual sync strategy

Isolated ports

PortProtocolPurpose
18384HTTPREST API (loopback only)
12000TCP + QUICSyncthing file sync
11027UDPLocal discovery

These are separate from Syncthing's default ports (8384, 22000, 21027), so dotkeeper never interferes with an existing Syncthing installation.

Three config files

FileLocationPurposeSynced?
machine.toml~/.config/dotkeeper/Local identity (name, slot)Never
config.toml~/.config/dotkeeper/Shared settings (machines, repos, ignore patterns)Via Syncthing
dotkeeper.tomlEach managed repoBreadcrumb log (machines, timestamps)Via git

Commands

Setup

dotkeeper initInitialize this machine. Creates identity, generates Syncthing keys, starts service. Flags: --name, --slot, --force.
dotkeeper join <ID>Join an existing setup. Pass the device ID from dotkeeper init on the first machine. Config syncs automatically.
dotkeeper pairRe-apply config. Adds all devices and folders to Syncthing. Run after config changes.

Repos

dotkeeper add <path>Add one or more repos to sync. Auto-detects git. Flags: --no-git, --name.
dotkeeper remove <name>Stop syncing a repo. Files are untouched, only sync is stopped.
dotkeeper syncRun git backup now on all configured repos. Pull, commit, push.

Service

dotkeeper startStart embedded Syncthing in foreground. Used by service managers.
dotkeeper stopStop the Syncthing service.
dotkeeper install-timerInstall scheduled git backup. Uses the interval from config.toml.
dotkeeper statusShow machine info, Syncthing status, repos, peers, and timer state.
dotkeeper versionPrint version and commit.

Quick start

First machine

dotkeeper init --name laptop --slot 0
dotkeeper add ~/dotfiles ~/projects/myapp
dotkeeper install-timer

Second machine

# Use the device ID shown by init on the first machine
dotkeeper join KFZZ7TP-GH5OLNL-WNSTHWQ-...
dotkeeper install-timer

After joining, the shared config syncs automatically. All repos configured on the first machine will start syncing.

Adding repos later

# On any machine — config syncs to all others
dotkeeper add ~/new-project
dotkeeper pair   # on other machines, to pick up the new repo

Platform support

OSArchitecturesService manager
Linuxamd64, arm64, armv7, 386, riscv64, ppc64le, s390xsystemd or cron
macOSamd64, arm64 (Apple Silicon)launchd
Windowsamd64, arm64, 386Task Scheduler
FreeBSDamd64, arm64cron
OpenBSDamd64, arm64cron
NetBSDamd64, arm64cron

Pre-built binaries and packages (.deb, .rpm, .apk, .pkg.tar.zst) are available for Linux architectures in every release.

Git timer configuration

The git backup schedule is set in config.toml:

[sync]
git_interval = "daily"      # hourly, daily, weekly, monthly, 2h, 6h, 12h
slot_offset_minutes = 5     # minutes between each machine's timer

Each machine gets a slot number (set during init). The timer fires at base_time + (slot * offset). With slot offset 5 and daily interval:

This prevents simultaneous pushes to the same git remote.

Ignore patterns

dotkeeper auto-generates .stignore files with sensible defaults. These are Syncthing ignore patterns — they control what Syncthing syncs, not what git tracks.

Default patterns include:

.git
*.sync-conflict-*
node_modules
__pycache__
*.pyc
*.o, *.so, *.dylib, *.exe, *.dll
*.sqlite3, *.sqlite3-journal
.DS_Store, Thumbs.db, desktop.ini
target/, dist/, build/
.idea/, .vscode/ (volatile state only)

Customize by editing the ignore list in config.toml. Changes sync to all machines.

Security

Report vulnerabilities to julian.corbet@gmail.com. See SECURITY.md for details.

Contributing

dotkeeper is AGPL-3.0 licensed. Contributions are welcome.

git clone https://github.com/julian-corbet/dotkeeper
cd dotkeeper
make test         # run 118 tests + 6 fuzz targets
make build        # build the binary

The test suite includes unit tests, fuzz tests, golden file tests, adversarial input tests, concurrent sync tests, CLI smoke tests, and error injection tests. See CONTRIBUTING.md for the full guide.