Skip to main content

Manage dotfiles: register configs, bootstrap symlinks, and keep everything in sync.

Project description

dotgarden

Manage dotfiles by moving them into a git-tracked repo and pointing $HOME at the repo-managed copies. dotfile register relocates a live config into the repo and leaves a symlink behind; dotfile bootstrap replays those symlinks (plus OS/profile variants) on any machine. Ships the dotfile CLI.

dotfile status output showing managed symlinks grouped by category

Install

uv tool install dotgarden
# or
pipx install dotgarden
# or
pip install dotgarden

Quick start

Clone the dotgarden-template repo — a working dotfiles layout that exercises every dotfile feature.

git clone https://github.com/andrewlook/dotgarden-template.git ~/dotfiles
cd ~/dotfiles
dotfile bootstrap --os macos        # or --os linux

What's in the template

dotfiles/
├── .gitconfig                      root dotfile → ~/.gitconfig
├── .macos.gitconfig                OS variant, sourced via ~/.gitconfig.local
├── .linux.gitconfig
├── .zprofile
├── .macos.zprofile
├── .tmux.conf
├── .config/                        auto-symlinked 1:1 into ~/.config/
│   ├── fish/
│   │   ├── config.fish
│   │   └── config.macos.fish       nested variant (BASE.MOD.EXT)
│   └── ghostty/
│       └── config
├── _cursor/                        registered: target lives outside ~/.config/
│   ├── settings.json
│   └── keybindings.json
├── __registry__.yaml
└── bootstrap.sh                    curl-pipe-sh installer for new machines

Everything at the repo root (.gitconfig, .zprofile, …) and every top-level child of .config/ is placed by convention. The registry handles the rest — here, just Cursor, whose real target path is nowhere near ~/.config/:

# __registry__.yaml
os: [macos, linux]
profiles: [work, home]

cursor:
  macos:
  - _cursor/settings.json: ~/Library/Application Support/Cursor/User/settings.json
  - _cursor/keybindings.json: ~/Library/Application Support/Cursor/User/keybindings.json

What bootstrap produces

$ dotfile bootstrap --os macos
  common
    ✓ ~/.gitconfig        ->  ~/dotfiles/.gitconfig
    ✓ ~/.macos.gitconfig  ->  ~/dotfiles/.macos.gitconfig
    ✓ ~/.zprofile         ->  ~/dotfiles/.zprofile
    ✓ ~/.config/fish      ->  ~/dotfiles/.config/fish
    ✓ ~/.config/ghostty   ->  ~/dotfiles/.config/ghostty

  registered
    ✓ ~/Library/Application\ Support/Cursor/User/settings.json
        ->  ~/dotfiles/_cursor/settings.json

  local
    ✓ ~/.gitconfig.local
    ✓ ~/.config/fish/config.fish.local

✓ Bootstrap complete (8 created)

$HOME is now a set of symlinks pointing back at the repo, plus a few generated .local files that source the right OS/profile variants:

$ ls -l ~/.gitconfig ~/.config/ghostty
~/.gitconfig       -> ~/dotfiles/.gitconfig
~/.config/ghostty  -> ~/dotfiles/.config/ghostty

$ cat ~/.gitconfig.local
# Auto-generated by dotfile bootstrap. Do not edit.
[include]
  path = ~/.macos.gitconfig

Edits in either location track together — they're the same inode. See GUIDE.md for the hands-on walkthrough.

Commands

Command Description
dotfile bootstrap Link files in $HOME to the repo-managed versions and generate .local include files
dotfile status Check health of all managed symlinks
dotfile register Move a config into the repo and symlink it back
dotfile unregister Remove a config from management
dotfile specialize Scaffold OS/profile variant files and wire their .local include
dotfile list List all managed files
dotfile doctor Find and remove stale symlinks
dotfile env Show current OS, profile, and overlay
dotfile ids Print entry IDs (for scripting)

dotfile bootstrap

dotfile bootstrap --os <macos|linux> [--profile <name>] [--overlay <dir>] [--dry-run]

Runs every symlink and .local generator from a clean slate. Safe to re-run.

  • --os — required on first run; remembered in ~/.dotfiles_env after.
  • --profile — activates a profile's variant files and registry entries.
  • --overlay — layers a second repo on top (see GUIDE.md § Overlay).
  • --dry-run — print the plan without touching the filesystem.
  • --skip-registry — only handle root + .config/* conventions, skip registered entries.
  • --skip-unsupported — silently skip .local generation for tool types with no known include syntax.

Existing non-symlink files at a link location are preserved as <path>.bak before being replaced.

dotfile register

dotfile register <path> [--category <name>] [--os <os>] [--profile <name>] [--name <file>] [--overlay <dir>] [--force] [--dry-run] [-y]

Moves <path> into the repo (under _<category>/ or the repo root) and creates a symlink back. Errors if the destination already exists unless you pass --force.

  • --category — target subdirectory in the repo (auto-detected from the source path if omitted).
  • --os / --profile — scope the entry so bootstrap only links it on matching machines.
  • --name — rename the file inside the repo.
  • --overlay — write into an overlay repo instead of the main one.
  • --force — overwrite an existing registration or repo file.
  • -y — skip the confirmation prompt.

dotfile specialize

dotfile specialize <os|profile> <dotfile> [--dry-run]

Scaffolds variant files for an existing base dotfile and appends the .local include line so bootstrap can generate the override file.

Works on root paths (.gitconfig) and nested paths under .config/<tool>/ (e.g. .config/fish/config.fish). Variant names come from the os: and profiles: lists in __registry__.yaml. Idempotent — safe to re-run.

Documentation

Development

See CONTRIBUTING.md for setup, testing (mise run test, ./test-docker), and the publish flow. The package layout, entry point (dotgarden.cli:main), and test harness all live in this repo — edits happen here directly.

The examples/starter/ directory is mirrored to andrewlook/dotgarden-template as the clone-ready starting point documented in Quick start above.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dotgarden-0.3.0.tar.gz (84.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dotgarden-0.3.0-py3-none-any.whl (52.6 kB view details)

Uploaded Python 3

File details

Details for the file dotgarden-0.3.0.tar.gz.

File metadata

  • Download URL: dotgarden-0.3.0.tar.gz
  • Upload date:
  • Size: 84.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dotgarden-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3432c296e34e9e266d9cbc9d7b964e0da171752616285af6c6290f8524aca77d
MD5 c5b605be77cc7968898181b972d304cf
BLAKE2b-256 d312c012473c7690fa0bdc091e4458bcc31bd38073d4150e9ceb5cd603373078

See more details on using hashes here.

Provenance

The following attestation bundles were made for dotgarden-0.3.0.tar.gz:

Publisher: publish.yml on andrewlook/dotgarden

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dotgarden-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: dotgarden-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 52.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dotgarden-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 77d8e3d4de5926350d1dac2a1b499b7993a49b59ed656c34747e46d0bec4440b
MD5 4b7c8a0f7c968cf9acf575837856a69e
BLAKE2b-256 35b335b36bb91d7b6db01e1161a59bfc23971edb8c89f9b2879778f309a67aed

See more details on using hashes here.

Provenance

The following attestation bundles were made for dotgarden-0.3.0-py3-none-any.whl:

Publisher: publish.yml on andrewlook/dotgarden

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page