Metadata-Version: 2.4
Name: git-back-dots
Version: 0.2.3
Summary: TUI for managing git-backed configuration backups on CachyOS/Arch
Project-URL: Repository, https://github.com/boundring/git-back-dots
Author: boundring
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: backup,dotfiles,etc,git,systemd,tui
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Archiving :: Backup
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: keyring>=25.0
Requires-Dist: platformdirs>=4.0
Requires-Dist: pydantic>=2.0
Requires-Dist: rich>=13.0
Requires-Dist: textual>=3.0
Requires-Dist: tomli-w>=1.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# git-back-dots

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.

## Repository modes

**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.

```sh
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.fish
```

## Install

From PyPI (recommended):

```sh
uv tool install git-back-dots
```

That 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:

```sh
cd ~/Projects/etc/20260725/git-back-dots
uv tool install --editable .
```

For an unreleased GitHub checkout:

```sh
uv tool install git+https://github.com/boundring/git-back-dots.git
```

### Requirements

- 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 suggest`
  features; everything else is distribution-agnostic

### Shell completion and man page

```sh
gbd --install-completion          # completion for bash/zsh/fish
gbd man --install ~/.local/share/man/man1   # then: man gbd
```

`gbd man` with no options prints the manual to the terminal. `gbd --help`
and `gbd COMMAND --help` cover every subcommand.

## Commands

```sh
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 now
```

`gbd run` is the command generated systemd units execute. It commits only when
the repo is dirty, then pushes with BatchMode SSH and hard timeouts.

## Repository naming schema

| 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)          |

## Workarounds

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:

```sh
gbd workaround add my-fix --target ~/.local/lib/tool/patched.py
gbd workaround schedule my-fix   # path unit watches the live file
```

The 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.

## Packages

`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

Authentication sources are resolved in this order:

1. SSH remotes and local SSH authentication.
2. Provider PATs in the current process environment.
3. 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`.

### OAuth device flow

`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.

## Scheduling model

Per repo, git-back-dots generates:

- a delayed boot/interval timer that runs `push` after 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:

```sh
gbd schedule install NAME
systemctl --user list-timers 'gbd-*'       # user repos
systemctl list-timers 'gbd-*'              # system repos
journalctl -t git-back-dots
```

## Current limits

- 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`, TUI `l`). 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, then
  `gbd 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.

## Development

```sh
uv sync --extra dev
uv run ruff check src/ tests/
uv run pytest tests/ -q
uv build
```

## License

GPL-3.0-only. See [LICENSE](LICENSE).
