diff --git a/README.md b/README.md index 1e966e34..d5ff8011 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,19 @@ Sparkdock is an automated macOS development environment provisioner built with A ## Features +### macOS System Defaults + +**Developer-Optimized Defaults:** + +- **UI/UX Improvements**: Expanded save/print panels, disk-first saving, disabled smart quotes/dashes +- **Finder Enhancements**: Show hidden files and extensions, status/path bars, prevent .DS_Store on networks +- **Dock Optimizations**: Auto-hide with fast animations, no recent apps, better window behavior +- **Keyboard/Input**: Faster key repeat rates, trackpad right-click, disabled press-and-hold +- **Safari Developer**: Web inspector, developer menu, full URLs, secure defaults +- **Terminal/Development**: UTF-8 encoding, secure input, plain text TextEdit +- **Accessibility**: Reduce motion for better focus and performance +- **System Tools**: Enhanced Activity Monitor, optimized screenshots, Time Machine settings + ### Applications & Tools **GUI Applications:** @@ -68,9 +81,10 @@ The installation process: 2. **Base Tools**: Git, curl, Python 3, Ansible 3. **Sparkdock Repository**: Cloned to `/opt/sparkdock` 4. **Applications & Tools**: All packages from the configuration -5. **HTTP Proxy System**: Configured and ready to use -6. **Task Runner**: sjust command available system-wide -7. **Update Service**: Automatic update checking via launchd +5. **macOS System Defaults**: Developer-optimized system settings +6. **HTTP Proxy System**: Configured and ready to use +7. **Task Runner**: sjust command available system-wide +8. **Update Service**: Automatic update checking via launchd ## Usage @@ -82,6 +96,54 @@ Run the provisioner to configure your system: sparkdock ``` +### Selective Deployment + +Run specific parts of the configuration using Ansible tags: + +**macOS System Defaults:** + +The macOS defaults configuration is implemented as a YAML-driven sjust task. Both Ansible and direct usage execute the same implementation: + +```bash +# Direct usage (recommended for individual use) +sjust macos-defaults # Apply all macOS developer defaults +sjust macos-defaults-check # Preview current defaults status +sjust macos-defaults-reset # Reset selected defaults (use with caution) +sjust macos-defaults-init-overrides # Create user overrides configuration + +# Via Ansible (calls sjust internally) +ansible-playbook ansible/macos.yml --tags macos-defaults --ask-become-pass +``` + +**User Customization:** + +You can override any defaults by creating user-specific configuration: + +```bash +# Initialize user overrides directory and example file +sjust macos-defaults-init-overrides + +# Edit your custom settings +nano ~/.local/spark/macos-defaults/overrides.yml +``` + +The system automatically merges your overrides with the default configuration. Configuration is stored in: +- **Default settings**: `config/macos/defaults.yml` (40+ developer-optimized defaults) +- **User overrides**: `~/.local/spark/macos-defaults/overrides.yml` (your customizations) + +**Skip macOS Defaults:** +```bash +ansible-playbook ansible/macos.yml --skip-tags macos-defaults --ask-become-pass +``` + +**Other available tags:** +```bash +ansible-playbook ansible/macos.yml --tags docker --ask-become-pass # Docker setup only +ansible-playbook ansible/macos.yml --tags http-proxy --ask-become-pass # HTTP proxy only +ansible-playbook ansible/macos.yml --tags keyboard --ask-become-pass # Keyboard config only +ansible-playbook ansible/macos.yml --tags sjust --ask-become-pass # Task runner only +``` + ### Manual Migration for Existing Users If you have an existing Sparkdock installation and want to update to the new HTTP proxy system without running the full provisioner: diff --git a/ansible/macos/macos/base.yml b/ansible/macos/macos/base.yml index ef933c0b..03596156 100644 --- a/ansible/macos/macos/base.yml +++ b/ansible/macos/macos/base.yml @@ -389,6 +389,13 @@ path: "{{ brew_prefix.stdout }}/share/zsh/site-functions/_sjust" mode: "0644" + # Apply macOS system defaults configuration using sjust + - name: Apply macOS system defaults for developers + shell: /usr/local/bin/sjust macos-defaults + become: no + tags: macos-defaults + when: "'/usr/local/bin/sjust' is exists" + - name: Remove unwanted cask packages community.general.homebrew_cask: name: "{{ all_removed_cask_packages }}" diff --git a/config/macos/defaults.yml b/config/macos/defaults.yml new file mode 100644 index 00000000..ef95e408 --- /dev/null +++ b/config/macos/defaults.yml @@ -0,0 +1,390 @@ +# macOS System Defaults Configuration for Developers +# This file defines the macOS system defaults that will be applied +# to optimize the system for developer productivity. + +# General UI/UX improvements +ui_ux: + - domain: NSGlobalDomain + key: NSNavPanelExpandedStateForSaveMode + type: bool + value: true + description: "Expand save panel by default" + + - domain: NSGlobalDomain + key: PMPrintingExpandedStateForPrint + type: bool + value: true + description: "Expand print panel by default" + + - domain: NSGlobalDomain + key: NSDocumentSaveNewDocumentsToCloud + type: bool + value: false + description: "Save to disk (not iCloud) by default" + + - domain: NSGlobalDomain + key: NSAutomaticCapitalizationEnabled + type: bool + value: false + description: "Disable automatic capitalization" + + - domain: NSGlobalDomain + key: NSAutomaticDashSubstitutionEnabled + type: bool + value: false + description: "Disable automatic dash substitution" + + - domain: NSGlobalDomain + key: NSAutomaticPeriodSubstitutionEnabled + type: bool + value: false + description: "Disable automatic period substitution" + + - domain: NSGlobalDomain + key: NSAutomaticQuoteSubstitutionEnabled + type: bool + value: false + description: "Disable smart quotes" + + - domain: NSGlobalDomain + key: NSAutomaticSpellingCorrectionEnabled + type: bool + value: false + description: "Disable automatic spelling correction" + +# Keyboard and input settings for developers +keyboard: + - domain: NSGlobalDomain + key: KeyRepeat + type: int + value: 1 + description: "Set key repeat rate (fastest)" + + - domain: NSGlobalDomain + key: InitialKeyRepeat + type: int + value: 10 + description: "Set initial key repeat delay" + + - domain: NSGlobalDomain + key: ApplePressAndHoldEnabled + type: bool + value: false + description: "Disable press-and-hold for key repeat" + +# Accessibility improvements for developers +accessibility: + - domain: com.apple.universalaccess + key: reduceMotion + type: int + value: 1 + description: "Reduce motion for better focus and performance" + +# Trackpad settings +trackpad: + - domain: com.apple.driver.AppleBluetoothMultitouch.trackpad + key: Clicking + type: bool + value: true + description: "Enable tap to click" + + - domain: com.apple.driver.AppleBluetoothMultitouch.trackpad + key: TrackpadRightClick + type: bool + value: true + description: "Enable right click" + + - domain: com.apple.driver.AppleBluetoothMultitouch.trackpad + key: TrackpadCornerSecondaryClick + type: int + value: 2 + description: "Right click in bottom right corner" + +# Finder improvements for developers +finder: + - domain: NSGlobalDomain + key: AppleShowAllExtensions + type: bool + value: true + description: "Show all filename extensions" + + - domain: com.apple.finder + key: AppleShowAllFiles + type: bool + value: true + description: "Show hidden files" + + - domain: com.apple.finder + key: ShowStatusBar + type: bool + value: true + description: "Show status bar" + + - domain: com.apple.finder + key: ShowPathbar + type: bool + value: true + description: "Show path bar" + + - domain: com.apple.finder + key: _FXShowPosixPathInTitle + type: bool + value: true + description: "Show full POSIX path in title bar" + + - domain: com.apple.finder + key: _FXSortFoldersFirst + type: bool + value: true + description: "Sort folders first" + + - domain: com.apple.finder + key: FXDefaultSearchScope + type: string + value: "SCcf" + description: "Search current folder by default" + + - domain: com.apple.finder + key: FXEnableExtensionChangeWarning + type: bool + value: false + description: "Disable extension change warning" + + - domain: com.apple.desktopservices + key: DSDontWriteNetworkStores + type: bool + value: true + description: "Don't create .DS_Store files on network volumes" + + - domain: com.apple.desktopservices + key: DSDontWriteUSBStores + type: bool + value: true + description: "Don't create .DS_Store files on USB volumes" + + - domain: com.apple.finder + key: FXPreferredViewStyle + type: string + value: "Nlsv" + description: "Use list view by default" + +# Dock improvements +dock: + - domain: com.apple.dock + key: tilesize + type: float + value: 48 + description: "Set dock tile size" + + - domain: com.apple.dock + key: mineffect + type: string + value: "scale" + description: "Use scale effect for minimizing" + + - domain: com.apple.dock + key: minimize-to-application + type: bool + value: true + description: "Minimize windows to application icon" + + - domain: com.apple.dock + key: enable-spring-load-actions-on-all-items + type: bool + value: true + description: "Enable spring loading for all dock items" + + - domain: com.apple.dock + key: show-process-indicators + type: bool + value: true + description: "Show indicator lights for open applications" + + - domain: com.apple.dock + key: launchanim + type: bool + value: false + description: "Disable launch animations" + + - domain: com.apple.dock + key: autohide + type: bool + value: true + description: "Auto-hide dock" + + - domain: com.apple.dock + key: autohide-delay + type: float + value: 0 + description: "Remove auto-hide delay" + + - domain: com.apple.dock + key: autohide-time-modifier + type: float + value: 0 + description: "Remove auto-hide animation" + + - domain: com.apple.dock + key: show-recents + type: bool + value: false + description: "Hide recent applications in dock" + +# Safari developer settings +safari: + - domain: com.apple.Safari + key: IncludeInternalDebugMenu + type: bool + value: true + description: "Enable internal debug menu" + + - domain: com.apple.Safari + key: IncludeDevelopMenu + type: bool + value: true + description: "Enable developer menu" + + - domain: com.apple.Safari + key: WebKitDeveloperExtrasEnabledPreferenceKey + type: bool + value: true + description: "Enable WebKit developer extras" + + - domain: com.apple.Safari + key: WebKitDeveloperExtras + type: bool + value: true + description: "Enable web inspector" + + - domain: com.apple.Safari + key: ShowFullURLInSmartSearchField + type: bool + value: true + description: "Show full URL in address bar" + + - domain: com.apple.Safari + key: AutoOpenSafeDownloads + type: bool + value: false + description: "Disable auto-opening safe downloads" + + - domain: com.apple.Safari + key: ShowStatusBar + type: bool + value: true + description: "Show status bar" + +# Terminal improvements +terminal: + - domain: com.apple.terminal + key: StringEncodings + type: array + value: [4] + description: "Set UTF-8 encoding" + + - domain: com.apple.terminal + key: SecureKeyboardEntry + type: bool + value: true + description: "Enable secure keyboard entry" + +# TextEdit improvements for developers +textedit: + - domain: com.apple.TextEdit + key: RichText + type: int + value: 0 + description: "Use plain text by default" + + - domain: com.apple.TextEdit + key: PlainTextEncoding + type: int + value: 4 + description: "Set UTF-8 encoding for reading" + + - domain: com.apple.TextEdit + key: PlainTextEncodingForWrite + type: int + value: 4 + description: "Set UTF-8 encoding for writing" + +# Activity Monitor improvements +activity_monitor: + - domain: com.apple.ActivityMonitor + key: OpenMainWindow + type: bool + value: true + description: "Show main window when launching" + + - domain: com.apple.ActivityMonitor + key: IconType + type: int + value: 5 + description: "Show CPU usage in dock icon" + + - domain: com.apple.ActivityMonitor + key: ShowCategory + type: int + value: 0 + description: "Show all processes" + + - domain: com.apple.ActivityMonitor + key: SortColumn + type: string + value: "CPUUsage" + description: "Sort by CPU usage" + + - domain: com.apple.ActivityMonitor + key: SortDirection + type: int + value: 0 + description: "Sort in descending order" + +# Screenshots improvements +screenshots: + - domain: com.apple.screencapture + key: location + type: string + value: "${HOME}/Desktop" + description: "Save screenshots to desktop" + + - domain: com.apple.screencapture + key: type + type: string + value: "png" + description: "Save screenshots as PNG" + + - domain: com.apple.screencapture + key: disable-shadow + type: bool + value: true + description: "Disable screenshot shadows" + +# Time Machine improvements +time_machine: + - domain: com.apple.TimeMachine + key: DoNotOfferNewDisksForBackup + type: bool + value: true + description: "Don't offer new disks for backup" + +# Disk Utility improvements +disk_utility: + - domain: com.apple.DiskUtility + key: DUDebugMenuEnabled + type: bool + value: true + description: "Enable debug menu" + + - domain: com.apple.DiskUtility + key: advanced-image-options + type: bool + value: true + description: "Enable advanced image options" + +# Applications to restart after applying defaults +restart_applications: + - Finder + - Dock + - Safari + - "Activity Monitor" \ No newline at end of file diff --git a/config/packages/all-packages.yml b/config/packages/all-packages.yml index 044443c3..e5689d38 100644 --- a/config/packages/all-packages.yml +++ b/config/packages/all-packages.yml @@ -48,6 +48,7 @@ homebrew_packages: - fzf - navi - jq + - yq - yadm - tmate - tmux diff --git a/sjust/justfile b/sjust/justfile index b9e22188..9ce2189b 100644 --- a/sjust/justfile +++ b/sjust/justfile @@ -20,6 +20,7 @@ import "/opt/sparkdock/sjust/recipes/_private.just" import "/opt/sparkdock/sjust/recipes/00-default.just" import "/opt/sparkdock/sjust/recipes/01-lima.just" import "/opt/sparkdock/sjust/recipes/02-docker-desktop.just" +import "/opt/sparkdock/sjust/recipes/03-macos-defaults.just" # this is optional and let the user to add custom tasks. import? "~/.config/sjust/100-custom.just" \ No newline at end of file diff --git a/sjust/recipes/03-macos-defaults.just b/sjust/recipes/03-macos-defaults.just new file mode 100644 index 00000000..1c3bc217 --- /dev/null +++ b/sjust/recipes/03-macos-defaults.just @@ -0,0 +1,392 @@ +# vim: set ft=make : + +# macOS System Defaults Configuration +# Apply developer-optimized macOS system defaults using YAML configuration + +sparkdock_path := "/opt/sparkdock" +config_file := sparkdock_path + "/config/macos/defaults.yml" +user_overrides := "${HOME}/.local/spark/macos-defaults/overrides.yml" + +# Apply macOS system defaults for developers +[group('macos')] +macos-defaults: + #!/usr/bin/env bash + set -euo pipefail + source /opt/sparkdock/sjust/libs/libformatting.sh + source /opt/sparkdock/sjust/libs/libcolors.sh + + # Check if yq is available + if ! command -v yq >/dev/null 2>&1; then + echo "${red}Error: yq is required but not installed.${normal}" + echo "Please install it with: brew install yq" + exit 1 + fi + + config_file="{{config_file}}" + user_overrides="{{user_overrides}}" + + echo "${bold}${cyan}Applying macOS System Defaults for Developers${normal}" + echo + echo "Configuration file: ${config_file}" + if [[ -f "${user_overrides}" ]]; then + echo "User overrides: ${user_overrides}" + fi + echo + + # Create temporary merged config if user overrides exist + temp_config="/tmp/macos-defaults-merged.yml" + if [[ -f "${user_overrides}" ]]; then + echo "${green}Merging user overrides...${normal}" + yq eval-all '. as $item ireduce ({}; . * $item)' "${config_file}" "${user_overrides}" > "${temp_config}" + config_to_use="${temp_config}" + else + config_to_use="${config_file}" + fi + + # Function to apply defaults from YAML + apply_defaults_category() { + local category="$1" + local description="$2" + + echo "• Configuring ${description}..." + + # Get all items in this category + yq eval ".${category}[]" "${config_to_use}" -o json | while IFS= read -r item; do + if [[ -n "${item}" && "${item}" != "null" ]]; then + domain=$(echo "${item}" | yq eval '.domain' -) + key=$(echo "${item}" | yq eval '.key' -) + type=$(echo "${item}" | yq eval '.type' -) + value=$(echo "${item}" | yq eval '.value' -) + description=$(echo "${item}" | yq eval '.description' -) + + # Handle different value types + case "${type}" in + "bool") + if [[ "${value}" == "true" ]]; then + defaults write "${domain}" "${key}" -bool true + else + defaults write "${domain}" "${key}" -bool false + fi + ;; + "int") + defaults write "${domain}" "${key}" -int "${value}" + ;; + "float") + defaults write "${domain}" "${key}" -float "${value}" + ;; + "string") + # Handle environment variable expansion + expanded_value=$(eval echo "${value}") + defaults write "${domain}" "${key}" -string "${expanded_value}" + ;; + "array") + # Handle arrays (like [4] for encoding) + array_values=$(echo "${item}" | yq eval '.value[]' - | tr '\n' ' ') + defaults write "${domain}" "${key}" -array ${array_values} + ;; + *) + echo "${yellow}Warning: Unknown type '${type}' for ${domain}.${key}${normal}" + ;; + esac + fi + done + } + + echo "This will configure macOS system defaults optimized for developer productivity." + echo "Settings are defined in: ${config_file}" + echo + echo "${yellow}Note: Some settings require applications to be restarted to take effect.${normal}" + echo + echo "${green}Applying macOS defaults...${normal}" + + # Apply all categories + apply_defaults_category "ui_ux" "UI/UX settings" + apply_defaults_category "keyboard" "keyboard settings" + apply_defaults_category "accessibility" "accessibility settings" + apply_defaults_category "trackpad" "trackpad settings" + apply_defaults_category "finder" "Finder settings" + apply_defaults_category "dock" "Dock settings" + apply_defaults_category "safari" "Safari developer settings" + apply_defaults_category "terminal" "Terminal settings" + apply_defaults_category "textedit" "TextEdit settings" + apply_defaults_category "activity_monitor" "Activity Monitor settings" + apply_defaults_category "screenshots" "screenshot settings" + apply_defaults_category "time_machine" "Time Machine settings" + apply_defaults_category "disk_utility" "Disk Utility settings" + + echo + echo "${green}Restarting affected applications...${normal}" + + # Get applications to restart from config + restart_apps=$(yq eval '.restart_applications[]' "${config_to_use}") + for app in ${restart_apps}; do + # Remove quotes if present + app_clean=$(echo "${app}" | tr -d '"') + killall "${app_clean}" 2>/dev/null || true + done + + # Clean up temporary file + if [[ -f "${temp_config}" ]]; then + rm -f "${temp_config}" + fi + + echo + echo "${bold}${green}✅ macOS system defaults applied successfully!${normal}" + echo + echo "Applications restarted:" + echo "${restart_apps}" | while read app; do + echo " • ${app}" + done + echo + echo "Some changes may require a logout/login or system restart to fully take effect." + +# Show current macOS defaults status (dry-run) +[group('macos')] +macos-defaults-check: + #!/usr/bin/env bash + set -euo pipefail + source /opt/sparkdock/sjust/libs/libformatting.sh + source /opt/sparkdock/sjust/libs/libcolors.sh + + # Check if yq is available + if ! command -v yq >/dev/null 2>&1; then + echo "${red}Error: yq is required but not installed.${normal}" + echo "Please install it with: brew install yq" + exit 1 + fi + + config_file="{{config_file}}" + user_overrides="{{user_overrides}}" + + echo "${bold}${cyan}Checking macOS System Defaults Status${normal}" + echo + echo "Configuration file: ${config_file}" + if [[ -f "${user_overrides}" ]]; then + echo "User overrides: ${user_overrides}" + fi + echo + + # Create temporary merged config if user overrides exist + temp_config="/tmp/macos-defaults-check.yml" + if [[ -f "${user_overrides}" ]]; then + echo "${green}Using merged configuration with user overrides...${normal}" + yq eval-all '. as $item ireduce ({}; . * $item)' "${config_file}" "${user_overrides}" > "${temp_config}" + config_to_use="${temp_config}" + else + config_to_use="${config_file}" + fi + + # Function to check defaults from a category + check_defaults_category() { + local category="$1" + local display_name="$2" + + echo "${bold}${display_name}:${normal}" + + # Get all items in this category + yq eval ".${category}[]" "${config_to_use}" -o json | while IFS= read -r item; do + if [[ -n "${item}" && "${item}" != "null" ]]; then + domain=$(echo "${item}" | yq eval '.domain' -) + key=$(echo "${item}" | yq eval '.key' -) + type=$(echo "${item}" | yq eval '.type' -) + expected=$(echo "${item}" | yq eval '.value' -) + description=$(echo "${item}" | yq eval '.description' -) + + # Get current value + current=$(defaults read "${domain}" "${key}" 2>/dev/null || echo "not set") + + # Handle different expected value types for comparison + case "${type}" in + "bool") + if [[ "${expected}" == "true" ]]; then + expected_display="1" + else + expected_display="0" + fi + ;; + "string") + # Handle environment variable expansion + expected_display=$(eval echo "${expected}") + ;; + "array") + # Format array for display + expected_display="(${expected})" + current=$(defaults read "${domain}" "${key}" 2>/dev/null | tr '\n' ' ' | xargs || echo "not set") + ;; + *) + expected_display="${expected}" + ;; + esac + + # Compare and display result + if [[ "${current}" == "${expected_display}" ]] || [[ "${current}" == "${expected}" ]]; then + echo " ${green}✓${normal} ${description}: ${green}${current}${normal}" + else + echo " ${red}✗${normal} ${description}: ${red}${current}${normal} (expected: ${yellow}${expected_display}${normal})" + fi + fi + done + echo + } + + # Check all categories + check_defaults_category "ui_ux" "UI/UX Settings" + check_defaults_category "keyboard" "Keyboard Settings" + check_defaults_category "accessibility" "Accessibility Settings" + check_defaults_category "trackpad" "Trackpad Settings" + check_defaults_category "finder" "Finder Settings" + check_defaults_category "dock" "Dock Settings" + check_defaults_category "safari" "Safari Developer Settings" + check_defaults_category "terminal" "Terminal Settings" + check_defaults_category "textedit" "TextEdit Settings" + check_defaults_category "activity_monitor" "Activity Monitor Settings" + check_defaults_category "screenshots" "Screenshot Settings" + check_defaults_category "time_machine" "Time Machine Settings" + check_defaults_category "disk_utility" "Disk Utility Settings" + + # Clean up temporary file + if [[ -f "${temp_config}" ]]; then + rm -f "${temp_config}" + fi + +# Reset macOS defaults to system defaults (use with caution) +[group('macos')] +macos-defaults-reset: + #!/usr/bin/env bash + set -euo pipefail + source /opt/sparkdock/sjust/libs/libformatting.sh + source /opt/sparkdock/sjust/libs/libcolors.sh + + # Check if yq is available + if ! command -v yq >/dev/null 2>&1; then + echo "${red}Error: yq is required but not installed.${normal}" + echo "Please install it with: brew install yq" + exit 1 + fi + + config_file="{{config_file}}" + + echo "${bold}${red}⚠️ Reset macOS System Defaults${normal}" + echo + echo "${yellow}This will reset the developer-optimized defaults back to system defaults.${normal}" + echo "${red}This action cannot be easily undone!${normal}" + echo + echo "Settings to be reset are defined in: ${config_file}" + echo + echo -n "Are you sure you want to continue? [y/N]: " + read -r response + + if [[ "${response}" =~ ^[Yy]$ ]]; then + echo + echo "${green}Resetting macOS defaults...${normal}" + + # Function to reset defaults from a category + reset_defaults_category() { + local category="$1" + local description="$2" + + echo "Resetting ${description}..." + + # Get all items in this category + yq eval ".${category}[]" "${config_file}" -o json | while IFS= read -r item; do + if [[ -n "${item}" && "${item}" != "null" ]]; then + domain=$(echo "${item}" | yq eval '.domain' -) + key=$(echo "${item}" | yq eval '.key' -) + + # Delete the key to restore system default + defaults delete "${domain}" "${key}" 2>/dev/null || true + fi + done + } + + # Reset selected categories (those that are commonly customized) + reset_defaults_category "keyboard" "keyboard settings" + reset_defaults_category "accessibility" "accessibility settings" + reset_defaults_category "finder" "Finder settings" + reset_defaults_category "dock" "Dock settings" + + echo + echo "${green}Restarting affected applications...${normal}" + + # Get applications to restart from config + restart_apps=$(yq eval '.restart_applications[]' "${config_file}") + for app in ${restart_apps}; do + # Remove quotes if present + app_clean=$(echo "${app}" | tr -d '"') + killall "${app_clean}" 2>/dev/null || true + done + + echo + echo "${bold}${green}✅ Selected macOS defaults have been reset.${normal}" + echo "${yellow}You may need to restart applications or reboot for all changes to take effect.${normal}" + else + echo "Reset cancelled." + fi + +# Create user overrides directory and example file +[group('macos')] +macos-defaults-init-overrides: + #!/usr/bin/env bash + set -euo pipefail + source /opt/sparkdock/sjust/libs/libformatting.sh + source /opt/sparkdock/sjust/libs/libcolors.sh + + user_overrides="{{user_overrides}}" + overrides_dir="$(dirname "${user_overrides}")" + + echo "${bold}${cyan}Initializing macOS Defaults User Overrides${normal}" + echo + echo "This will create a user overrides file at: ${user_overrides}" + echo + + # Create directory if it doesn't exist + if [[ ! -d "${overrides_dir}" ]]; then + echo "Creating directory: ${overrides_dir}" + mkdir -p "${overrides_dir}" + fi + + # Create example overrides file if it doesn't exist + if [[ ! -f "${user_overrides}" ]]; then + echo "Creating example overrides file..." + cat > "${user_overrides}" << 'EOF' +# macOS Defaults User Overrides +# This file allows you to override the default macOS settings. +# +# Example: To disable dock auto-hide and keep recent applications visible: +# +# dock: +# - domain: com.apple.dock +# key: autohide +# type: bool +# value: false +# description: "Don't auto-hide dock" +# +# - domain: com.apple.dock +# key: show-recents +# type: bool +# value: true +# description: "Show recent applications in dock" +# +# Example: To change key repeat settings: +# +# keyboard: +# - domain: NSGlobalDomain +# key: KeyRepeat +# type: int +# value: 2 +# description: "Slower key repeat rate" + +# Add your custom overrides below: +EOF + + echo "${bold}${green}✅ User overrides file created successfully!${normal}" + echo + echo "Edit your overrides at: ${user_overrides}" + echo "Then run 'sjust macos-defaults' to apply settings with your overrides." + else + echo "${yellow}User overrides file already exists: ${user_overrides}${normal}" + fi + + echo + echo "To view the default configuration structure, see:" + echo " {{config_file}}" \ No newline at end of file