-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.sh
executable file
·1595 lines (1304 loc) · 54.8 KB
/
setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# not usr/bin/env so that this stays compatible
# MacOS Setup Script
# Copyright © 2023 Riley Martine
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Script to set up a new MacOS computer for development.
# DO NOT RUN THIS without reading through it and tweaking to your liking.
# GOALS:
# - Sets up a decent development workstation.
# - Works on a fresh MacOS Ventura install, with nothing set up
# - As much as possible, does things without user intervention.
# - I am not going to write too many applescripts to click on things, PROBABLY.
# - When things need user intervention, do them as late as possible.
# - Idempotent.
# - Running twice is safe.
# - Running, then uninstalling half of the things, then running again, is safe.
# - Running, then deleting your dotfiles, then running again restores the dotfiles.
# - Running twice does not change your dotfiles more than running once.
# - For now, compatible with external dotfiles. That means everything goes in a '.d' directory
# so that I can pull other dotfiles without overwriting, and don't clutter my own with
# tool-specific config. (e.g. pyenv path)
# - Eventually, the script will regenerate my preferred dotfiles from scratch.
# - Passes shellcheck with no warnings or errors
# NON-GOALS:
# - All things to all people. This is highly opionated; it is how I want MY workstation set up.
# It WILL mess with preferences you want one way. It WILL have opinions about how you should
# organize things you don't agree with. It WILL install applications and utilities you have
# no use for.
# - Eventually, I may twiddle this to be super configurable, because maybe not everyone wants
# three jdks. This would be a large rewrite, but make it useful in the base form.
# - The goal for this would be: Does not mutate computer state without making sure the user
# understands exactly what would happen, and the user is able to confirm/deny each choice.
# - Being pretty (this will come later)
# - An update script. There are sections that run updates; this script should not be run in order
# to update the things it installs. (that will come later)
# - Modular; while linear, dependency relations are not encoded as a proper DAG.
# Delete sections at your own risk.
# You may have to run this script several times to work through all the updates.
# For developing, a pretty good method of figuring out preferences is:
# 1) Find the "domain" you're operating in (com.apple.Dock)
# 2) `defaults read <domain> > before`
# 3) Edit the preferences for that thing
# 4) `defaults read <domain> > after`
# 5) `diff before after`
# You can also omit the domain to get ALL the values. Sometimes you need the -currentHost flag,
# sometimes you need to run with sudo.
# More useful generic tips for plist munging here:
# https://apple.stackexchange.com/questions/79761/editing-system-preferences-via-terminal
# alias plist='plutil -convert xml1 -o /dev/stdout'
# Bits taken from anywhere linked, and the following:
# https://sourabhbajaj.com/mac-setup/SystemPreferences/
# https://macos-defaults.com/#💻-list-of-commands
# https://www.stuartellis.name/articles/mac-setup/
# https://www.robinwieruch.de/mac-setup-web-development/
# https://github.com/pivotal/workstation-setup/blob/main/setup.sh
# https://github.com/geerlingguy/dotfiles/blob/master/.osx
# https://github.com/mathiasbynens/dotfiles/blob/main/.macos
# https://github.com/thoughtbot/laptop/blob/main/mac
#
# TODO impl https://git.herrbischoff.com/awesome-macos-command-line/about/
set -euo pipefail
if [[ $EUID -eq 0 ]]; then
echo "This script should not be run as root."
exit 1
fi
echo "Caching password..."
sudo -K
sudo true
###################
# Functions #
###################
# https://unix.stackexchange.com/questions/71253/what-should-shouldnt-go-in-zshenv-zshrc-zlogin-zprofile-zlogout
# zsh:
# .zshenv is sourced for scripts (non-login, non-interactive shells, e.g. zsh -c 'command')
# .zshenv and .zshrc are sourced for interactive shells (e.g. just typing zsh)
# .zprofile is sourced for login shells. You only get login shells on MacOS if you pop a new terminal tab or window.
# https://unix.stackexchange.com/questions/119627/why-are-interactive-shells-on-osx-login-shells-by-default
# bash:
# the file specified by $BASH_ENV is sourced for scripts (bash -c 'command', ./test.sh)
# .bashrc is sourced for interactive, non-login shells (popping a subshell with bash)
# .bash_profile is sourced for login shells. You only get login shells on MacOS if you pop a new terminal tab or window.
# https://fishshell.com/docs/current/faq.html#how-do-i-run-a-command-every-login-what-s-fish-s-equivalent-to-bashrc-or-profile
# fish:
# ~/.config/fish/config.fish is always sourced. To make something only run for interactive shells, use:
# if status is-interactive
# fish also sources everything in ~/.config/fish/conf.d/*.fish, in lexical sort order.
# exporting an env var makes it available to all subshells. e.g. setting PATH in .zshrc allows it to be read from a bash script called from an interactive zshell.
# TODO finish section
# https://gist.github.com/ptc-mrucci/61772387878ed53a6c717d51a21d9371
# some
SCRIPT_PATH="$(readlink -f "$0")"
SCRIPT_DIR=$( dirname "$SCRIPT_PATH" )
export PATH="$SCRIPT_DIR/bin:$PATH"
source "$SCRIPT_DIR/setup.d/utils.sh"
# https://www.dzombak.com/blog/2021/11/macOS-Scripting-How-to-tell-if-the-Terminal-app-has-Full-Disk-Access.html
if ! plutil -lint /Library/Preferences/com.apple.TimeMachine.plist > /dev/null; then
echo "This script requires granting Terminal.app (or whatever terminal it is running in) Full Disk Access permissions."
echo "Please navigate to System Preferences -> Security & Privacy -> Full Disk Access and check the box for Terminal."
echo "Once you've done so, quit and reopen Terminal and re-run this script."
exit 1
fi
echo "Detecting system properties..."
if [ "$(arch)" = "arm64" ]; then
echo "This script is running on Apple silicon (ARM)."
arm=true
else
echo "This script is running an intel processor (x86)."
arm=false
fi
echo "Done detecting system properties."
echo "Updating MacOS..."
softwareupdate -i -a
add-update macos 'softwareupdate -i -a'
echo "Closing system preferences..."
osascript -e 'tell application "System Preferences" to quit'
echo "Disabling boot sound..."
sudo nvram SystemAudioVolume=" "
echo "Enabling MacOS auto-update..."
defaults write com.apple.SoftwareUpdate ScheduleFrequency -int 1
defaults write com.apple.SoftwareUpdate CriticalUpdateInstall -int 1
sudo defaults write \
/Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled \
-bool TRUE
sudo defaults write \
/Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload \
-bool TRUE
sudo defaults write \
/Library/Preferences/com.apple.SoftwareUpdate \
AutomaticallyInstallMacOSUpdates \
-bool TRUE
# App store auto-update
sudo defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate \
-bool TRUE
echo "Installing developer tools..."
if ! pkgutil --pkg-info=com.apple.pkg.CLTools_Executables > /dev/null; then
echo "Please select 'Yes' on the prompt."
xcode-select --install
echo "Press any key when done."
read -r
fi
if [ $arm = true ]; then
echo "Installing rosetta..."
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
echo "Done installing rosetta."
fi
echo "Enabling FileVault..."
if [ "$(sudo fdesetup status)" = "FileVault is Off." ]; then
# fdesetup scares me. Make user do it manually.
echo "Please enable filevault."
open /System/Library/PreferencePanes/Security.prefPane
read -rp "Press any key once complete."
fi
echo "Installing homebrew..."
if ! which brew; then
NONINTERACTIVE=1 HOMEBREW_NO_ANALYTICS=1 /bin/bash -c \
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
echo "Disabling homebrew analytics..."
brew analytics off
echo "Updating homebrew..."
brew update
echo "Installing homebrew services..."
brew tap homebrew/services
# echo "Cleaning up homebrew installation..."
# brew cleanup
append ~/.zshrc '# Set PATH, MANPATH, etc., for Homebrew.'
append ~/.zshrc 'eval "$(/opt/homebrew/bin/brew shellenv)"'
append ~/.bash_profile 'if [ -f ~/.bashrc ]; then . ~/.bashrc; fi'
append ~/.bashrc '# Set PATH, MANPATH, etc., for Homebrew.'
append ~/.bashrc 'eval "$(/opt/homebrew/bin/brew shellenv)"'
mkdir -p ~/.config/fish/conf.d/
append ~/.config/fish/conf.d/00_brew.fish 'eval (/opt/homebrew/bin/brew shellenv)'
eval "$(/opt/homebrew/bin/brew shellenv)"
add-update homebrew 'brew update
brew upgrade
brew upgrade --cask --greedy'
"$SCRIPT_DIR/setup.d/touch-id-sudo.sh"
echo "Setting screenshots as jpg and not png, for smaller file size..."
# TODO nvm?
defaults write com.apple.screencapture type png
echo 'Disabling opening previous previewed files (e.g. PDFs) when opening a new one'
defaults write com.apple.Preview ApplePersistenceIgnoreState YES
echo "Showing ~/Library and /Volumes folders..."
chflags nohidden ~/Library
xattr -d com.apple.FinderInfo ~/Library || true
sudo chflags nohidden /Volumes
# https://apple.stackexchange.com/questions/408716/setting-safari-preferences-from-script-on-big-sur
echo "Configuring Safari settings..."
echo "Disabling websites prompting to allow notifications..."
defaults write com.apple.Safari CanPromptForPushNotifications -bool FALSE
echo 'Setting find-in-page to "Contains Match" rather than "Starts with Match"...'
defaults write com.apple.Safari FindOnPageMatchesWordStartsOnly -bool false
echo 'Disabling history auto-erasing (default 1 year)...'
sudo defaults write com.apple.Safari HistoryAgeInDaysLimit -int 365000
echo "Showing the full URL in the address bar (note: this still hides the scheme)..."
sudo defaults write com.apple.Safari ShowFullURLInSmartSearchField -bool TRUE
echo "Showing URLs on hover..."
defaults write com.apple.Safari ShowStatusBar -bool TRUE
echo "Enabling restore of last session on re-launch..."
defaults write com.apple.Safari AlwaysRestoreSessionAtLaunch -bool TRUE
echo "Setting Safari's home page to 'about:blank' for faster loading..."
defaults write com.apple.Safari HomePage -string "about:blank"
echo "Enabling extenstion auto-update..."
defaults write com.apple.Safari InstallExtensionUpdatesAutomatically -bool TRUE
echo "Switching default search provider to DuckDuckGo..."
defaults write com.apple.Safari SearchProviderShortName 'DuckDuckGo'
echo "Disabling some weasel-worded tracking code..."
defaults write com.apple.Safari "WebKitPreferences.privateClickMeasurementEnabled" -bool FALSE
echo "Enabling developer options..."
defaults write com.apple.Safari IncludeDevelopMenu -bool TRUE
defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool TRUE
defaults write com.apple.Safari "WebKitPreferences.developerExtrasEnabled" -bool TRUE
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true
defaults write NSGlobalDomain WebKitDeveloperExtras -bool true
defaults write com.apple.Safari IncludeInternalDebugMenu -bool true
echo "Disabling auto-open of files..."
defaults write com.apple.Safari AutoOpenSafeDownloads -bool FALSE
echo "Disabling preloading top hit & safari suggestions so apple doesn't get them..."
defaults write com.apple.Safari PreloadTopHit -bool FALSE
defaults write com.apple.Safari UniversalSearchEnabled -bool FALSE
defaults write com.apple.Safari SuppressSearchSuggestions -bool true
echo "Hiding bookmarks bar..."
defaults write com.apple.Safari ShowFavoritesBar -bool false
echo "Hiding sidebar in top sites..."
defaults write com.apple.Safari ShowSidebarInTopSites -bool false
echo "Disabling auto-fill..."
defaults write com.apple.Safari AutoFillFromAddressBook -bool false
defaults write com.apple.Safari AutoFillPasswords -bool false
defaults write com.apple.Safari AutoFillCreditCardData -bool false
defaults write com.apple.Safari AutoFillMiscellaneousForms -bool false
echo "Warning about fraudulent websites..."
defaults write com.apple.Safari WarnAboutFraudulentWebsites -bool true
echo "Disabling autoplay..."
defaults write com.apple.Safari WebKitMediaPlaybackAllowsInline -bool false
defaults write com.apple.SafariTechnologyPreview WebKitMediaPlaybackAllowsInline -bool false
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2AllowsInlineMediaPlayback -bool false
defaults write com.apple.SafariTechnologyPreview com.apple.Safari.ContentPageGroupIdentifier.WebKit2AllowsInlineMediaPlayback -bool false
echo "Enabling do-not-track..."
defaults write com.apple.Safari SendDoNotTrackHTTPHeader -bool true
echo "Done configuring Safari settings."
echo "Expanding save panel by default..."
defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true
defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true
echo "Expanding print panel by default..."
defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true
defaults write NSGlobalDomain PMPrintingExpandedStateForPrint2 -bool true
echo "Setting printer app to quit once print jobs complete..."
defaults write com.apple.print.PrintingPrefs "Quit When Finished" -bool true
echo "Displaying control characters in default views..."
# Try e.g. `cd /tmp; unidecode "\x{0000}" > cc.txt; open -e cc.txt`
defaults write NSGlobalDomain NSTextShowsControlCharacters -bool true
echo "Showing all processes in Activity Monitor..."
defaults write com.apple.ActivityMonitor ShowCategory -int 0
echo "Setting up AdGuard DNS servers..."
# We do this in a weird way so we get DNS-over-HTTPS.
# "networksetup -setdnsservers Wi-Fi servers" would work if we didn't need that.
# Using AdGuard for grapheneos' reasoning:
# https://grapheneos.org/faq#ad-blocking
# > Apps and web sites can detect that ad-blocking is being used and can determine what's being blocked. This can be used as part of fingerprinting users. Using a widely used service like AdGuard with a standard block list is much less of an issue than a custom set of subscriptions / rules, but it still stands out compared to the default of not doing it.
# We'll still do browser-local content blocking as well though. But not for safari, I don't use it much.
# Safari makes actual content blocking hard. See:
# https://github.com/el1t/uBlock-Safari/issues/158
if profiles show | grep -qe "dns.adguard-dns.com"; then
echo "DNS profile already installed, nothing to do."
else
echo "DNS profile not yet installed."
profile_path="$(curl -X POST https://api.adguard-dns.io/public_api/v1/dns/mobile_config --data '{"dns_proto_type":"DOH","filtering_type":"DEFAULT"}' -H 'Content-Type: application/json' | sed -n 's/^{"download_link":"\(.*\)"}$/\1/p')"k
curl "https://api.adguard-dns.io${profile_path}" > adguard-dns.mobileconfig
open /System/Library/PreferencePanes/Profiles.prefPane adguard-dns.mobileconfig
echo "Manual intervention required. Please install profile. Press any key to continue."
read
rm adguard-dns.mobileconfig
echo "Flushing DNS cache..."
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
fi
echo "Always showing scroll bars, instead of just when scrolling..."
defaults write NSGlobalDomain AppleShowScrollBars -string "Always"
echo "Enabling tap-to-click..."
# https://osxdaily.com/2014/01/31/turn-on-mac-touch-to-click-command-line/
defaults write com.apple.AppleMultitouchTrackpad Clicking -bool TRUE
sudo defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool TRUE
sudo defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1
sudo defaults write NSGlobalDomain com.apple.mouse.tapBehavior -int 1
echo "Setting dock to auto-hide..."
defaults write com.apple.Dock autohide -bool TRUE
killall Dock
echo "Putting screenshots in ~/Screenshots..."
mkdir -p ~/Screenshots
defaults write com.apple.screencapture location "$HOME/Screenshots/"
killall SystemUIServer
echo "Preventing Photos from opening on volume connected..."
defaults -currentHost write com.apple.ImageCapture disableHotPlug -bool true
echo "Setting language and locale..."
defaults write NSGlobalDomain AppleLanguages -array "en-US"
defaults write NSGlobalDomain AppleLocale -string "en_US"
sudo systemsetup -settimezone 'America/Denver' > /dev/null
echo "Configuring Finder..."
echo "Setting new window to open to home directory..."
# note "finder" not "Finder"
defaults write com.apple.finder NewWindowTarget -string "PfHm"
defaults write com.apple.finder NewWindowTargetPath -string "file://$HOME/"
echo "Showing all extensions..."
defaults write NSGlobalDomain "AppleShowAllExtensions" -bool TRUE
echo "Not prompting on extension change..."
defaults write com.apple.finder FXEnableExtensionChangeWarning -bool FALSE
echo "Disabling iCloud bits..."
defaults write com.apple.finder FXEnableRemoveFromICloudDriveWarning -bool FALSE
defaults write NSGlobalDomain "NSDocumentSaveNewDocumentsToCloud" -bool FALSE
echo "Showing hidden files..."
defaults write com.apple.finder "AppleShowAllFiles" -bool "true"
echo "Deleting trash after 30 days..."
defaults write com.apple.finder FXRemoveOldTrashItems -bool TRUE
echo "Setting default view to columns..."
defaults write com.apple.finder "FXPreferredViewStyle" -string "clmv"
echo "Keeping folders on top for sorting..."
defaults write com.apple.finder "_FXSortFoldersFirst" -bool "true"
defaults write com.apple.finder "_FXSortFoldersFirstOnDesktop" -bool "true"
echo "Setting default search scope to current folder, instead of system-wide..."
defaults write com.apple.finder FXDefaultSearchScope -string "SCcf"
echo "Not creating .DS_Store files on network volumes or USB stores..."
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true
echo "Showing full path in title bar..."
defaults write com.apple.finder '_FXShowPosixPathInTitle' -bool true
echo "Enabling Command-Q to quit..."
defaults write com.apple.finder QuitMenuItem -bool true
echo "Hiding tags..."
defaults write com.apple.finder ShowRecentTags -bool FALSE
echo "Modifying Favorites..."
brew-get --cask mysides
echo "Removing airdrop..."
mysides remove / || true
echo "Removing applications..."
mysides remove Applications || true
echo "Adding HOME..."
mysides add "$(whoami)" "file://$HOME/"
echo "Adding dev..."
mkdir -p ~/dev
mysides add "Dev" "file://$HOME/dev/"
echo "Adding screenshots..."
mysides add "Screenshots" "file://$HOME/Screenshots/"
echo "Adding Music..."
mysides add "Music" "file://$HOME/Music/"
echo "Showing path and status bar..."
defaults write com.apple.finder "ShowPathbar" -bool "true"
defaults write com.apple.finder ShowStatusBar -bool true
killall Finder
echo "Done configuring Finder."
echo "Modifying spotlight search..."
# MENU_SPOTLIGHT_SUGGESTIONS sends search queries to Apple
# TODO I don't think this is working... it isn't changing what it says in sysprefs
# or what comes out of spotlight.
# Maybe it needs to be in the same order?
# defaults write com.apple.spotlight orderedItems -array \
# '{"enabled" = 1;"name" = "APPLICATIONS";}' \
# '{"enabled" = 1;"name" = "SYSTEM_PREFS";}' \
# '{"enabled" = 1;"name" = "DIRECTORIES";}' \
# '{"enabled" = 1;"name" = "PDF";}' \
# '{"enabled" = 1;"name" = "MENU_DEFINITION";}' \
# '{"enabled" = 1;"name" = "MENU_EXPRESSION";}' \
# '{"enabled" = 1;"name" = "MENU_CONVERSION";}' \
# '{"enabled" = 0;"name" = "FONTS";}' \
# '{"enabled" = 0;"name" = "DOCUMENTS";}' \
# '{"enabled" = 0;"name" = "MESSAGES";}' \
# '{"enabled" = 0;"name" = "CONTACT";}' \
# '{"enabled" = 0;"name" = "EVENT_TODO";}' \
# '{"enabled" = 0;"name" = "IMAGES";}' \
# '{"enabled" = 0;"name" = "BOOKMARKS";}' \
# '{"enabled" = 0;"name" = "MUSIC";}' \
# '{"enabled" = 0;"name" = "MOVIES";}' \
# '{"enabled" = 0;"name" = "PRESENTATIONS";}' \
# '{"enabled" = 0;"name" = "SPREADSHEETS";}' \
# '{"enabled" = 0;"name" = "SOURCE";}' \
# '{"enabled" = 0;"name" = "MENU_OTHER";}' \
# '{"enabled" = 0;"name" = "MENU_SPOTLIGHT_SUGGESTIONS";}'
# Load new settings before rebuilding the index
# killall mds || true
# Make sure indexing is enabled for the main volume
# sudo mdutil -i on /
# Rebuild the index from scratch
# sudo mdutil -E /
echo "Setting terminal to only use utf-8..."
defaults write com.apple.terminal StringEncodings -array 4
echo "Enabling secure keyboard entry..."
# See: https://security.stackexchange.com/a/47786/8918
defaults write com.apple.terminal SecureKeyboardEntry -bool true
echo "Enabling disk utility debug menu..."
defaults write com.apple.DiskUtility DUDebugMenuEnabled -bool true
defaults write com.apple.DiskUtility advanced-image-options -bool true
echo "Setting TextEdit to use UTF-8 .txt for new files instead of rtf..."
defaults write com.apple.TextEdit "RichText" -bool "false"
defaults write com.apple.TextEdit PlainTextEncodingForWrite -int 4
defaults write com.apple.TextEdit PlainTextEncoding -int 4
echo "Allowing help viewer to go behind other windows..."
defaults write com.apple.helpviewer "DevMode" -bool "true"
echo "Setting press-and-hold to repeat keys..."
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
# This also makes holding delete much faster
defaults write "Apple Global Domain" KeyRepeat -int 2
defaults write "Apple Global Domain" InitialKeyRepeat -int 15
echo "Disabling auto-correct..."
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
echo "Disabling Apple's targeted advertising..."
defaults write "com.apple.AdLib" allowApplePersonalizedAdvertising -bool FALSE
defaults write "com.apple.AdLib" allowIdentifierForAdvertising -bool FALSE
echo "Setting screensaver to activate after 10m..."
defaults -currentHost write com.apple.screensaver idleTime -int 600
echo "Setting sleep to start at 10m..."
sudo pmset -a displaysleep 10
sudo pmset -b sleep 10
# This MAY actually prompt for password immediately. It may also do nothing.
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
echo "Enabling firewall..."
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
echo "Disabling asking if disks should be used for time machine backup..."
defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true
echo "Making external monitors look a bit better..."
# https://tonsky.me/blog/monitors/
defaults -currentHost write -g AppleFontSmoothing -int 0
defaults write NSGlobalDomain AppleFontSmoothing -int 0
sudo defaults write /Library/Preferences/com.apple.windowserver \
DisplayResolutionEnabled -bool true
echo "Disabling some keyboard auto-fixers..."
defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false
defaults write "Apple Global Domain" NSAutomaticCapitalizationEnabled \
-bool FALSE
defaults write "Apple Global Domain" NSAutomaticDashSubstitutionEnabled \
-bool FALSE
defaults write "Apple Global Domain" NSAutomaticQuoteSubstitutionEnabled \
-bool FALSE
defaults write "Apple Global Domain" "KB_DoubleQuoteOption" -string "\\"abc\\""
defaults write "Apple Global Domain" "KB_SingleQuoteOption" -string "'abc'"
# Good lady this one was painful to write
defaults write "Apple Global Domain" NSUserQuotesArray \
-array '"\""' '"\""' "\'" "\'"
echo "Setting computer name to not contain login name..."
sudo scutil --set ComputerName "Computer"
sudo scutil --set LocalHostName "Computer"
sudo scutil --set HostName "Computer"
sudo defaults write \
/Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName \
-string "Computer"
echo "Installing quicklook plugins..."
if ! defaults read "com.apple.preferences.extensions.QuickLook" | grep -qe QLMarkdown; then
brew install --cask qlmarkdown
xattr -r -d com.apple.quarantine /Applications/QLMarkdown.app
defaults write org.sbarex.QLMarkdown SUEnableAutomaticChecks -bool FALSE
echo "Opening QLMarkdown to register Extension..."
open /Applications/QLMarkdown.app && sleep 5 && killall QLMarkdown
fi
if ! defaults read "com.apple.preferences.extensions.QuickLook" | grep -qe SyntaxHighlight; then
brew install --cask --no-quarantine syntax-highlight
echo "Opening Syntax Highlight to register extension..."
open '/Applications/Syntax Highlight.app' &&
sleep 5 &&
killall 'Syntax Highlight'
fi
defaults write com.apple.finder QLEnableTextSelection -bool TRUE
echo "Done installing quicklook plugins."
# TODO other shell integration
echo "Installing iTerm2..."
brew-get --cask iterm2
curl -L --no-progress-bar https://iterm2.com/shell_integration/fish \
-o ~/.config/fish/conf.d/90_iterm2_shell_integration.fish
add-update iterm2 \
'curl -L --no-progress-bar https://iterm2.com/shell_integration/fish \
-o ~/.config/fish/conf.d/90_iterm2_shell_integration.fish'
# Makes copying dotfiles easier
# https://imarslo.gitbook.io/handbook/gitbook/app/iterm2
# TODO check out this doc more
defaults write com.googlecode.iterm2 "Coprocess MRU" -int 0
brew tap homebrew/cask-fonts
brew-get --cask font-roboto font-blex-mono-nerd-font
echo "Installing GNU utilities..."
brew-get \
bash \
gawk \
wget \
parallel \
gnu-time \
gettext \
grep \
less \
gsed \
gnu-tar \
gnupg \
aspell \
findutils \
grep \
coreutils \
binutils \
diffutils \
readline
echo "will cite" | parallel --citation
add-update gpg 'gpg --refresh-keys'
echo "Installing various utilities..."
brew-get \
git \
bash-completion \
bash-language-server \
zsh-completions \
vim \
dict \
fish \
tree \
jq \
yq \
htop \
watch \
cowsay \
sl \
ddate \
gifsicle \
ffmpeg \
gh \
pandoc \
tmux \
pinentry-mac \
imagemagick \
openssl \
openssh \
lynx \
html2text \
direnv \
jump \
reattach-to-user-namespace
brew unlink openssh # needed so we can UseKeychain
brew-get --HEAD universal-ctags/universal-ctags/universal-ctags
echo "Installing zsh plugins..."
brew-get \
zsh-syntax-highlighting
echo "Installing next-gen CLI utilities..."
brew-get \
git-delta \
git-absorb \
eza \
bat \
duf \
fzf \
tldr \
fd \
ripgrep \
ripgrep-all \
hyperfine \
tz \
mdcat
add-update tldr 'tldr --update'
/opt/homebrew/opt/fzf/install --all
add-update fzf '/opt/homebrew/opt/fzf/install --all'
echo "Installing texlive..."
brew-get texlive
echo "Adding bash completion..."
append ~/.bashrc \
"[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion"
echo "Adding zsh completion to zshrc..."
append ~/.zshrc 'if type brew &>/dev/null; then
FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
autoload -Uz compinit
compinit
autoload bashcompinit && bashcompinit # Unsure if this is needed
fi'
rm -f ~/.zcompdump
# https://unix.stackexchange.com/questions/383365/zsh-compinit-insecure-directories-run-compaudit-for-list
zsh -c 'autoload -Uz compinit && compinit && compaudit | xargs chmod g-w'
echo "Setting editor..."
append ~/.bashrc 'export EDITOR=vim'
append ~/.zshrc 'export EDITOR=vim'
append ~/.config/fish/conf.d/10_editor.fish 'set -x EDITOR vim'
echo "Installing fisher..."
fish -c 'curl -sL https://git.io/fisher | source && \
fisher install jorgebucaran/fisher'
add-update fisher 'fish -c "fisher update"'
echo "Configuring starship..."
brew-get starship
append ~/.zshrc 'eval "$(starship init zsh)"'
append ~/.bashrc 'eval "$(starship init bash)"'
append ~/.config/fish/conf.d/99_starship.fish 'starship init fish | source'
echo "Installing python via pyenv..."
brew-get pyenv
# TODO consolidate appends
append ~/.bashrc 'export PYENV_ROOT="$HOME/.pyenv"'
append ~/.bashrc \
'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"'
append ~/.bashrc 'eval "$(pyenv init -)"'
append ~/.bashrc 'export PYTHON_CONFIGURE_OPTS="--enable-framework"'
append ~/.zshrc 'export PYENV_ROOT="$HOME/.pyenv"'
append ~/.zshrc \
'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"'
append ~/.zshrc 'eval "$(pyenv init -)"'
append ~/.zshrc 'export PYTHON_CONFIGURE_OPTS="--enable-framework"'
fish -c 'set -Ux PYENV_ROOT $HOME/.pyenv'
fish -c 'set -U fish_user_paths $PYENV_ROOT/bin $fish_user_paths'
append ~/.config/fish/conf.d/30_pyenv.fish 'pyenv init - | source'
append ~/.config/fish/conf.d/30_pyenv.fish \
'set -x PYTHON_CONFIGURE_OPTS "--enable-framework"'
# https://github.com/pyenv/pyenv/wiki#suggested-build-environment
brew-get openssl readline sqlite3 xz zlib tcl-tk
eval "$(pyenv init -)"
# Install latest stable python
pyenv install --skip-existing \
"$(pyenv install --list | sed 's/ //g' | ggrep -P '^[\d\.]+$' | tail -n 1)"
pyenv global "$(pyenv latest 3)"
git clone https://github.com/pyenv/pyenv-update.git $(pyenv root)/plugins/pyenv-update
# Update pyenv and plugins
add-update pyenv 'pyenv update'
# Update to latest python from pyenv
# https://stackoverflow.com/questions/4664229/here-document-as-an-argument-to-bash-function
# This is really cool; it lets us not have to escape anything.
add-update pyenv "$(
cat << "EOF"
pyenv install --skip-existing \
"$(pyenv install --list | sed 's/ //g' | ggrep -P '^[\d\.]+$' | tail -n 1)"
pyenv global "$(pyenv latest 3)"
EOF
)"
# Update installed fellas from each pyenv
add-update pyenv "$(
cat << "EOF"
pyenv versions --bare |
gxargs -d \$'\n' bash -c $'eval "$(pyenv init -)";
for arg; do
pyenv shell $arg
python --version
python -m pip install --upgrade pip
pip list --format=freeze |
grep -v "^\-e" |
cut -d = -f 1 |
xargs -n1 pip install -U
done' _
EOF
)"
# We also have to add updates for brew python packages
# TODO figure out expected fails like libtorrent
add-update brew-python "$(
cat << "EOF"
# Update pip itself
brew list |
sed -rn 's/python@(.+)/\1/p' |
xargs -I{} bash -c '/opt/homebrew/bin/"python{}" -m pip install --upgrade pip'
# Update packages installed by pip
brew list |
sed -rn 's/python@(.+)/\1/p' |
xargs -I{} bash -c '/opt/homebrew/bin/"pip{}" list --format=freeze |
grep -v "^\-e" |
cut -d = -f 1 |
xargs -n1 pip{} install -U'
EOF
)"
echo "Installing python packages..."
brew-get pkg-config poppler python
mkdir -p ~/.config/python
# This is where I'm keeping my binaries to bring with on new python versions
append ~/.config/python/global-requirements.txt "pdftotext"
pip install -r ~/.config/python/global-requirements.txt
add-update pyenv 'pip install -r ~/.config/python/global-requirements.txt'
#TODO should I use asdf, or fnm?
# https://github.com/Schniz/fnm ooh its rust
echo "Installing node and nvm..."
# brew-get nvm node
# TODO make this use latest tag
# Review if appends are needed
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
mkdir -p ~/.nvm
append ~/.zshrc 'export NVM_DIR="$HOME/.nvm"'
append ~/.zshrc '[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"'
append ~/.zshrc '[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"'
append ~/.bashrc 'export NVM_DIR="$HOME/.nvm"'
append ~/.bashrc '[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"'
append ~/.bashrc '[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"'
fish -c 'fisher install jorgebucaran/nvm.fish'
# So despite installing nvm, we're going to use homebrew node for everything global.
set +u
# TODO fix
# source /opt/homebrew/opt/nvm/nvm.sh
# nvm use system
set -u
add-update npm 'npm update -g'
echo "Installing go..."
brew-get go
append ~/.bashrc 'export PATH=$PATH:$(go env GOPATH)/bin'
append ~/.bashrc 'export GOPATH="$HOME/go"'
append ~/.zshrc 'export PATH=$PATH:$(go env GOPATH)/bin'
append ~/.zshrc 'export GOPATH="$HOME/go"'
mkdir -p "$HOME/go/bin"
fish -c 'set -Ux GOPATH $HOME/go'
fish -c 'set -U fish_user_paths $(go env GOPATH)/bin $fish_user_paths'
echo 'Installing gup (go global update)'
go install github.com/nao1215/gup@latest
add-update go "gup update"
echo "Installing rust..."
brew-get rustup
rustup-init -y
source "$HOME/.cargo/env"
append ~/.bashrc 'export PATH=$PATH:~/.cargo/bin'
append ~/.zshrc 'export PATH=$PATH:~/.cargo/bin'
fish -c 'set -U fish_user_paths ~/.cargo/bin $fish_user_paths'
cargo install cargo-update
add-update rust "cargo install-update -a"
add-update rust "rustup update"
echo "Installing ruby..."
brew-get rbenv ruby-build
brew-get autoconf automake gdbm gmp \
libksba libtool libyaml openssl pkg-config readline
append ~/.bashrc 'eval "$(rbenv init - bash)"'
append ~/.zshrc 'eval "$(rbenv init - zsh)"'
append ~/.config/fish/conf.d/52_rbenv.fish \
"status --is-interactive; and rbenv init - fish | source"
# we're not using homebrew ruby because of package shennanigans
rbenv install "$(rbenv install -l | grep -v - | tail -1)" --skip-existing
if [ "$(rbenv global)" = system ]; then
rbenv global "$(rbenv versions | tail -n1 | sed 's/ //g')"
fi
# Disables doc generation, speeding up gem installs
append ~/.gemrc 'gem: --no-ri --no-rdoc'
latest="$(rbenv install -l | grep -v - | tail -1)"
if [ ! "$(rbenv global)" = "$latest" ]; then
echo "updateme"
fi
add-update ruby 'gem update --system && gem update'
echo 'Installing Java \(Temurin 8, 11, 17\) with jenv...'
brew tap homebrew/cask-versions
brew update
brew tap homebrew/cask
brew-get --cask temurin8 temurin11 temurin17
brew-get jenv
append ~/.bashrc 'export PATH="$HOME/.jenv/bin:$PATH"'
append ~/.bashrc 'eval "$(jenv init -)"'
append ~/.zshrc 'export PATH="$HOME/.jenv/bin:$PATH"'
append ~/.zshrc 'eval "$(jenv init -)"'
append ~/.config/fish/conf.d/53_jenv.fish 'set PATH "$HOME"/.jenv/bin "$PATH"'
append ~/.config/fish/conf.d/53_jenv.fish \
"status --is-interactive; and jenv init - | source"
jenv add /Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
jenv add /Library/Java/JavaVirtualMachines/temurin-11.jdk/Contents/Home
jenv add /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
# jenv enable-plugin export # Not for fish! Disable for fish!
echo "Installing perl via perlbrew..."
if ! type perlbrew; then
SHELL=bash curl -L https://install.perlbrew.pl | bash
fi
append ~/.bashrc 'source ~/perl5/perlbrew/etc/bashrc'
append ~/.zshrc 'source ~/perl5/perlbrew/etc/bashrc'
append ~/.config/fish/conf.d/13_perlbrew.fish \
'. ~/perl5/perlbrew/etc/perlbrew.fish'
set +u
SHELL=bash source "$HOME/perl5/perlbrew/etc/bashrc"
set -u
SHELL=bash perlbrew init
latest="$(perlbrew available | /usr/bin/sed -nE 's/.*(perl-.*)/\1/p' | head -n1 | tr -d '[:space:]')"
if ! perlbrew list | grep -qF "$latest"; then
perlbrew install "$latest"
fi
perlbrew switch "$latest"
if [ ! -f "$PERLBREW_ROOT/bin/cpanm" ]; then
perlbrew install-cpanm --yes
fi
# TODO global perl deps
cpanm Perl::Critic
cpanm CPAN::DistnameInfo
cpanm Text::Levenshtein
cpanm Log::Log4perl
cpanm Term::ReadLine::Perl
cpanm App::cpanoutdated
# add-update perl 'yes | perl -MCPAN -e "upgrade /(.\*)/"'
add-update perl 'cpanm --self-upgrade || perlbrew install-cpanm --yes'
add-update perl 'cpan-outdated -p | cpanm'
echo "Installing lua via brew..."
brew-get lua luarocks
echo "Installing linters and fixers..."
# bash
brew-get \
shellcheck \
shfmt \
bash-language-server
pip install bashate
# cloudformation
brew-get cfn-lint
# css
npm i -g vscode-langservers-extracted
# docker
npm install -g dockerfile_lint
brew-get hadolint
# git
brew-get gitlint
# go handled by vim-go
# graphql
npm install -g gqlint
# HCL
brew tap hashicorp/tap
brew-get \
hashicorp/tap/packer \
hashicorp/tap/terraform \
hashicorp/tap/terraform-ls \
tflint \
tfsec \