Git-backed configuration backups for CachyOS and Arch Linux.
git-back-dots discovers configuration files, groups them by package or
component, and manages git repos with a Textual terminal UI. It has a headless
runner for systemd timers, path triggers, and shutdown commits.
Discovery, the git runner, logging, scheduling, environment-token detection, snapshot repositories, package-config suggestions, workarounds, OAuth device-flow login, and the core TUI all work and are covered by tests. The provider-side remote-creation flow and branch-merge UI are not finished yet.
inplace — the git root contains the tracked files. /etc is the canonical
example: gbd run etc commits changes directly inside /etc. Use this for
system configuration trees.
snapshot — a managed repo stores copies of scattered source files under a
deterministic files/… tree. Before every commit the runner syncs each tracked
source into the snapshot; restore copies back atomically. Use this for
dotfiles and package configs that live anywhere on disk.
gbd repo add dots ~/.local/share/git-back-dots/dots --mode snapshot \
--track ~/.config/fish/config.fish --track ~/.bashrc
gbd run dots --mode commit
gbd repo restore dots ~/.config/fish/config.fishFrom PyPI (recommended):
uv tool install git-back-dotsThat installs gbd and git-back-dots into uv's tool bin directory
(~/.local/bin by default — make sure it is on your PATH).
For the checkout being developed here:
cd ~/Projects/etc/20260725/git-back-dots
uv tool install --editable .For an unreleased GitHub checkout:
uv tool install git+https://github.com/boundring/git-back-dots.git- Linux with systemd (timers/path units are how scheduled runs fire)
- git, and an SSH key or PAT for pushing to remotes
- CachyOS/Arch for the pacman-aware
scan packages/repo suggestfeatures; everything else is distribution-agnostic
gbd --install-completion # completion for bash/zsh/fish
gbd man --install ~/.local/share/man/man1 # then: man gbdgbd man with no options prints the manual to the terminal. gbd --help
and gbd COMMAND --help cover every subcommand.
gbd # launch the TUI
gbd doctor # git, systemd, ssh-key, PAT, and registry checks
gbd scan etc # discover /etc candidates and package owners
gbd scan home # discover dotfiles and ~/.config candidates
gbd scan packages # pacman-aware config suggestions per naming schema
gbd repo suggest # turn package suggestions into snapshot repos
gbd auth env # detect GITHUB_TOKEN, GH_TOKEN, CODEBERG_TOKEN
gbd auth ssh # list public keys and test provider SSH auth
gbd auth login github # OAuth device-flow login (needs --client-id or env)
gbd man # print the manual; --install DIR installs gbd.1
gbd repo list # show registered repositories
gbd run NAME --mode push
gbd workaround add NAME --target PATH # track a live patch
gbd workaround check # drift report (exit 1 when stale)
gbd workaround apply NAME # re-apply nowgbd run is the command generated systemd units execute. It commits only when
the repo is dirty, then pushes with BatchMode SSH and hard timeouts.
| Prefix | Scope | Use |
|---|---|---|
dots-<pkg> |
user | dotfiles owned by a package |
etc-<pkg> |
system | package-owned system configuration |
etc-base |
system | the whole /etc tree (inplace) |
wa-<name> |
any | workaround repos (see below) |
A workaround is a live patch applied to another tool's files — for example a
hotfix inside an installed application that its next update will clobber.
git-back-dots tracks the patched files in a dedicated snapshot repo under
~/.local/share/git-back-dots/workarounds/<name>/, generates an idempotent
apply.sh, and can re-apply automatically:
gbd workaround add my-fix --target ~/.local/lib/tool/patched.py
gbd workaround schedule my-fix # path unit watches the live fileThe path unit fires when the target changes. The runner then checks drift:
if the live file differs from the snapshot (the update clobbered the patch),
apply.sh installs the tracked copy back before committing — the repo always
records the patched state. Your own edits are safe: the runner syncs them
into the snapshot on the same pass, so intentional changes are committed, not
reverted. Disable with --no-auto and apply manually with
gbd workaround apply NAME.
apply.sh runs as the installing user (via sudo -E for --system
workarounds). It is generated from the repo and committed to git history —
review it like any other privileged script. Keep workaround repos private if
the patched files come from proprietary or third-party source.
gbd scan packages combines a well-known profile list (Emacs, KDE/Plasma,
fish, common AI CLIs, …) with an /etc sweep over everything pacman has
installed. Library, framework, and game packages are filtered out by default;
--all shows them dimmed, and ignore_packages in the config extends the
filter. AI-CLI profiles are explicit allowlists — auth tokens, session
databases, and history files are never tracked, and the pre-commit secret
scanner is the backstop.
gbd repo suggest --apply registers the suggestions as snapshot repos using
the naming schema above.
Authentication sources are resolved in this order:
- SSH remotes and local SSH authentication.
- Provider PATs in the current process environment.
- Tokens stored through the system keyring, falling back to an owner-only file.
GitHub environment variables: GITHUB_TOKEN, then GH_TOKEN.
Codeberg environment variables: CODEBERG_TOKEN, then GITEA_TOKEN.
gbd auth login github (or codeberg) walks the OAuth device flow: it
prints a one-time code and verification URL, polls until you authorize,
validates the token, stores it via the system keyring (or an owner-only file),
and registers the account. The TUI Accounts screen offers the same flow on
l. The device flow needs a public OAuth app client ID — register an OAuth
app with the provider (device flow enabled), then pass --client-id or set
GBD_GITHUB_CLIENT_ID / GBD_CODEBERG_CLIENT_ID.
gbd auth env masks token values and only prints the final four characters.
Tokens are never put in a remote URL or written to the run journal.
System services do not inherit your login environment. For root-owned
repos, use a root-owned SSH key and SSH remote. The system registry is copied
to /etc/git-back-dots/config.toml during schedule installation; it contains
repo metadata only, never PAT values.
Per repo, git-back-dots generates:
- a delayed boot/interval timer that runs
pushafter networking is available; - an optional
PathChanged=unit for selected hot files; - a shutdown service that performs a local commit only.
The shutdown unit never attempts a network push. A later timer or the next boot sends the committed change. Pushes use a 15-second limit and SSH batch mode, so they cannot request a password or hang indefinitely.
Validate the generated units before installing them:
gbd schedule install NAME
systemctl --user list-timers 'gbd-*' # user repos
systemctl list-timers 'gbd-*' # system repos
journalctl -t git-back-dots- A timer can fire while a file is mid-edit; git commits whatever bytes are on disk. Inherent to any file-based backup — prefer quiescent times (boot, shutdown, idle intervals) for system repos.
- OAuth device-flow login is wired (
gbd auth login, TUIl). It stores tokens and registers accounts, but it does not yet create provider-side remotes for you — create the empty repo on GitHub/Codeberg yourself, thengbd repo add NAME PATH --remote URL. HTTPS credential injection for git pushes is also not wired — use SSH remotes or env-var PATs for pushing. - The TUI includes dashboard, discovery, repo files/history/schedule views, accounts, logs, notifications, workarounds, and a per-file history browser with restore-from-any-version. Branch merge UI is still planned.
uv sync --extra dev
uv run ruff check src/ tests/
uv run pytest tests/ -q
uv buildGPL-3.0-only. See LICENSE.