Skip to content

feat: convert dotfiles to nix-darwin + home-manager#55

Open
radiosilence wants to merge 3 commits intomainfrom
nix
Open

feat: convert dotfiles to nix-darwin + home-manager#55
radiosilence wants to merge 3 commits intomainfrom
nix

Conversation

@radiosilence
Copy link
Copy Markdown
Owner

@radiosilence radiosilence commented Apr 16, 2026

Summary

  • Replace scattered zsh conf.d files and brew-managed CLI tools with declarative nix-darwin + home-manager configuration
  • Portable: macOS uses nix-darwin + home-manager, Linux uses standalone home-manager — shared modules work on both
  • Modular nix config: flake.nix entrypoint + nix/ modules for darwin, home, packages, programs, git, ssh, zsh, and file symlinks
  • Brew retained only for macOS system-integration packages (zsh, mise, pam-reattach), casks (1password, ghostty), and native libs for mise runtimes
  • Taskfile converge pipeline updated — nix:switch auto-detects platform
  • mise stays for project-level runtimes — nix handles the global CLI toolkit

Known TODOs

  • claude-code-completion zsh plugin has placeholder sha256 — needs real hash or removal
  • Test darwin-rebuild switch --flake . end-to-end on clean macOS system
  • Test home-manager switch --flake . on a Linux box
  • Verify flake.lock generation (not committed yet)

Testing from scratch (zero nix)

macOS

# 1. Install Nix
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
exec $SHELL

# 2. Switch to nix branch
cd ~/.dotfiles && git fetch origin nix && git checkout nix

# 3. First build (generates flake.lock, downloads the world — few minutes)
darwin-rebuild switch --flake ~/.dotfiles

# 4. Open a NEW terminal, then verify:
which bat        # should be /nix/store/...
starship --version
git log --oneline  # delta as pager

Linux

# 1. Install Nix
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
exec $SHELL

# 2. Clone and switch to nix branch
git clone git@github.com:radiosilence/dotfiles ~/.dotfiles
cd ~/.dotfiles && git checkout nix

# 3. First build
home-manager switch --flake ~/.dotfiles

# 4. Open a NEW terminal, then verify:
which bat
starship --version

Ongoing updates

# Update all nix inputs and rebuild
nix flake update --flake ~/.dotfiles && task converge

# Or just rebuild with current pins (auto-detects macOS vs Linux)
task converge

Eject: full revert to pre-nix dotfiles

macOS

# 1. Switch back to main
cd ~/.dotfiles && git checkout main

# 2. Uninstall Nix (Determinate installer has clean uninstall)
/nix/nix-installer uninstall

# 3. Restore brew-managed tools
brew bundle --file=~/Brewfile
task converge

# 4. Clean up dead symlinks from home-manager
find ~/.config -type l ! -exec test -e {} \; -delete
rm -rf ~/.cache/nix ~/.local/state/nix ~/.local/state/home-manager

# 5. Restart shell
exec $SHELL

Linux

# 1. Switch back to main
cd ~/.dotfiles && git checkout main

# 2. Uninstall Nix
/nix/nix-installer uninstall

# 3. Clean up dead symlinks
find ~/.config -type l ! -exec test -e {} \; -delete
rm -rf ~/.cache/nix ~/.local/state/nix ~/.local/state/home-manager

# 4. Re-converge (uses apt/dnf + mise on main)
task converge
exec $SHELL

Architecture

flake.nix
├── darwinConfigurations (macOS)
│   ├── nix/darwin.nix      ← macOS-only: system defaults, PAM, homebrew
│   └── home-manager
│       └── nix/home.nix    ← shared entry point
└── homeConfigurations (Linux)
    └── nix/home.nix        ← same shared entry point

nix/home.nix imports:
├── packages.nix    ← CLI tools (portable)
├── programs.nix    ← starship, fzf, bat, helix, etc (portable)
├── git.nix         ← git config, delta (1Password path: darwin-only)
├── ssh.nix         ← hardened SSH (portable)
├── zsh.nix         ← shell config (brew/libpq/orbstack: darwin-only)
└── files.nix       ← XDG symlinks (portable)

Test plan

  • Run darwin-rebuild switch --flake ~/.dotfiles on macOS — verify shell, git, ssh
  • Run home-manager switch --flake ~/.dotfiles on Linux — verify shell, git, ssh
  • Verify brew only installs system packages on macOS (no duplicate CLI tools)
  • Open new shell on both platforms — aliases, completions, starship, fzf-tab
  • Verify task converge works as bootstrap entrypoint on both platforms
  • Test eject path on both platforms

🤖 Generated with Claude Code

radiosilence and others added 3 commits April 16, 2026 10:34
Replace scattered zsh conf.d files and brew-managed CLI tools with
declarative nix configuration. Brew retained only for system-integration
packages (zsh, mise, pam-reattach), casks, and libs needed by mise runtimes.

- flake.nix: nix-darwin + home-manager entrypoint
- nix/: modular config (darwin, home, packages, programs, git, ssh, zsh, files)
- Taskfile.yml: updated converge pipeline — nix:switch as primary, removed old link tasks
- brewfiles.d/core.rb: trimmed to system-only packages
- config.d/zsh/conf.d/: deleted 29 files (inlined into nix/zsh.nix)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- flake.nix: add homeConfigurations for standalone home-manager on Linux
  alongside existing darwinConfigurations for macOS
- home.nix: HOMEBREW_BUNDLE_FILE only set on darwin
- git.nix: 1Password SSH signing path conditional on darwin (Linux uses
  agent or local gitconfig)
- zsh.nix: brew paths, completions fpath, libpq, OrbStack guarded behind
  lib.optionalString isDarwin — clean no-ops on Linux
- Taskfile nix:switch: auto-detects platform (darwin-rebuild vs home-manager)

Shared modules (packages, programs, ssh, files) are fully portable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant