@jaspermayone.com's dotfiles
1# Darwin (macOS) specific configuration
2{
3 config,
4 pkgs,
5 lib,
6 inputs,
7 hostname,
8 ...
9}:
10
11{
12 # Nix configuration
13 nix.settings.experimental-features = [
14 "nix-command"
15 "flakes"
16 ];
17
18 # Fix GID mismatch for nixbld group (new installs use 350, old used 30000)
19 ids.gids.nixbld = 350;
20
21 # Allow unfree packages
22 nixpkgs.config.allowUnfree = true;
23
24 # Primary user (required for homebrew and other user-specific options)
25 system.primaryUser = "jsp";
26
27 # System-level packages available to all users
28 environment.systemPackages = with pkgs; [
29 vim
30 git
31 inputs.agenix.packages.${pkgs.stdenv.hostPlatform.system}.default
32
33 # CLI tools (migrated from homebrew)
34 coreutils
35 moreutils
36 findutils
37 git-lfs
38 gnupg
39 gnugrep
40 openssh
41 screen
42 zsh
43 ffmpeg
44 imagemagick
45 wget
46 woff2
47
48 # Additional CLI tools
49 lazygit
50 mkcert
51 inetutils # telnet, ftp, etc.
52 watchman
53 pipx
54 pwgen
55 ninja
56 gnumake
57 ghostscript
58 bitwarden-cli
59 git-filter-repo
60 libyaml
61 fswatch
62 wireguard-tools
63 ];
64
65 # Homebrew integration
66 homebrew = {
67 enable = true;
68 onActivation = {
69 autoUpdate = true;
70 # cleanup = "zap"; # Remove unlisted packages
71 upgrade = true;
72 };
73
74 taps = [
75 "bramstein/webfonttools"
76 "charmbracelet/tap"
77 "heroku/brew"
78 "jaspermayone/tap"
79 "minio/stable"
80 "oven-sh/bun"
81 "sst/tap"
82 "stripe/stripe-cli"
83 "withgraphite/tap"
84 "dotenvx/brew"
85 ];
86
87 # CLI tools (only macOS-specific, special taps, or unavailable in nixpkgs)
88 brews = [
89 # macOS specific
90 "mas" # Mac App Store CLI
91 "libyaml" # Required for mise-installed Ruby (psych gem)
92
93 # Font tools (bramstein tap)
94 "sfnt2woff"
95 "sfnt2woff-zopfli"
96
97 # Cloud/Dev CLIs (from taps)
98 "heroku/brew/heroku"
99 "stripe/stripe-cli/stripe"
100 "vercel-cli"
101 "withgraphite/tap/graphite"
102 "sst/tap/opencode"
103 "dotenvx/brew/dotenvx"
104
105 # Charmbracelet tools
106 "charmbracelet/tap/freeze"
107 "charmbracelet/tap/crush"
108
109 # Custom/personal
110 "jaspermayone/tap/boxcar"
111 "minio/stable/mc"
112 "ruby"
113
114 # Build tools
115 "ccache"
116 "cmake"
117 "sccache"
118
119 # Languages/runtimes (specific versions)
120 "composer"
121 "openjdk"
122 "openjdk@21"
123 "rust" # Keep for toolchain management
124
125 # Databases (specific versions)
126 "mysql@8.0"
127 "postgresql@17"
128 "redis"
129 "percona-toolkit"
130 "pgvector"
131
132 # Image processing
133 "vips"
134 "graphicsmagick"
135
136 # Misc tools
137 "thefuck"
138 "trufflehog"
139 "eget"
140 "gitmoji"
141 "create-dmg"
142 ];
143
144 # GUI apps (casks) - shared across all Darwin machines
145 casks = [
146 "alacritty"
147 "bitwarden"
148 "discord"
149 "element"
150 "espanso"
151 "gcc-arm-embedded" # ARM embedded toolchain for Pico SDK
152 "google-chrome"
153 "iterm2"
154 "ngrok"
155 "obsidian"
156 "raycast"
157 "signal"
158 "slack"
159 "slack-cli"
160 "spotify"
161 ];
162
163 # Mac App Store apps (requires `mas` CLI)
164 # masApps = {
165 # "Xcode" = 497799835;
166 # };
167 };
168
169 # macOS system preferences
170 system.defaults = {
171 # Global preferences
172 NSGlobalDomain = {
173 # Mouse/scrolling
174 AppleEnableMouseSwipeNavigateWithScrolls = false;
175 AppleEnableSwipeNavigateWithScrolls = false;
176
177 # Auto-corrections
178 NSAutomaticCapitalizationEnabled = false;
179 NSAutomaticDashSubstitutionEnabled = false;
180 NSAutomaticInlinePredictionEnabled = false;
181 NSAutomaticPeriodSubstitutionEnabled = false;
182 NSAutomaticQuoteSubstitutionEnabled = false;
183 NSAutomaticSpellingCorrectionEnabled = false;
184
185 # Interface
186 AppleInterfaceStyle = "Dark";
187 AppleICUForce24HourTime = false;
188 _HIHideMenuBar = false;
189
190 # Keyboard
191 InitialKeyRepeat = 15;
192 KeyRepeat = 2;
193 ApplePressAndHoldEnabled = false;
194 AppleKeyboardUIMode = 3; # Full keyboard access
195
196 # Scrolling
197 "com.apple.swipescrolldirection" = true; # Natural scrolling
198
199 # Appearance
200 AppleShowAllExtensions = true;
201 NSTableViewDefaultSizeMode = 2;
202
203 # Units
204 AppleMeasurementUnits = "Inches";
205 AppleMetricUnits = 0;
206 AppleTemperatureUnit = "Fahrenheit";
207
208 # Window behavior
209 NSWindowResizeTime = 0.001; # Faster window resize
210 NSNavPanelExpandedStateForSaveMode = true; # Expand save panel
211 NSNavPanelExpandedStateForSaveMode2 = true;
212 PMPrintingExpandedStateForPrint = true; # Expand print panel
213 PMPrintingExpandedStateForPrint2 = true;
214 NSDocumentSaveNewDocumentsToCloud = false; # Save to disk, not iCloud
215 NSDisableAutomaticTermination = true; # Prevent auto-termination of apps
216 };
217
218 # Finder
219 finder = {
220 AppleShowAllExtensions = true;
221 AppleShowAllFiles = false;
222 CreateDesktop = true;
223 FXEnableExtensionChangeWarning = false;
224 FXPreferredViewStyle = "clmv"; # Column view
225 QuitMenuItem = true;
226 ShowPathbar = true;
227 ShowStatusBar = true;
228 _FXShowPosixPathInTitle = true;
229 # Desktop icons
230 ShowExternalHardDrivesOnDesktop = false;
231 ShowHardDrivesOnDesktop = false;
232 ShowMountedServersOnDesktop = false;
233 ShowRemovableMediaOnDesktop = false;
234 # Sorting and search
235 _FXSortFoldersFirst = true;
236 FXDefaultSearchScope = "SCcf"; # Search current folder
237 };
238
239 # Screenshots
240 screencapture = {
241 disable-shadow = true;
242 type = "png";
243 };
244
245 # Screen saver / lock
246 screensaver = {
247 askForPassword = true;
248 askForPasswordDelay = 0;
249 };
250
251 # Menu bar clock
252 menuExtraClock = {
253 Show24Hour = true;
254 ShowDayOfMonth = true;
255 ShowDayOfWeek = true;
256 ShowSeconds = false;
257 };
258
259 # Dock
260 dock = {
261 autohide = true; # Auto-hide the dock when not in use
262 autohide-delay = 0.0; # Delay before dock appears on hover (0 = instant)
263 mineffect = "scale"; # Minimize animation: "scale" or "genie"
264 minimize-to-application = false; # Minimize windows into app icon vs separate dock item
265 mru-spaces = false; # Rearrange spaces based on most recent use
266 orientation = "left"; # Dock position: "left", "bottom", or "right"
267 show-recents = false; # Show recently used apps in separate dock section
268 tilesize = 48; # Icon size in pixels
269 launchanim = false; # Animate app launch (bouncing icon)
270 expose-animation-duration = 0.1; # Mission Control animation speed (lower = faster)
271 showhidden = false; # Dim hidden app icons (Cmd+H) to show they're hidden
272 };
273
274 # Trackpad
275 trackpad = {
276 Clicking = true; # Tap to click
277 TrackpadRightClick = true;
278 TrackpadThreeFingerDrag = false; # Keep false to allow three-finger gestures (Mission Control, etc.)
279 Dragging = true;
280 };
281
282 # Spaces
283 spaces = {
284 spans-displays = false;
285 };
286
287 # Window Manager (Stage Manager)
288 WindowManager = {
289 EnableStandardClickToShowDesktop = false;
290 EnableTiledWindowMargins = false;
291 GloballyEnabled = false;
292 };
293
294 # Login window
295 loginwindow = {
296 GuestEnabled = false;
297 };
298
299 # Custom settings
300 CustomUserPreferences = {
301 # System sound
302 "com.apple.systemsound" = {
303 "com.apple.sound.uiaudio.enabled" = 0; # Disable boot sound
304 };
305
306 # Help Viewer non-floating
307 "com.apple.helpviewer" = {
308 DevMode = true;
309 };
310
311 # Disable "Are you sure you want to open this application?" dialog
312 "com.apple.LaunchServices" = {
313 LSQuarantine = false;
314 };
315
316 # Disable Resume system-wide
317 "com.apple.systempreferences" = {
318 NSQuitAlwaysKeepsWindows = false;
319 };
320
321 # Printer: quit when finished
322 "com.apple.print.PrintingPrefs" = {
323 "Quit When Finished" = true;
324 };
325
326 # Finder extras
327 "com.apple.finder" = {
328 ShowRecentTags = false;
329 OpenWindowForNewRemovableDisk = true; # Auto-open for mounted volumes
330 };
331
332 # Disk images: skip verification
333 "com.apple.frameworks.diskimages" = {
334 skip-verify = true;
335 skip-verify-locked = true;
336 skip-verify-remote = true;
337 };
338
339 # Dock spring loading
340 "com.apple.dock" = {
341 "springboard-show-duration" = 0;
342 };
343
344 # Safari
345 "com.apple.Safari" = {
346 UniversalSearchEnabled = false; # Don't send search queries to Apple
347 SuppressSearchSuggestions = true;
348 ShowFullURLInSmartSearchField = true;
349 HomePage = "about:blank";
350 IncludeDevelopMenu = true;
351 WebKitDeveloperExtrasEnabledPreferenceKey = true;
352 "com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled" = true;
353 WarnAboutFraudulentWebsites = true;
354 SendDoNotTrackHTTPHeader = true;
355 };
356
357 # Mail
358 "com.apple.mail" = {
359 AddressesIncludeNameOnPasteboard = false; # Copy addresses without name
360 NSUserKeyEquivalents = {
361 Send = "@\\U21a9"; # Cmd+Enter to send
362 };
363 DisableInlineAttachmentViewing = true;
364 };
365
366 # Terminal
367 "com.apple.terminal" = {
368 StringEncodings = [ 4 ]; # UTF-8 only
369 };
370
371 # iTerm2
372 "com.googlecode.iterm2" = {
373 PromptOnQuit = false;
374 };
375
376 # Time Machine
377 "com.apple.TimeMachine" = {
378 DoNotOfferNewDisksForBackup = true;
379 };
380
381 # Activity Monitor
382 "com.apple.ActivityMonitor" = {
383 OpenMainWindow = true;
384 ShowCategory = 0; # All processes
385 SortColumn = "CPUUsage";
386 SortDirection = 0;
387 };
388
389 # TextEdit
390 "com.apple.TextEdit" = {
391 RichText = 0; # Plain text mode
392 PlainTextEncoding = 4; # UTF-8
393 PlainTextEncodingForWrite = 4;
394 };
395
396 # Disk Utility
397 "com.apple.DiskUtility" = {
398 DUDebugMenuEnabled = true;
399 "advanced-image-options" = true;
400 };
401
402 # Mac App Store
403 "com.apple.appstore" = {
404 ShowDebugMenu = true;
405 WebKitDeveloperExtras = true;
406 };
407
408 # Software Update
409 "com.apple.SoftwareUpdate" = {
410 AutomaticCheckEnabled = true;
411 ScheduleFrequency = 1; # Daily
412 AutomaticDownload = 1;
413 CriticalUpdateInstall = 1; # Auto-install security updates
414 AutoUpdate = true;
415 };
416
417 # Don't write .DS_Store files on network or USB volumes
418 "com.apple.desktopservices" = {
419 DSDontWriteNetworkStores = true;
420 DSDontWriteUSBStores = true;
421 };
422
423 # Photos: don't open automatically
424 "com.apple.ImageCapture" = {
425 disableHotPlug = true;
426 };
427
428 # Messages
429 "com.apple.messageshelper.MessageController" = {
430 SOInputLineSettings = {
431 automaticQuoteSubstitutionEnabled = false;
432 };
433 };
434 "com.apple.messages.text" = {
435 NSAutomaticSpellingCorrectionEnabled = false;
436 };
437 };
438 };
439
440 # Activation scripts for settings that can't be done declaratively
441 # Note: these run as root during activation
442 system.activationScripts.extraActivation.text = ''
443 # Symlink nix tools to homebrew bin for GUI app compatibility
444 ln -sf /run/current-system/sw/bin/bw /opt/homebrew/bin/bw
445 ln -sf /run/current-system/sw/bin/git /opt/homebrew/bin/git
446
447 # Symlink LibreOffice CLI tool
448 ln -sf /Applications/LibreOffice.app/Contents/MacOS/soffice /opt/homebrew/bin/libreoffice
449
450 # Show ~/Library folder (for primary user)
451 chflags nohidden /Users/jsp/Library
452
453 # Show /Volumes folder
454 chflags nohidden /Volumes
455
456 # Power management settings
457 # Wake on lid open
458 pmset -a lidwake 1
459 # Display sleep: 15 min on power, 5 min on battery
460 pmset -c displaysleep 15
461 pmset -b displaysleep 5
462 # Disable sleep while charging (system sleep never on AC)
463 pmset -c sleep 0
464 # 24-hour delay before standby (in seconds: 86400)
465 pmset -a standbydelay 86400
466
467 # Enable HiDPI display modes
468 defaults write /Library/Preferences/com.apple.windowserver DisplayResolutionEnabled -bool true
469 '';
470
471 # Enable Touch ID for sudo
472 security.pam.services.sudo_local.touchIdAuth = true;
473
474 # Create /etc/zshrc that loads nix-darwin environment
475 programs.zsh.enable = true;
476
477 # Fonts
478 fonts.packages = with pkgs; [
479 nerd-fonts.jetbrains-mono
480 nerd-fonts.fira-code
481 ];
482
483 # Used for backwards compatibility
484 system.stateVersion = 4;
485}