{ config, lib, pkgs, globalInputs, system, ... }: let leader = "cmd"; # Change this to experiment with different leader keys (e.g., "cmd", "ctrl") in { # Claude Code Package Override for Corporate Work Environment # # This overlay overrides the default claude-code package specifically for work environments # where corporate network restrictions may prevent access to npm registry distributions. # # Context: # - The default claude-code package (used in home environments) fetches from npm registry # - Corporate firewalls and security policies often block npm registry access # - Our custom claude-code package uses Google Cloud Storage distribution as a workaround # - This maintains the same package name across environments while adapting to network constraints # # Environment-specific behavior: # - Home environments: Use standard npm-distributed claude-code package # - Work environments: Use custom binary-distributed claude-code package from GCS # # This approach ensures consistent tooling availability regardless of network environment # while respecting corporate security policies. nixpkgs.overlays = [ (final: prev: { unstable = prev.unstable // { claude-code = prev.custom.claude-code; }; }) ]; # Home Manager configuration for Darwin work laptop # Corporate-friendly setup with essential development tools home.username = lib.mkForce "johno"; home.homeDirectory = lib.mkForce "/Users/johno"; home.stateVersion = "24.05"; # System packages home.packages = with pkgs; [ autoraise google-cloud-sdk ]; # Note: ghostty installed via Homebrew (managed outside of nix) # Auto-start autoraise on login launchd.agents.autoraise = { enable = true; config = { ProgramArguments = [ "${pkgs.autoraise}/bin/AutoRaise" "-pollMillis" "50" "-delay" "2" "-focusDelay" "2" ]; RunAtLoad = true; KeepAlive = true; }; }; # Auto-start aerospace on login # NOTE: In 25.11+, this can be simplified to `programs.aerospace.launchd.enable = true` launchd.agents.aerospace = { enable = true; config = { Program = "${pkgs.aerospace}/Applications/AeroSpace.app/Contents/MacOS/AeroSpace"; RunAtLoad = true; KeepAlive = true; StandardOutPath = "/tmp/aerospace.log"; StandardErrorPath = "/tmp/aerospace.err.log"; }; }; # Override Darwin-incompatible settings from base role programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac; # Disable Home Manager from managing shell RC files # topsoil/compost will manage these files instead programs.bash.enable = lib.mkForce false; programs.zsh.enable = lib.mkForce false; # Create a local nix integration file that topsoil-managed configs can source home.file.".nix-integration.sh" = { text = '' # Source Home Manager session variables (nix paths, environment, etc.) if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then . /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh fi # Setup bash completions from nix profiles if [[ ! -v BASH_COMPLETION_VERSINFO ]] && [ -n "$NIX_PROFILES" ]; then for profile in $NIX_PROFILES; do if [ -f "$profile/etc/profile.d/bash_completion.sh" ]; then . "$profile/etc/profile.d/bash_completion.sh" break fi done fi # command-not-found handler command_not_found_handle() { local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite if [ -n "$NIX_PROFILES" ]; then for profile in $NIX_PROFILES; do if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then "$profile/bin/command-not-found" "$@" return $? fi done fi echo "$1: command not found" >&2 return 127 } ''; }; home.file.".nix-integration.zsh" = { text = '' # Source Home Manager session variables (nix paths, environment, etc.) if [ -e /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh ]; then . /etc/profiles/per-user/johno/etc/profile.d/hm-session-vars.sh fi # Setup zsh completions from nix profiles typeset -U path cdpath fpath manpath for profile in ''${(z)NIX_PROFILES}; do fpath+=($profile/share/zsh/site-functions $profile/share/zsh/$ZSH_VERSION/functions $profile/share/zsh/vendor-completions) done autoload -U compinit && compinit # command-not-found handler command_not_found_handler() { local p=/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite if [ -n "$NIX_PROFILES" ]; then for profile in ''${(z)NIX_PROFILES}; do if [ -x "$profile/bin/command-not-found" ] && [ -f "$p" ]; then "$profile/bin/command-not-found" "$@" return $? fi done fi echo "$1: command not found" >&2 return 127 } ''; }; # Keep SSH and Git disabled to avoid conflicts with work environment programs.ssh.enable = lib.mkForce false; programs.git.enable = lib.mkForce false; programs.rbw.enable = lib.mkForce false; home.shell.enableShellIntegration = true; # TODO: Move this to its own role and/or module programs.aerospace = { enable = true; userSettings.mode.main.binding = { "${leader}-slash" = "layout tiles horizontal vertical"; "${leader}-comma" = "layout accordion horizontal vertical"; "${leader}-shift-q" = "close"; "${leader}-shift-f" = "fullscreen"; "${leader}-h" = "focus left"; "${leader}-j" = "focus down"; "${leader}-k" = "focus up"; "${leader}-l" = "focus right"; "${leader}-shift-h" = "move left"; "${leader}-shift-j" = "move down"; "${leader}-shift-k" = "move up"; "${leader}-shift-l" = "move right"; "${leader}-minus" = "resize smart -50"; "${leader}-equal" = "resize smart +50"; "${leader}-1" = "workspace 1"; "${leader}-2" = "workspace 2"; "${leader}-3" = "workspace 3"; "${leader}-4" = "workspace 4"; "${leader}-5" = "workspace 5"; "${leader}-6" = "workspace 6"; "${leader}-7" = "workspace 7"; "${leader}-8" = "workspace 8"; "${leader}-9" = "workspace 9"; "${leader}-0" = "workspace 10"; "${leader}-shift-1" = "move-node-to-workspace 1"; "${leader}-shift-2" = "move-node-to-workspace 2"; "${leader}-shift-3" = "move-node-to-workspace 3"; "${leader}-shift-4" = "move-node-to-workspace 4"; "${leader}-shift-5" = "move-node-to-workspace 5"; "${leader}-shift-6" = "move-node-to-workspace 6"; "${leader}-shift-7" = "move-node-to-workspace 7"; "${leader}-shift-8" = "move-node-to-workspace 8"; "${leader}-shift-9" = "move-node-to-workspace 9"; "${leader}-shift-0" = "move-node-to-workspace 10"; "${leader}-tab" = "workspace-back-and-forth"; "${leader}-shift-tab" = "move-workspace-to-monitor --wrap-around next"; "${leader}-enter" = '' exec-and-forget osascript <<'APPLESCRIPT' tell application "Ghostty" activate tell application "System Events" keystroke "n" using {command down} end tell end tell APPLESCRIPT ''; "${leader}-shift-enter" = '' exec-and-forget osascript <<'APPLESCRIPT' tell application "Google Chrome" set newWindow to make new window activate tell newWindow to set index to 1 end tell APPLESCRIPT ''; "${leader}-shift-e" = "exec-and-forget zsh --login -c \"emacsclient -c -n\""; # Service mode: Deliberate aerospace window management "${leader}-i" = "mode service"; # Passthrough mode: Temporarily disable aerospace to use macOS shortcuts # Press Cmd-P, then use any macOS shortcut (like Cmd-K in Slack), then press Cmd-P again to exit "${leader}-p" = "mode passthrough"; }; # Service mode: For deliberate aerospace window management operations userSettings.mode.service.binding = { esc = ["reload-config" "mode main"]; r = ["flatten-workspace-tree" "mode main"]; # reset layout f = ["layout floating tiling" "mode main"]; # Toggle between floating and tiling layout backspace = ["close-all-windows-but-current" "mode main"]; "${leader}-shift-h" = ["join-with left" "mode main"]; "${leader}-shift-j" = ["join-with down" "mode main"]; "${leader}-shift-k" = ["join-with up" "mode main"]; "${leader}-shift-l" = ["join-with right" "mode main"]; }; # Passthrough mode: All shortcuts pass through to macOS # This mode has minimal bindings - just ways to exit back to main mode userSettings.mode.passthrough.binding = { esc = "mode main"; "${leader}-p" = "mode main"; # Toggle back with same key (Cmd-P) }; }; home.roles = { base.enable = true; development = { enable = true; allowArbitraryClaudeCodeModelSelection = true; }; }; imports = [ ./roles ./modules/emacs ./modules/kubectl ./modules/tmux ]; }