Dotfiles Target Architecture Migration: Phase 1

Objective

Eliminate the “Split Brain” configuration tech debt by migrating the user’s manual dotfiles (~/dotfiles/base/) into a declarative Nix Home Manager architecture using a flattened module structure (Option C.2).

Key Files & Context

  • Current Root: ~/dotfiles/nix/home.nix (Monolithic, uses bashrcExtra to source external files).
  • Target Deletions (Eventually): ~/dotfiles/base/.bash_aliases, ~/dotfiles/base/.gitconfig, ~/dotfiles/base/.bashrc.
  • New Modules to Create: ~/dotfiles/shell.nix, ~/dotfiles/git.nix.

Implementation Steps (To be executed by refactor subagent)

1. Create git.nix

Translate the existing .gitconfig into pure Nix syntax.

{ config, pkgs, ... }:
 
{
  programs.git = {
    enable = true;
    userName = "Kevin Dockman";
    userEmail = "[email protected]";
    
    signing = {
      key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII1A1dxiXwDjWU5CplNsVUc7aiULT+BdQYDQxbA/kYVt";
      signByDefault = true;
    };
 
    extraConfig = {
      gpg.format = "ssh";
      gpg.ssh.program = "/opt/1Password/op-ssh-sign";
      core.repositoryformatversion = "0";
      core.filemode = true;
      core.bare = false;
      core.logallrefupdates = true;
      credential."https://github.com".helper = "!/usr/bin/gh auth git-credential";
      credential."https://gist.github.com".helper = "!/usr/bin/gh auth git-credential";
    };
 
    includes = [
      {
        condition = "gitdir:~/Projects/clients/dogwizard/";
        path = "~/.gitconfig-dogwizard";
      }
    ];
  };
}

2. Create shell.nix

Translate the existing bash aliases, environment variables, and functions from base/.bash_aliases and home.nix into pure Nix syntax.

{ config, pkgs, ... }:
 
