Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .chezmoiignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Brewfile
fonts/
plans/
README.md
LICENSE
.github/
13 changes: 13 additions & 0 deletions .chezmoiscripts/run_once_after_20-zinit.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"

if [ -d "$ZINIT_HOME/.git" ]; then
exit 0
fi

echo "Installing zinit..."
mkdir -p "$(dirname "$ZINIT_HOME")"
git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
38 changes: 38 additions & 0 deletions .chezmoiscripts/run_once_after_21-macos-system-defaults.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

if [ -n "${CI:-}" ]; then
echo "Skipping macOS system defaults (needs sudo) in CI"
exit 0
fi

echo "Setting macOS system defaults..."

IS_LAPTOP=$(/usr/sbin/system_profiler SPHardwareDataType | grep "Model Identifier" | grep "Book" || true)
if [ -n "$IS_LAPTOP" ]; then
sudo pmset -b sleep 20 disksleep 15 displaysleep 10 halfdim 1
sudo pmset -c sleep 0 disksleep 0 displaysleep 30 halfdim 1

# Menu bar: show remaining battery time (on pre-10.8); hide percentage
defaults write com.apple.menuextra.battery ShowPercent -string "YES"
defaults write com.apple.menuextra.battery ShowTime -string "NO"
else
sudo pmset sleep 0 disksleep 0 displaysleep 15 halfdim 1
fi

# Don't show any password hints
sudo defaults write /Library/Preferences/com.apple.loginwindow RetriesUntilHint -int 0

# Enable key repeat
defaults write -g ApplePressAndHoldEnabled -bool false

# Set keyboard repeat rate
defaults write -g KeyRepeat -int 2
defaults write -g InitialKeyRepeat -int 15

# Disable auto-correct
defaults write -g NSAutomaticSpellingCorrectionEnabled -bool false

# Set scroll direction
sudo defaults write /Library/Preferences/.GlobalPreferences com.apple.swipescrolldirection -bool false
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#!/bin/zsh
echo "\nSet OsX user defaults"
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

echo "Setting macOS user defaults..."

# ==============================================
# Trackpad
# ==============================================
# Tap to click
IS_LAPTOP=`/usr/sbin/system_profiler SPHardwareDataType | grep "Model Identifier" | grep "Book"`
if [[ "$IS_LAPTOP" != "" ]]; then
IS_LAPTOP=$(/usr/sbin/system_profiler SPHardwareDataType | grep "Model Identifier" | grep "Book" || true)
if [ -n "$IS_LAPTOP" ]; then
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
defaults -currentHost write -g com.apple.mouse.tapBehavior -int 1
# Tap with two fingers to emulate right click
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick -bool false
# Secondary click
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadCornerSecondaryClick -int 2
defaults -currentHost write -g com.apple.trackpad.trackpadCornerClickBehavior -int 1
defaults -currentHost write -g com.apple.trackpad.enableSecondaryClick -bool true
Expand All @@ -22,38 +22,16 @@ defaults write com.apple.dock showAppExposeGestureEnabled -bool true
defaults write com.apple.dock showDesktopGestureEnabled -bool true
defaults write com.apple.dock showLaunchpadGestureEnabled -bool true

# ==============================================
# Archive Utility
# ==============================================
# Move archives to trash after extraction
# defaults write com.apple.archiveutility "dearchive-move-after" -string "~/.Trash"

# Don't reveal extracted items
# defaults write com.apple.archiveutility "dearchive-reveal-after" -bool false

# ==============================================
# Finder
# ==============================================
# Expand the "Open with" and "Sharing & Permissions" panes
defaults write com.apple.finder FXInfoPanesExpanded -dict OpenWith -bool true Privileges -bool true

# Show status bar
defaults write com.apple.finder ShowStatusBar -bool true

# Show all filename extensions
defaults write -g AppleShowAllExtensions -bool true

# Show all files
defaults write com.apple.finder AppleShowAllFiles -bool true

# Finder: allow text selection in Quick Look
defaults write com.apple.finder QLEnableTextSelection -bool true
# When performing a search, search the current folder by default
defaults write com.apple.finder FXDefaultSearchScope -string "SCcf"
# Use column view
defaults write com.apple.finder FXPreferredViewStyle -string "clmv"

# Automatically open a new Finder window when a volume is mounted
defaults write com.apple.frameworks.diskimages auto-open-ro-root -bool false
defaults write com.apple.frameworks.diskimages auto-open-rw-root -bool false
defaults write com.apple.finder OpenWindowForNewRemovableDisk -bool true
Expand All @@ -63,60 +41,40 @@ defaults write com.apple.finder OpenWindowForNewRemovableDisk -bool true
# ==============================================
defaults write com.apple.dock showAppExposeGesture -bool true
defaults write com.apple.dock magnification -bool true
defaults write com.apple.dock tilesize -int 29
defaults write com.apple.dock tilesize -int 71
defaults write com.apple.dock minimize-to-application -bool true
defaults write com.apple.dock autohide 1
defaults write com.apple.dock autohide -bool true

# ==============================================
# Safari & WebKit
# ==============================================
# Show status bar
defaults write com.apple.Safari ShowStatusBar -bool true

# Show favorites bar
defaults write com.apple.Safari ShowFavoritesBar -bool true
defaults write com.apple.Safari "ShowFavoritesBar-v2" -bool true

# New tabs open with: Empty Page
defaults write com.apple.Safari NewTabBehavior -int 1

# Homepage
defaults write com.apple.Safari HomePage -string "about:blank"

# Open pages in tabs instead of windows: automatically
defaults write com.apple.Safari TabCreationPolicy -int 1

# Command-clicking a link creates tabs
defaults write com.apple.Safari CommandClickMakesTabs -bool true

# Update extensions automatically
defaults write com.apple.Safari InstallExtensionUpdatesAutomatically -bool true

# Enable the Develop menu and the Web Inspector in Safari
defaults write com.apple.Safari IncludeDevelopMenu -bool true
defaults write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true
defaults write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true

# Add a context menu item for showing the Web Inspector in web views
defaults write -g WebKitDeveloperExtras -bool true

# Prevent Safari from opening ‘safe’ files automatically after downloading
defaults write com.apple.Safari AutoOpenSafeDownloads -bool false
defaults write com.apple.Safari AutoOpenSafeDownloads -bool false

# ==============================================
# Terminal
# ==============================================
# Set the "Pro" as the default
defaults write com.apple.Terminal "Default Window Settings" -string "Pro"
defaults write com.apple.Terminal "Startup Window Settings" -string "Pro"

pathToTerminalPrefs="${HOME}/Library/Preferences/com.apple.Terminal.plist"
/usr/libexec/PlistBuddy -c "Add :Window\ Settings:Pro:columnCount integer 120" ${pathToTerminalPrefs}
/usr/libexec/PlistBuddy -c "Add :Window\ Settings:Pro:rowCount integer 70" ${pathToTerminalPrefs}
/usr/libexec/PlistBuddy -c "Add :Window\\ Settings:Pro:columnCount integer 120" "$pathToTerminalPrefs" 2>/dev/null || true
/usr/libexec/PlistBuddy -c "Add :Window\\ Settings:Pro:rowCount integer 70" "$pathToTerminalPrefs" 2>/dev/null || true

# ==============================================
# Sound
# ==============================================
# Disable user interface sound efects
defaults write -g "com.apple.sound.beep.feedback" -bool false
defaults write com.apple.systemsound "com.apple.sound.uiaudio.enabled" -bool false

Expand All @@ -128,11 +86,9 @@ defaults write com.apple.screencapture location -string "$HOME/Downloads"
# ==============================================
# Time Machine
# ==============================================
# Prevent Time Machine from prompting to use new hard drives as backup volume
defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true
defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true

# ==============================================
# Applications
# ==============================================
# Disable the “Are you sure you want to open this application?” dialog
defaults write com.apple.LaunchServices LSQuarantine -bool false
7 changes: 7 additions & 0 deletions .chezmoiscripts/run_once_after_23-fonts.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

echo "Installing fonts..."
mkdir -p "$HOME/Library/Fonts"
cp -n "{{ .chezmoi.sourceDir }}"/fonts/*.ttf "$HOME/Library/Fonts/"
19 changes: 19 additions & 0 deletions .chezmoiscripts/run_once_after_24-browser-extensions.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

echo "Installing Brave extensions..."
BRAVE_EXTENSIONS="$HOME/Library/Application Support/BraveSoftware/Brave-Browser/External Extensions"
mkdir -p "$BRAVE_EXTENSIONS"
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$BRAVE_EXTENSIONS/aapbdbdomjkkjkaonfhkkikfgjllcleb.json" # Google Translate
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$BRAVE_EXTENSIONS/kbfnbcaeplbcioakkpcpgfkobkghlhen.json" # Grammarly
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$BRAVE_EXTENSIONS/idgpnmonknjnojddfkpgkljpfnnfcklj.json" # ModHeader
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$BRAVE_EXTENSIONS/bcjindcccaagfpapjjmafapmmgkkhgoa.json" # JSON Formatter

echo "Installing Chrome extensions..."
CHROME_EXTENSIONS="$HOME/Library/Application Support/Google/Chrome Dev/External Extensions"
mkdir -p "$CHROME_EXTENSIONS"
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$CHROME_EXTENSIONS/aapbdbdomjkkjkaonfhkkikfgjllcleb.json" # Google Translate
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$CHROME_EXTENSIONS/kbfnbcaeplbcioakkpcpgfkobkghlhen.json" # Grammarly
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$CHROME_EXTENSIONS/idgpnmonknjnojddfkpgkljpfnnfcklj.json" # ModHeader
echo '{"external_update_url": "https://clients2.google.com/service/update2/crx"}' > "$CHROME_EXTENSIONS/bcjindcccaagfpapjjmafapmmgkkhgoa.json" # JSON Formatter
45 changes: 45 additions & 0 deletions .chezmoiscripts/run_once_after_30-dock.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

if ! command -v dockutil >/dev/null 2>&1; then
eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv 2>/dev/null)" || true
fi

if ! command -v dockutil >/dev/null 2>&1; then
echo "dockutil not found, skipping Dock setup"
exit 0
fi

echo "Configuring Dock..."
dockutil --remove all --no-restart

dockutil --add "/System/Applications/Launchpad.app" --no-restart
dockutil --add "/System/Applications/Mission Control.app" --no-restart
dockutil --add "/System/Applications/System Settings.app" --no-restart
dockutil --add "/Applications/Safari.app" --no-restart

for app in \
"/Applications/Warp.app" \
"/Applications/Cursor.app" \
"/Applications/Visual Studio Code.app" \
"/Applications/Claude.app" \
"/Applications/Brave Browser.app" \
"/Applications/Google Chrome Dev.app" \
"/Applications/Firefox Developer Edition.app" \
"/Applications/Slack.app" \
"/Applications/Spotify.app" \
"/Applications/Microsoft Outlook.app"; do
if [ -d "$app" ]; then
dockutil --add "$app" --no-restart
fi
done

if [ -d "$HOME/Documents" ]; then
dockutil --add "$HOME/Documents" --view grid --display stack --sort name --no-restart
fi
if [ -d "$HOME/Downloads" ]; then
dockutil --add "$HOME/Downloads" --view grid --display stack --sort dateadded --no-restart
fi

killall Dock || true
10 changes: 10 additions & 0 deletions .chezmoiscripts/run_once_after_40-editor-extensions.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

if command -v cursor >/dev/null 2>&1; then
echo "Installing Brewfile's vscode extensions into Cursor..."
grep -oE '^vscode "[^"]+"' "{{ .chezmoi.sourceDir }}/Brewfile" | sed -E 's/vscode "//;s/"//' | while read -r extension; do
cursor --install-extension "$extension"
done
fi
19 changes: 19 additions & 0 deletions .chezmoiscripts/run_once_before_00-xcode-cli.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

if [ -n "${CI:-}" ]; then
echo "Skipping Xcode CLI tools / Software Update in CI"
exit 0
fi

echo "Installing Xcode Command Line Tools..."
xcode-select -p >/dev/null 2>&1 || xcode-select --install

echo "Checking for macOS software updates..."
softwareupdate -ia --verbose

if [ "$(uname -m)" = "arm64" ]; then
echo "Installing Rosetta 2..."
softwareupdate --install-rosetta --agree-to-license
fi
10 changes: 10 additions & 0 deletions .chezmoiscripts/run_once_before_01-homebrew.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
set -euo pipefail

if command -v brew >/dev/null 2>&1; then
exit 0
fi

echo "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
26 changes: 26 additions & 0 deletions .chezmoiscripts/run_onchange_before_10-packages.sh.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
{{ if ne .chezmoi.os "darwin" }}exit 0{{ end }}
# Brewfile hash: {{ include "Brewfile" | sha256sum }}
set -euo pipefail

if ! command -v brew >/dev/null 2>&1; then
eval "$(/opt/homebrew/bin/brew shellenv 2>/dev/null || /usr/local/bin/brew shellenv)"
fi

if [ -n "${CI:-}" ]; then
# Only checks that the Brewfile's bundle DSL parses; it deliberately does
# NOT try to resolve every formula/cask name (third-party-tap entries like
# svu/goreleaser fail that check unless explicitly `brew trust`-ed, which
# would make this a trust-model test instead of a Brewfile syntax test).
# Run `brew bundle check --verbose` locally after editing the Brewfile to
# catch renamed/removed formulas - see README.
echo "CI: validating Brewfile syntax without installing everything in it"
brew bundle list --file="{{ .chezmoi.sourceDir }}/Brewfile" >/dev/null
exit 0
fi

echo "Installing Homebrew packages..."
brew bundle --file="{{ .chezmoi.sourceDir }}/Brewfile"

echo "Cleaning up old formulae..."
brew cleanup --prune=all
29 changes: 29 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Lint

on:
push:
pull_request:

jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Strip chezmoi template guards for linting
run: |
mkdir -p /tmp/lint
for f in .chezmoiscripts/*.tmpl; do
base=$(basename "$f" .tmpl)
# Force a bash shebang for linting purposes regardless of the
# script's real shebang - ShellCheck refuses zsh scripts
# outright (SC1071), and this action has no option to force
# --shell, so the shebang line itself is what it auto-detects
# from.
{ echo '#!/bin/bash'; tail -n +2 "$f" | sed -E 's/\{\{.*\}\}//g'; } > "/tmp/lint/$base"
done

- name: ShellCheck
uses: ludeeus/action-shellcheck@master
with:
scandir: /tmp/lint
Loading
Loading