Skip to content

connorads/dotfiles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1,623 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

dotfiles

Use git to manage dotfiles without symlinks. This setup uses a dedicated git dir at ~/git/dotfiles with work-tree ~ (via the dotfiles wrapper). Uses nix-darwin (macOS) or home-manager (Linux) and brew (macOS) to set up and install software, and mise to manage runtimes.

Quick start: curl -fsSL https://raw.githubusercontent.com/connorads/dotfiles/master/install.sh | bash β€” bootstraps macOS, Linux, or Codespaces.

⚠️ Tailored to my specific machines (usernames connor/connorads and a handful of named host configs). Forking? See Setup below for what to change (flake.nix configs + the VALID_DARWIN / VALID_HM lists in install.sh).

Why this setup

  • No symlinks: tracked files live directly in $HOME.
  • Git metadata stays out of the way in ~/git/dotfiles.
  • Bootstrap is safer on existing machines where dotfiles may already exist.
  • Day-to-day Git UX stays reliable, including ahead-behind and push state in LazyGit.

Under the hood, git metadata is stored at ~/git/dotfiles, and core.worktree points at $HOME.

Usage

If you've already got your dotfiles setup you can use the following commands to manage your dotfiles.

Updating dotfiles

Track file

First un-ignore the file/path in ~/.gitignore, then add it:

dotfiles add .somefile

Untrack file

dotfiles rm --cached .somefile

Code quality hooks (hk)

Dotfiles use hk for fast staged-file checks on commit.

dotfiles config core.hooksPath .hk-hooks
mise install
dhk check

dotfiles commit then runs .hk-hooks/pre-commit, which calls hk run pre-commit.

For shell-function regression tests:

mise run zsh-tests

Managing system

macOS (nix-darwin)

Build and activate nix-darwin config. This will make changes to the system and update packages as per flake.nix

darwin-rebuild switch --flake ~/.config/nix
# alias: drs

Update nix packages. This will update your non-homebrew packages and update flake.lock

nix flake update --flake ~/.config/nix
# alias: nfu
# You need to run build and activate after i.e. drs

Update brew packages

brew upgrade

Update mise packages

mise upgrade

Linux (home-manager)

Build and activate home-manager config. This will update packages as per flake.nix

home-manager switch --flake ~/.config/nix
# alias: hms

Update nix packages. This will update your packages and update flake.lock

nix flake update --flake ~/.config/nix
# alias: nfu
# You need to run home-manager switch after i.e. hms

Update mise packages

mise upgrade

Setup

Quick start (recommended)

If you are setting up this exact repo on macOS, Linux, or Codespaces, use the bootstrap script:

curl -fsSL https://raw.githubusercontent.com/connorads/dotfiles/master/install.sh | bash

It installs dotfiles and sets upstream tracking so git status/LazyGit show ahead-behind correctly.

Fresh machine β€” selecting the host config. The script activates a specific config (nix-darwin on macOS, home-manager on Linux), normally resolved from the machine's hostname. On a freshly reset/provisioned box the hostname rarely matches yet, so:

  • Set the override env var to pick explicitly:
    • macOS: DARWIN_HOST=Connors-Mac-mini (or Connors-MacBook-Air)
    • Linux: HM_HOST=dev (or penguin / rpi5)
  • …or answer the interactive prompt. For the prompt to get a terminal, prefer bash <(curl -fsSL …/install.sh) or download-then-run over a bare curl … | bash pipe.
  • Picking the wrong host is refused rather than silently applied; an unknown/undecidable host fails loudly with the valid list.