{
  programs.bash = {
    enable = true;
    enableCompletion = true;
 
    shellAliases = {
      work = "ssh waycup-vm";
      vm = "ssh waycup-vm";
      box = "ssh box";
      reload = "bash ~/dotfiles/gemini/sync-obsidian-vertex.sh && source ~/.bashrc && echo \"TCI environment reloaded.\"";
      edit-config = "nano ~/.bashrc && source ~/.bashrc";
      ll = "ls -la";
      "env-check" = "echo \"Node: $(node -v)\"; echo \"NPM: $(npm -v)\"";
      "wc-kill-ag" = "pkill -f antigravity-server || pkill -f antigravity";
      "disable-extensions" = "mv ~/.gemini/extensions ~/.gemini/extensions_disabled && echo \"Extensions disabled.\"";
      "enable-extensions" = "mv ~/.gemini/extensions_disabled ~/.gemini/extensions && echo \"Extensions enabled.\"";
      cd0 = "cd ~/projects/00_core/vault";
      cd1 = "cd ~/projects/01_internal";
      cd2 = "cd ~/projects/02_labs";
      cd3 = "cd ~/projects/03_clients";
      cd4 = "cd ~/projects/04_archive";
      cdway = "cd ~/projects/03_clients/waycup";
      cddog = "cd ~/projects/03_clients/dogwizard";
      cdkdock = "cd ~/projects/03_clients/kevin-dockman";
      dot = "cd ~/dotfiles";
      gst = "git status";
      ga = "git add .";
      gc = "git commit -m";
      gp = "git push";
      gl = "git log --oneline --graph --decorate";
    };
 
    bashrcExtra = ''
      # Ensure NPM globals and Nix are prioritized
      export PATH=/home/kevindockman/.npm-global/bin:/home/kevindockman/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH
 
      # 1Password SSH Agent
      if [ -z "$SSH_AUTH_SOCK" ] && [ -S ~/.1password/agent.sock ]; then
          export SSH_AUTH_SOCK=~/.1password/agent.sock
      fi
 
      # Load 1Password Service Account for secrets
      source "$HOME/dotfiles/base/.op_service_account"
 
      # Load Gemini API Key
      [ -f "$HOME/gemini.env" ] && source "$HOME/gemini.env"
 
      # Start Polkit agent for 1Password biometric bridging (WayCup TCI)
      if [ -x /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1 ] && ! pgrep -f "polkit-gnome-authentication-agent-1" > /dev/null; then
          /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1 &
      fi
 
      # Abstracted Functions
      function p {
          local PROJECTS_DIR="$HOME/projects"
          if [ -z "$1" ]; then
              echo "📂 Current Projects in $PROJECTS_DIR:"
              ls -1 "$PROJECTS_DIR"
          else
              if [ -d "$PROJECTS_DIR/$1" ]; then
                  cd "$PROJECTS_DIR/$1"
              else
                  local match=$(find "$PROJECTS_DIR" -maxdepth 2 -type d -name "*$1*" | head -n 1)
                  [ -n "$match" ] && cd "$match" || echo "❌ Project '$1' not found."
              fi
          fi
      }
 
      function snip {
          case "$1" in
              push)
                  if [ -z "$2" ]; then echo "Usage: snip push <file>"; return 1; fi
                  gh gist create "$2" --desc "WayCup Snippet: $(basename "$2")"
                  echo "✅ Snippet pushed to GitHub Gists."
                  ;;
              pull)
                  if [ -z "$2" ]; then echo "Usage: snip pull <gist-id>"; return 1; fi
                  gh gist view "$2" --raw
                  ;;
              list)
                  gh gist list --limit 50
                  ;;
              search)
                  if [ -z "$2" ]; then echo "Usage: snip search <keyword>"; return 1; fi
                  gh gist list | grep -i "$2"
                  ;;
              *)
                  echo "Usage: snip {push|pull|list|search}"
                  ;;
          esac
      }
 
      function sys-update {
          echo "Starting System Update (Engine via Nix)..."
          if [ "$WAYCUP_MODE" = "ENGINE" ]; then
              sudo apt update && sudo apt upgrade -y
          fi
          nix-channel --update && home-manager switch
          bash ~/dotfiles/gemini/sync-obsidian-vertex.sh
      }
 
      function sync-all {
          local orig_dir="$(pwd)"
          cd $TCI_DIR || return
          echo "📥 Stashing local changes and pulling latest dotfiles..."
          git add .
          git stash
          git pull origin main --rebase
          git stash pop || echo "⚠️ No local changes to restore."
          echo "📦 Committing local changes..."
          git add .
          git commit -m "Sync: TCI update via sync-all" || true
          echo "☁️ Pushing to cloud..."
          git push origin main
          cd "$orig_dir"
          echo "✅ Sync complete!"
      }
    '';
  };
}

3. Wire into home.nix

Modify ~/dotfiles/nix/home.nix to import the new modules and strip out the old monolithic programs.bash block.

{ config, pkgs, ... }:
 
let
  username = builtins.getEnv "USER";
  homeDir = builtins.getEnv "HOME";
in
{
  imports = [
    ../shell.nix
    ../git.nix
  ];
 
  nixpkgs.config.allowUnfree = true;
 
  home.username = username;
  home.homeDirectory = homeDir;
  home.stateVersion = "24.11";
 
  home.packages = with pkgs; [
    # Core Utilities
    git tmux mosh curl wget ripgrep htop fzf jq bat unzip zip
    
    # Dev & Cloud Tools
    nodejs_22 gh google-cloud-sdk _1password-cli
    
    # Language Runtimes
    python3 go php phpPackages.composer ruby jdk17 maven gradle gcc gnumake
  ];
 
  # Temporary legacy symlinks (To be removed in Phase 2)
  home.file.".config/starship.toml".source = config.lib.file.mkOutOfStoreSymlink "${homeDir}/dotfiles/base/starship.toml";
  home.file.".ssh/config".source = config.lib.file.mkOutOfStoreSymlink "${homeDir}/dotfiles/base/.ssh/config";
 
  home.sessionVariables = {
    WAYCUP_MODE = if (username == "kevin_waycupcreative_com" || username == "kevindockman") then "ENGINE" else "REMOTE";
    TCI_DIR = "${homeDir}/dotfiles";
  };
 
  programs.starship = {
    enable = true;
    enableBashIntegration = true;
  };
 
  programs.home-manager.enable = true;
}

Verification & Testing

  1. Execute plan via subagent.
  2. Run home-manager switch manually to verify compilation.
  3. Once verified, delete base/.bash_aliases and base/.gitconfig.