Skip to content

ADR 003 — Symlinked dotfiles with backup (optional chezmoi) ​

Status ​

Accepted

Context ​

Configuration files (zsh, starship, ssh, vim, VS Code, git, opencode) must stay in sync with the repository so the repo is the single source of truth. A copy-based approach drifts: edit the live file and the repo copy is stale, or edit the repo and nothing changes until the next sync. The setup must also never silently destroy a hand-written config that already exists on the machine.

Decision ​

Manage dotfiles as symlinks from the repository into $HOME, created by a single ensure_symlink primitive. It detects a correct existing link (no-op), replaces a wrong one, and backs up any real file to <target>.backup.<timestamp> before linking. A missing source is a logged error, not a crash. chezmoi is supported as an optional extra layer (chezmoi apply) when present, but is never required.

Consequences ​

  • Pros: Editing the repo copy is instantly live. Re-runs are true no-ops when links are already correct. User data is never destroyed — it is moved aside with a timestamp. The primitive is reused for every managed file, so behaviour is uniform.
  • Cons / trade-offs: Symlinks can confuse tools that resolve real paths, and a broken repo path breaks every link at once. Backups accumulate over time and are never cleaned up. The optional chezmoi layer adds a second, overlapping mechanism that can be confusing if both manage the same file.
  • Alternatives rejected: Copying files (drift, no live edits), a bare Git repo checked out over $HOME (fragile, easy to clobber untracked files), or making chezmoi mandatory (an extra hard dependency for a job symlinks already do).