Too broad
App folders mix config with churn.
`~/.config`, editor folders, and agent homes often contain logs, caches, databases, generated files, and credentials next to the small files you meant to keep.
Rust-native dotfiles backup
Your config is scattered across shell files, app folders, package inventories, and a few absolute paths. `dotr` backs up the selected pieces into Git without taking over how those files are managed.
$ cargo install dotr-cli
$ dotr init ~/dotbackup --with-defaults --set-default
$ dotr add ~/.zshrc
$ dotr backup --dry-run
$ dotr backup --commit --push
$ dotr restore --dry-run ~/.config/nvim
Why
The annoying part is not copying files. It is deciding what counts as durable config, avoiding noisy app state, and keeping restore boring enough to trust.
Too broad
`~/.config`, editor folders, and agent homes often contain logs, caches, databases, generated files, and credentials next to the small files you meant to keep.
Too magical
Templates, encoded filenames, and symlink farms are powerful, but they are a lot of system for people who mainly want a private, restorable backup.
Too risky
`dotr watch` only backs up. Restore is a separate command, previewable by default, and absolute paths require an explicit allow flag.
Common commands
cargo install dotr-cli
dotr init ~/dotbackup --with-defaults --set-default
dotr keygen
dotr add ~/.config/nvim
dotr backup --dry-run
dotr backup --commit --push
dotr daemon start | status | restart | stop
dotr restore --dry-run ~/.zshrc
dotr restore --apply ~/.zshrc
dotr check
Compact config
[[path_set]]
base = "~"
items = [
".zshrc",
".gitconfig",
{ src = ".config/nvim", include = ["init.lua", "lua/**"] },
{ src = ".hermes", include = ["config.yaml", "skills/**"] },
]
[[custom_backup]]
name = "vscode"
backup = "code --list-extensions > ~/.config/vscode/extensions.txt"
paths = ["~/.config/vscode/extensions.txt"]
Security
dotr keygen creates the age identity, writes the public
recipients file, and updates dotr.toml.
dotr add --encrypt adds one selected path and stores it
as an encrypted .age file.
$ cd ~/dotbackup
$ dotr keygen
$ dotr add --encrypt ~/.ssh/config
dotr keygen creates credentials firstly:
~/.config/dotr/identity
private key
~/dotbackup/recipients
public recipient
then writes this to dotr.toml:
[encryption]
backend = "age"
recipients_file = "recipients"
identity = "~/.config/dotr/identity"
identity is the private key: treat it like a password and
keep it out of the backup Git repo. recipients is the
public age recipient and is safe to commit.
After that, encrypted path entries stay explicit and auditable:
[[path]]
src = "~/.ssh/config"
encrypt = true
Commit
The recipients file can live in the backup repository
because it only contains public age recipients.
Keep local
Keep ~/.config/dotr/identity out of Git and back it
up through a separate trusted channel.
History
If a secret was already committed as plaintext, rotate it or rewrite history before publishing the repository.
Runtime model
Use `path_set`, includes, excludes, and custom inventories.
Hash source files, skip volatile state, update `files/`.
Write metadata for restore, permissions, and encrypted entries.
Let Git carry history, diffs, remotes, and normal review habits.