The first activation passes the config explicitly (--flake …#<attr>) and then converges the hostname (macOS via networking.hostName, Linux via hostnamectl). After that, bare drs/hms/up resolve the right config from the hostname with no #attr needed.

The valid host names are hardcoded in install.sh (VALID_DARWIN / VALID_HM) β€” keep them in sync with flake.nix if you add or rename a config.

Manual setup (from this repo)

If you want to follow the manual path (or fork this repo), use this.

  1. Clone using a separate git dir

    DOTFILES_REPO=https://github.com/connorads/dotfiles.git
    DOTFILES_DIR=$HOME/git/dotfiles
    BOOTSTRAP_WORKTREE=$(mktemp -d "$HOME/.dotfiles-bootstrap.XXXXXX")
    
    git clone --separate-git-dir="$DOTFILES_DIR" "$DOTFILES_REPO" "$BOOTSTRAP_WORKTREE"
    rm -rf "$BOOTSTRAP_WORKTREE"

    Why the temporary BOOTSTRAP_WORKTREE dir? git clone needs a checkout target path, and $HOME is non-empty. The temp dir keeps bootstrap safe and disposable.

  2. Point the repo at $HOME and ensure tracking refs

    git --git-dir="$DOTFILES_DIR" config core.bare false
    git --git-dir="$DOTFILES_DIR" config core.worktree "$HOME"
    git --git-dir="$DOTFILES_DIR" config --replace-all remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
    git --git-dir="$DOTFILES_DIR" fetch origin --prune
  3. Check out dotfiles into $HOME (⚠️ this overwrites conflicting files)

    git --git-dir="$DOTFILES_DIR" checkout 2>&1 | sed -n 's/^[[:space:]]\+//p' | while IFS= read -r file; do
      if [ -f "$file" ]; then
        mv "$file" "$file.bak"
      fi
    done
    
    git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" checkout -f
  4. Set upstream for the current branch

    CURRENT_BRANCH=$(git --git-dir="$DOTFILES_DIR" symbolic-ref --quiet --short HEAD)
    git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" branch --set-upstream-to="origin/$CURRENT_BRANCH" "$CURRENT_BRANCH"
  5. Set up nix, brew and install software

    macOS (nix-darwin):

    # Install Homebrew
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    eval "$(/opt/homebrew/bin/brew shellenv)"
    
    # Install Nix (vanilla, not Determinate Nix)
    curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --determinate false
    . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
    
    # Build and activate nix-darwin configuration
    nix run nix-darwin/master#darwin-rebuild -- switch --flake ~/.config/nix

    Linux (home-manager):

    # Install Nix (vanilla, not Determinate Nix)
    curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --determinate false
    . ~/.nix-profile/etc/profile.d/nix.sh
    
    # Build and activate home-manager configuration
    nix run home-manager/master -- switch --flake ~/.config/nix
  6. Reload your shell

    exec zsh

Migration helper (if needed)

If an existing machine has an older setup, run:

DOTFILES_DIR=$HOME/git/dotfiles
if [ "$(git --git-dir=$DOTFILES_DIR rev-parse --is-bare-repository 2>/dev/null || true)" = "true" ]; then
  git --git-dir=$DOTFILES_DIR config --unset core.bare || true
fi
git --git-dir=$DOTFILES_DIR config core.worktree $HOME
CURRENT_BRANCH=$(git --git-dir=$DOTFILES_DIR/ symbolic-ref --quiet --short HEAD)
git --git-dir=$DOTFILES_DIR/ config --replace-all remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git --git-dir=$DOTFILES_DIR/ fetch origin --prune
git --git-dir=$DOTFILES_DIR/ --work-tree=$HOME branch --set-upstream-to=origin/$CURRENT_BRANCH $CURRENT_BRANCH

Create from scratch (optional)

This section is for anyone who wants to build their own dotfiles repo using the same git-dir + work-tree technique (not specifically this repo).

Show from-scratch setup
  1. Create the git dir and point work-tree at $HOME

    DOTFILES_DIR=$HOME/git/dotfiles
    mkdir -p "$DOTFILES_DIR"
    git init "$DOTFILES_DIR"
    git --git-dir="$DOTFILES_DIR" config core.worktree "$HOME"
    git --git-dir="$DOTFILES_DIR" config --replace-all remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
  2. Add a safe default ignore policy (ignore everything, then un-ignore specific files)

    touch "$HOME/.gitignore"
    grep -qxF '/*' "$HOME/.gitignore" || printf '%s\n' '/*' >> "$HOME/.gitignore"
    grep -qxF '!.gitignore' "$HOME/.gitignore" || printf '%s\n' '!.gitignore' >> "$HOME/.gitignore"
  3. Start tracking files by un-ignoring paths in ~/.gitignore, then adding them

    git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" add .gitignore
    git --git-dir="$DOTFILES_DIR" --work-tree="$HOME" commit -m "chore(dotfiles): initialise from scratch"
  4. Optional: connect a remote and push

    [email protected]:your-user/dotfiles.git
    dotfiles remote add origin "$DOTFILES_REPO"
    dotfiles push -u origin HEAD

Setup YubiKey for sudo

macOS sudo auth is configured in darwin.nix:

  • Touch ID is enabled for both Macs
  • pam_reattach is enabled so Touch ID works inside tmux
  • pam_u2f remains in the sudo PAM stack for YubiKey auth

In practice:

  • MacBook Air uses Touch ID first, with YubiKey as fallback
  • Mac mini falls through to YubiKey unless it has a Touch ID-capable keyboard

The YubiKey mapping file is local per machine and is not tracked in dotfiles:

mkdir ~/.config/Yubico
pamu2fcfg > ~/.config/Yubico/u2f_keys

Add a second key if you like

pamu2fcfg -n >> ~/.config/Yubico/u2f_keys

Credit

Inspired by

About

@connorads dotfiles 🟒

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors