Skip to content

Repository files navigation

dotfiles 🍩

screenshot

Personal dotfiles, managed in three layers:

  • Nix (nix/) — system configuration and packages, pinned by flake.lock and applied with a rebuild. Fully reproducible.
  • Stow (stow/) — dotfiles symlinked into $HOME with GNU Stow. Changes take effect immediately, no rebuild needed.
  • Homebrew (macOS) — GUI apps and Mac App Store apps. Nix declares which packages and a rebuild installs or removes to match, but versions are unpinned and upgraded manually.

Quickstart

Nix

Note

  • This requires having Nix installed. See the Nix README.
  • The flake.nix is designed to set up the machine based on its hostname.
# Rebuild system + packages + dotfiles (reproducible, uses flake.lock)
sudo darwin-rebuild switch --flake ~/.dotfiles#"$(hostname -s)"  # macOS
sudo nixos-rebuild switch --flake ~/.dotfiles#"$(hostname -s)"   # NixOS

# Update ALL flake inputs, then rebuild
nix flake update

# Update only the unstable-pinned inputs, then rebuild
nix flake update nixpkgs-unstable nix-darwin home-manager-unstable llm-agents

# Clean up old Nix generations, keeping the last 5 days for rollback safety
sudo nix-collect-garbage --delete-older-than 5d

Note

On macOS, home-manager's per-user activation can silently fail to apply (a known upstream launchctl asuser flakiness). The rebuild self-heals this: a guard in nix/shared/system/darwin.nix verifies the activation landed and retries it, failing loudly otherwise. See CLAUDE.md for manual verification and recovery.

Stow

Dotfiles are managed with GNU Stow, not Nix.

Note

Rebuilds run stow too. On NixOS only when the home-manager generation changed, so after editing just stow/, run dotfiles-stow.

  • Edit files in stow/ and run dotfiles-stow
  • Changes are immediately active (no rebuild needed)

Stow forbids slashes in package names, so each level is its own invocation:

Package Applies to
stow/shared/ every machine
stow/platform/{Darwin,Linux}/ matching uname -s
stow/kaizen/ the niri + Quickshell hosts (renoir, wily)
stow/host/<hostname>/ that machine only; optional

A file in a later package must not target a path an earlier one already supplies; GNU Stow reports that as a conflict rather than treating it as an override, so per-host drift means keeping that file out of the shared package entirely.

--adopt absorbs any real file that has replaced a managed symlink into the repo instead of aborting; review the result with git diff before committing.

Shell

The shell entrypoint is stow/shared/.zshrc, which sources stow/shared/.zshrc_user. The user file loads the shell configuration chain:

  1. shell/exports.sh — PATH (including shell/bin/ utils), globals, env vars
  2. shell/aliases.sh — shell aliases
  3. shell/sourcing.sh — tool initialization, plugins, completions

See Project config for details on shell initialization, direnv, and per-project tooling.

Homebrew

nix/shared/system/darwin.nix declares the Homebrew taps, brews, casks and Mac App Store apps, and a rebuild installs or removes packages to match that set (cleanup = "zap", so anything undeclared is uninstalled). Versions are not pinned — bump them deliberately:

brew update && brew upgrade   # add --greedy to also bump self-updating casks

Pinning Homebrew versions is possible via nix-homebrew with locked taps, but it buys little here: casks that self-update ignore the pin, vendors delete old cask artifacts, and Mac App Store apps cannot be pinned at all.

LLM agent CLIs (claude-code, opencode,...) are the exception: they are plain Nix packages from the llm-agents flake input, upgraded via nix flake update llm-agents + rebuild.

Other READMEs and references

About

No description or website provided.

Topics

Resources

Stars

261 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages