···11+# macOS Application Management Summary
22+33+## Overview
44+55+All non-system apps are now managed declaratively via Nix. This document lists all applications found in `/Applications` and their management status.
66+77+---
88+99+## ✅ Managed by Homebrew Casks
1010+1111+These apps are installed and managed via `settings/config/darwin.nix` → `homebrew.casks`:
1212+1313+### Communication
1414+- Discord
1515+- Element (Matrix client)
1616+- Signal
1717+- WhatsApp
1818+1919+### Productivity
2020+- Claude
2121+- GitHub Desktop
2222+- Obsidian
2323+- Visual Studio Code
2424+2525+### Browsers
2626+- Firefox
2727+2828+### Media & Entertainment
2929+- HandBrake
3030+- OBS Studio
3131+- Spotify
3232+3333+### Gaming
3434+- Epic Games Launcher
3535+- Prism Launcher (Minecraft)
3636+- Steam
3737+- Steam Link
3838+- UTM (Virtual Machines)
3939+4040+### Utilities
4141+- Cloudflare WARP
4242+- FileZilla (FTP)
4343+- Mos (Mouse/trackpad)
4444+- OneDrive
4545+- OnyX (System maintenance)
4646+- Parsec (Remote desktop)
4747+- Tailscale (VPN)
4848+- The Unarchiver
4949+- Transmission (BitTorrent)
5050+5151+### Office & Documents
5252+- LibreOffice
5353+- Microsoft Excel
5454+- Microsoft PowerPoint
5555+- Microsoft Teams
5656+- Microsoft Word
5757+5858+### Hardware
5959+- Logi Tune (Logitech webcam)
6060+- Logitech Options (Logitech devices)
6161+6262+### Other
6363+- NetNewsWire (RSS reader)
6464+6565+---
6666+6767+## ✅ Managed by Mac App Store (MAS)
6868+6969+These apps are installed via `settings/config/darwin.nix` → `masApps`:
7070+7171+- Amphetamine (ID: 937984704)
7272+- EA app (ID: 1246969117)
7373+- Mini Motorways (ID: 1453901000)
7474+- OP Auto Clicker (ID: 6754914118)
7575+- Roblox (ID: 1319456934)
7676+- TestFlight (ID: 899247664)
7777+- Zone Bar (ID: 6755328989)
7878+7979+---
8080+8181+## 🔧 System Apps (Not Managed)
8282+8383+These are built-in macOS applications and don't need to be managed:
8484+8585+- FaceTime → `/System/Applications/FaceTime.app`
8686+- iPhone Mirroring → `/System/Applications/iPhone Mirroring.app`
8787+- Mail → `/System/Applications/Mail.app`
8888+- Messages → `/System/Applications/Messages.app`
8989+- Phone → `/System/Applications/Phone.app`
9090+- Safari → `/Applications/Safari.app`
9191+- Terminal → `/System/Applications/Utilities/Terminal.app`
9292+9393+---
9494+9595+## ❌ Not Managed (Manual Installation)
9696+9797+These apps cannot be easily managed via Nix and must be installed manually:
9898+9999+### Adobe Suite
100100+- **Adobe Creative Cloud** - Requires Adobe account and subscription
101101+- **Adobe Photoshop 2026** - Installed via Creative Cloud
102102+103103+### Other
104104+- **2FHey** - Not available in Homebrew/MAS
105105+- **Letta Desktop** - Not available in Homebrew/MAS
106106+107107+### Folders (Not Apps)
108108+- Development
109109+- EA Games
110110+- Emulation
111111+- get_iplayer
112112+- Nix Apps (managed by Nix itself)
113113+- Utilities (system folder)
114114+115115+---
116116+117117+## 📊 Summary Statistics
118118+119119+- **Total apps in /Applications:** ~50
120120+- **Managed by Homebrew:** 37 apps
121121+- **Managed by MAS:** 7 apps
122122+- **System apps:** 7 apps
123123+- **Manual installation required:** 4 items
124124+- **Folders:** 6 folders
125125+126126+**Management Coverage:** 44/50 apps (88%) are declaratively managed!
127127+128128+---
129129+130130+## 🚀 Applying Changes
131131+132132+To install all managed applications:
133133+134134+```bash
135135+darwin-rebuild switch --flake ~/.config/nix-config#macmini
136136+```
137137+138138+This will:
139139+1. Install all Homebrew cask apps
140140+2. Install all Mac App Store apps (via `mas`)
141141+3. Configure your Dock
142142+4. Apply system settings
143143+144144+---
145145+146146+## 📝 Adding New Apps
147147+148148+### Via Homebrew Cask
149149+150150+1. Search for the app:
151151+ ```bash
152152+ brew search <app-name>
153153+ ```
154154+155155+2. Add to `settings/config/darwin.nix` → `homebrew.casks`:
156156+ ```nix
157157+ casks = [
158158+ # ...
159159+ "new-app-name"
160160+ ];
161161+ ```
162162+163163+3. Rebuild:
164164+ ```bash
165165+ darwin-rebuild switch --flake ~/.config/nix-config#macmini
166166+ ```
167167+168168+### Via Mac App Store
169169+170170+1. Find the app ID:
171171+ ```bash
172172+ mas search "App Name"
173173+ ```
174174+175175+2. Add to `settings/config/darwin.nix` → `masApps`:
176176+ ```nix
177177+ masApps = {
178178+ # ...
179179+ "App Name" = 123456789;
180180+ };
181181+ ```
182182+183183+3. Rebuild:
184184+ ```bash
185185+ darwin-rebuild switch --flake ~/.config/nix-config#macmini
186186+ ```
187187+188188+---
189189+190190+## 🔍 Verifying Installation
191191+192192+Check which apps are installed:
193193+194194+```bash
195195+# Homebrew casks
196196+brew list --cask
197197+198198+# Mac App Store apps
199199+mas list
200200+201201+# All apps in /Applications
202202+ls /Applications
203203+```
204204+205205+---
206206+207207+## ⚠️ Important Notes
208208+209209+1. **Finder** - Always shown in Dock, doesn't need to be listed in `persistent-apps`
210210+2. **Adobe apps** - Must be installed manually via Creative Cloud
211211+3. **App updates** - Homebrew apps update via `brew upgrade`, MAS apps via App Store
212212+4. **Homebrew cleanup** - Run `brew cleanup` periodically to remove old versions
213213+214214+---
215215+216216+## 🎯 Current Dock Configuration
217217+218218+Order (left to right):
219219+1. Finder (always shown)
220220+2. Mail
221221+3. WhatsApp
222222+4. Phone
223223+5. iPhone Mirroring
224224+6. FaceTime
225225+7. Messages
226226+8. Signal
227227+9. Element
228228+10. Discord
229229+11. Spotify
230230+12. Firefox
231231+13. Obsidian
232232+14. Visual Studio Code
233233+15. Terminal
234234+235235+All configured in `settings/darwin/default.nix` → `system.defaults.dock.persistent-apps`
+237
docs/macos-gatekeeper.md
···11+# macOS Gatekeeper Fix
22+33+## The Problem
44+55+macOS Gatekeeper blocks apps downloaded from the internet with errors like:
66+```
77+"Spotify.app" can't be opened because Apple cannot check it for malicious software.
88+```
99+1010+This happens because:
1111+1. Homebrew downloads apps from the internet
1212+2. macOS marks them with the `com.apple.quarantine` extended attribute
1313+3. Gatekeeper blocks quarantined apps from opening
1414+1515+## Immediate Fix (Run Now)
1616+1717+### Option 1: Remove Quarantine (Fastest)
1818+1919+```bash
2020+# For Spotify specifically
2121+sudo xattr -rd com.apple.quarantine /Applications/Spotify.app
2222+2323+# For all Homebrew apps
2424+find /Applications -name "*.app" -maxdepth 1 -exec sudo xattr -dr com.apple.quarantine {} \; 2>/dev/null
2525+```
2626+2727+### Option 2: Manual Approval
2828+2929+1. Try to open the app (it will fail)
3030+2. Go to **System Settings → Privacy & Security**
3131+3. Scroll down to see "Spotify was blocked"
3232+4. Click **"Open Anyway"**
3333+5. Try opening again, then click **"Open"** to confirm
3434+3535+### Option 3: Right-Click Method
3636+3737+1. Open Finder → `/Applications`
3838+2. **Right-click** on Spotify.app
3939+3. Select **"Open"** (not double-click!)
4040+4. In the dialog, click **"Open"**
4141+4242+## Automatic Fix (Added to Config)
4343+4444+I've created `modules/darwin/gatekeeper.nix` which automatically removes quarantine attributes on every rebuild.
4545+4646+### How It Works
4747+4848+On every `darwin-rebuild switch`, the module:
4949+1. Scans `/Applications` for all `.app` bundles
5050+2. Removes the `com.apple.quarantine` attribute
5151+3. Also checks `~/Applications` for user apps
5252+5353+This prevents Gatekeeper from blocking Homebrew apps.
5454+5555+## Verification
5656+5757+Check if an app is quarantined:
5858+5959+```bash
6060+# Check Spotify
6161+xattr -l /Applications/Spotify.app
6262+6363+# If quarantined, you'll see:
6464+# com.apple.quarantine: ...
6565+6666+# After fix, you should see nothing or other attributes only
6767+```
6868+6969+## Understanding Gatekeeper
7070+7171+### What is Gatekeeper?
7272+7373+macOS's security feature that:
7474+- Checks apps are from identified developers
7575+- Verifies apps are notarized by Apple
7676+- Blocks unsigned or unnotarized apps by default
7777+7878+### Why Does Homebrew Trigger This?
7979+8080+1. **Apps are downloaded** - macOS marks anything from the internet
8181+2. **Not from App Store** - Gatekeeper is more strict
8282+3. **Quarantine attribute** - Applied automatically by Safari/curl/Homebrew
8383+8484+### The Extended Attribute
8585+8686+```bash
8787+# View all extended attributes
8888+xattr /Applications/Spotify.app
8989+9090+# View quarantine details
9191+xattr -p com.apple.quarantine /Applications/Spotify.app
9292+9393+# Output looks like:
9494+# 0083;63a8f4b9;Chrome;F643CD55-6CF1-4FD1-B339-1C45F35CB205
9595+```
9696+9797+The quarantine attribute contains:
9898+- Flags (0083 = downloaded from web)
9999+- Timestamp
100100+- Source application (Chrome/Safari/curl)
101101+- UUID
102102+103103+## Security Considerations
104104+105105+### Is This Safe?
106106+107107+**Yes, but understand the implications:**
108108+109109+✅ **Safe when:**
110110+- You trust Homebrew's sources
111111+- Apps are from official casks (verified by Homebrew community)
112112+- You're installing well-known apps (Spotify, etc.)
113113+114114+⚠️ **Be careful when:**
115115+- Installing from unknown taps
116116+- Using third-party casks
117117+- Downloading random .dmg files
118118+119119+### Alternative: Selective Removal
120120+121121+If you want to be more selective, modify the gatekeeper.nix to only remove quarantine from specific apps:
122122+123123+```nix
124124+# Only remove for trusted apps
125125+apps=("Spotify.app" "Element.app" "Tailscale.app")
126126+for app in "''${apps[@]}"; do
127127+ if [ -d "/Applications/$app" ]; then
128128+ xattr -dr com.apple.quarantine "/Applications/$app" 2>/dev/null || true
129129+ fi
130130+done
131131+```
132132+133133+## Troubleshooting
134134+135135+### App Still Won't Open?
136136+137137+1. **Check permissions:**
138138+ ```bash
139139+ ls -la@ /Applications/Spotify.app
140140+ ```
141141+142142+2. **Verify signature:**
143143+ ```bash
144144+ codesign -dv /Applications/Spotify.app
145145+ ```
146146+147147+3. **Check for other issues:**
148148+ ```bash
149149+ spctl -a -vv /Applications/Spotify.app
150150+ ```
151151+152152+### "Operation not permitted" Error?
153153+154154+You need Full Disk Access for Terminal:
155155+1. System Settings → Privacy & Security
156156+2. Full Disk Access
157157+3. Add Terminal (or iTerm, etc.)
158158+159159+### Gatekeeper Still Blocking?
160160+161161+Disable Gatekeeper entirely (not recommended):
162162+```bash
163163+# Disable (requires recovery mode on Apple Silicon)
164164+sudo spctl --master-disable
165165+166166+# Re-enable
167167+sudo spctl --master-enable
168168+```
169169+170170+## macOS Versions
171171+172172+This affects all modern macOS versions:
173173+- ✅ **Sequoia (15.x)** - Strictest Gatekeeper
174174+- ✅ **Sonoma (14.x)** - Very strict
175175+- ✅ **Ventura (13.x)** - Strict
176176+- ✅ **Monterey (12.x)** - Moderate
177177+- ⚠️ **Big Sur and older** - Less strict, may not need fixes
178178+179179+## Alternative Approaches
180180+181181+### 1. Homebrew's Built-in Quarantine Removal
182182+183183+Homebrew has a flag to skip quarantine:
184184+```bash
185185+brew install --cask --no-quarantine spotify
186186+```
187187+188188+However, this doesn't work with nix-darwin's Homebrew module.
189189+190190+### 2. Launch Services + Quarantine
191191+192192+Our config now handles both:
193193+- **launch-services.nix** - Registers apps with macOS
194194+- **gatekeeper.nix** - Removes quarantine attributes
195195+196196+Together they ensure Homebrew apps work perfectly.
197197+198198+### 3. Manual Per-App
199199+200200+If you don't want automatic removal:
201201+```bash
202202+# Create a script
203203+cat > ~/bin/allow-app << 'EOF'
204204+#!/bin/bash
205205+xattr -rd com.apple.quarantine "/Applications/$1"
206206+echo "✅ Allowed: $1"
207207+EOF
208208+209209+chmod +x ~/bin/allow-app
210210+211211+# Usage
212212+allow-app Spotify.app
213213+```
214214+215215+## Summary
216216+217217+**What we've implemented:**
218218+219219+1. ✅ **gatekeeper.nix** - Automatically removes quarantine on rebuild
220220+2. ✅ **Integrated** - Added to macmini configuration
221221+3. ✅ **Safe** - Only affects apps in /Applications
222222+4. ✅ **Automatic** - Runs on every `darwin-rebuild switch`
223223+224224+**Next rebuild will:**
225225+- Remove quarantine from all Homebrew apps
226226+- Allow them to open without manual approval
227227+- Keep your system secure while being convenient
228228+229229+Run the immediate fix now, then rebuild to make it automatic:
230230+231231+```bash
232232+# Immediate fix
233233+sudo xattr -rd com.apple.quarantine /Applications/Spotify.app
234234+235235+# Then rebuild for automatic future handling
236236+darwin-rebuild switch --flake ~/.config/nix-config#macmini
237237+```
···11+{ config, lib, pkgs, ... }:
22+33+##############################################################################
44+# Gatekeeper Management for macOS
55+#
66+# Automatically removes quarantine attributes from Homebrew-installed apps
77+# and detects apps with invalid code signatures.
88+#
99+# Invalid signatures usually mean the app needs to be reinstalled.
1010+# Run: brew reinstall --cask <app-name>
1111+##############################################################################
1212+1313+{
1414+ system.activationScripts.removeQuarantine.text = lib.mkAfter ''
1515+ echo "Removing quarantine attributes from applications..." >&2
1616+1717+ # Remove quarantine from Homebrew Cask apps in /Applications
1818+ if [ -d "/Applications" ]; then
1919+ for app in /Applications/*.app; do
2020+ if [ -d "$app" ]; then
2121+ xattr -dr com.apple.quarantine "$app" 2>/dev/null || true
2222+ # Also ensure the app is executable
2323+ chmod -R +x "$app/Contents/MacOS"/* 2>/dev/null || true
2424+ fi
2525+ done
2626+ fi
2727+2828+ # Also check ~/Applications and Home Manager Apps
2929+ for apps_dir in "$HOME/Applications" "$HOME/Applications/Home Manager Apps"; do
3030+ if [ -d "$apps_dir" ]; then
3131+ for app in "$apps_dir"/*.app; do
3232+ if [ -d "$app" ]; then
3333+ xattr -dr com.apple.quarantine "$app" 2>/dev/null || true
3434+ chmod -R +x "$app/Contents/MacOS"/* 2>/dev/null || true
3535+ fi
3636+ done
3737+ fi
3838+ done
3939+4040+ echo "Quarantine attributes removed successfully" >&2
4141+4242+ # Check for apps with invalid signatures
4343+ echo "Checking code signatures..." >&2
4444+ for app in /Applications/*.app; do
4545+ if [ -d "$app" ]; then
4646+ if spctl -a -vv "$app" 2>&1 | grep -qi "invalid"; then
4747+ app_name=$(basename "$app")
4848+ echo "WARNING: $app_name has invalid signature and may not open" >&2
4949+ echo " Fix: brew reinstall --cask <cask-name>" >&2
5050+ fi
5151+ fi
5252+ done
5353+ '';
5454+}
+167
scripts/diagnose-macos-apps.sh
···11+#!/bin/bash
22+33+echo "==================================="
44+echo "macOS Apps Diagnostic Script"
55+echo "==================================="
66+echo ""
77+88+# Get list of Homebrew casks from nix config
99+CONFIG_DIR="$HOME/.config/nix-config"
1010+CASKS_FILE="$CONFIG_DIR/settings/config/darwin.nix"
1111+1212+# Extract cask list from config
1313+echo "Reading cask list from config..."
1414+CASKS=$(grep -A 50 'casks = \[' "$CASKS_FILE" | grep '"' | grep -v '^\s*#' | sed 's/.*"\(.*\)".*/\1/')
1515+1616+echo ""
1717+echo "Found casks in config:"
1818+echo "$CASKS" | sed 's/^/ - /'
1919+echo ""
2020+2121+# Function to check an app
2222+check_app() {
2323+ local cask_name="$1"
2424+ local app_name="$2"
2525+ local app_path="/Applications/$app_name"
2626+2727+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
2828+ echo "Checking: $app_name"
2929+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
3030+3131+ # Check if app exists
3232+ if [ ! -d "$app_path" ]; then
3333+ echo "❌ NOT FOUND at $app_path"
3434+3535+ # Try to find it elsewhere
3636+ echo " Searching system..."
3737+ local found=$(mdfind "kMDItemDisplayName == '$app_name'" 2>/dev/null | head -1)
3838+ if [ -n "$found" ]; then
3939+ echo " ℹ️ Found at: $found"
4040+ app_path="$found"
4141+ else
4242+ echo " ❌ Not found anywhere on system"
4343+ return 1
4444+ fi
4545+ else
4646+ echo "✅ Found at: $app_path"
4747+ fi
4848+4949+ # Check quarantine
5050+ if xattr -l "$app_path" 2>/dev/null | grep -q quarantine; then
5151+ echo "❌ HAS quarantine attribute"
5252+ echo " Fix: sudo xattr -rd com.apple.quarantine '$app_path'"
5353+ else
5454+ echo "✅ No quarantine attribute"
5555+ fi
5656+5757+ # Check executable
5858+ local exe_path=$(find "$app_path/Contents/MacOS" -type f -perm +111 2>/dev/null | head -1)
5959+ if [ -n "$exe_path" ]; then
6060+ echo "✅ Executable found: $(basename "$exe_path")"
6161+ else
6262+ echo "❌ No executable found"
6363+ fi
6464+6565+ # Check Gatekeeper/signature
6666+ local spctl_output=$(spctl -a -vv "$app_path" 2>&1)
6767+ if echo "$spctl_output" | grep -q "accepted"; then
6868+ echo "✅ Gatekeeper: accepted"
6969+ elif echo "$spctl_output" | grep -qi "invalid"; then
7070+ echo "❌ Gatekeeper: INVALID SIGNATURE"
7171+ echo " $(echo "$spctl_output" | grep -i invalid)"
7272+ echo " Fix: brew reinstall --cask $cask_name"
7373+ elif echo "$spctl_output" | grep -qi "rejected"; then
7474+ echo "⚠️ Gatekeeper: rejected (may need manual approval)"
7575+ else
7676+ echo "⚠️ Gatekeeper: $spctl_output"
7777+ fi
7878+7979+ # Check Launch Services
8080+ if /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -dump 2>/dev/null | grep -q "$(basename "$app_path" .app)"; then
8181+ echo "✅ Registered with Launch Services"
8282+ else
8383+ echo "⚠️ NOT registered with Launch Services"
8484+ fi
8585+8686+ echo ""
8787+}
8888+8989+# Check each cask
9090+# Map cask names to app names (common patterns)
9191+while IFS= read -r cask; do
9292+ case "$cask" in
9393+ logitune) check_app "$cask" "Logi Tune.app" ;;
9494+ logitech-options) check_app "$cask" "Logitech Options.app" ;;
9595+ microsoft-excel) check_app "$cask" "Microsoft Excel.app" ;;
9696+ microsoft-powerpoint) check_app "$cask" "Microsoft PowerPoint.app" ;;
9797+ microsoft-teams) check_app "$cask" "Microsoft Teams.app" ;;
9898+ microsoft-word) check_app "$cask" "Microsoft Word.app" ;;
9999+ netnewswire) check_app "$cask" "NetNewsWire.app" ;;
100100+ prismlauncher) check_app "$cask" "PrismLauncher.app" ;;
101101+ spotify) check_app "$cask" "Spotify.app" ;;
102102+ tailscale-app) check_app "$cask" "Tailscale.app" ;;
103103+ element) check_app "$cask" "Element.app" ;;
104104+ *)
105105+ # Generic check - try to guess the app name
106106+ app_name=$(echo "$cask" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++)sub(/./,toupper(substr($i,1,1)),$i)}1' | sed 's/ //g').app
107107+ check_app "$cask" "$app_name"
108108+ ;;
109109+ esac
110110+done <<< "$CASKS"
111111+112112+echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
113113+echo "Summary of Issues"
114114+echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
115115+echo ""
116116+117117+# Check for any apps with invalid signatures
118118+echo "Apps with invalid signatures (need reinstall):"
119119+while IFS= read -r cask; do
120120+ case "$cask" in
121121+ spotify) app_path="/Applications/Spotify.app" ;;
122122+ element) app_path="/Applications/Element.app" ;;
123123+ tailscale-app) app_path="/Applications/Tailscale.app" ;;
124124+ microsoft-excel) app_path="/Applications/Microsoft Excel.app" ;;
125125+ microsoft-word) app_path="/Applications/Microsoft Word.app" ;;
126126+ microsoft-powerpoint) app_path="/Applications/Microsoft PowerPoint.app" ;;
127127+ *) continue ;;
128128+ esac
129129+130130+ if [ -d "$app_path" ]; then
131131+ if spctl -a -vv "$app_path" 2>&1 | grep -qi "invalid"; then
132132+ echo " ❌ $cask - run: brew reinstall --cask $cask"
133133+ fi
134134+ fi
135135+done <<< "$CASKS"
136136+137137+echo ""
138138+echo "Apps with quarantine attribute:"
139139+while IFS= read -r cask; do
140140+ case "$cask" in
141141+ spotify) app_path="/Applications/Spotify.app" ;;
142142+ element) app_path="/Applications/Element.app" ;;
143143+ tailscale-app) app_path="/Applications/Tailscale.app" ;;
144144+ *) continue ;;
145145+ esac
146146+147147+ if [ -d "$app_path" ]; then
148148+ if xattr -l "$app_path" 2>/dev/null | grep -q quarantine; then
149149+ echo " ⚠️ $cask - run: sudo xattr -rd com.apple.quarantine '$app_path'"
150150+ fi
151151+ fi
152152+done <<< "$CASKS"
153153+154154+echo ""
155155+echo "==================================="
156156+echo "Quick Fixes"
157157+echo "==================================="
158158+echo ""
159159+echo "Rebuild Launch Services database:"
160160+echo " /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -gc -R -apps u,s,l"
161161+echo ""
162162+echo "Remove all quarantine attributes:"
163163+echo " sudo find /Applications -name '*.app' -maxdepth 1 -exec xattr -dr com.apple.quarantine {} \\;"
164164+echo ""
165165+echo "Rebuild nix-darwin config:"
166166+echo " darwin-rebuild switch --flake ~/.config/nix-config#macmini"
167167+echo ""
+110
scripts/fix-macos-apps.sh
···11+#!/bin/bash
22+33+echo "==================================="
44+echo "macOS Apps Auto-Fix Script"
55+echo "==================================="
66+echo ""
77+88+# Colors
99+RED='\033[0;31m'
1010+GREEN='\033[0;32m'
1111+YELLOW='\033[1;33m'
1212+NC='\033[0m' # No Color
1313+1414+CONFIG_DIR="$HOME/.config/nix-config"
1515+CASKS_FILE="$CONFIG_DIR/settings/config/darwin.nix"
1616+1717+# Extract cask list
1818+CASKS=$(grep -A 50 'casks = \[' "$CASKS_FILE" | grep '"' | grep -v '^\s*#' | sed 's/.*"\(.*\)".*/\1/')
1919+2020+echo "Checking all Homebrew cask apps from config..."
2121+echo ""
2222+2323+ISSUES_FOUND=0
2424+FIXED=0
2525+2626+# Function to get app path from cask name
2727+get_app_path() {
2828+ local cask="$1"
2929+ case "$cask" in
3030+ logitune) echo "/Applications/Logi Tune.app" ;;
3131+ logitech-options) echo "/Applications/Logitech Options.app" ;;
3232+ microsoft-excel) echo "/Applications/Microsoft Excel.app" ;;
3333+ microsoft-powerpoint) echo "/Applications/Microsoft PowerPoint.app" ;;
3434+ microsoft-teams) echo "/Applications/Microsoft Teams.app" ;;
3535+ microsoft-word) echo "/Applications/Microsoft Word.app" ;;
3636+ netnewswire) echo "/Applications/NetNewsWire.app" ;;
3737+ prismlauncher) echo "/Applications/PrismLauncher.app" ;;
3838+ spotify) echo "/Applications/Spotify.app" ;;
3939+ tailscale-app) echo "/Applications/Tailscale.app" ;;
4040+ element) echo "/Applications/Element.app" ;;
4141+ *) echo "" ;;
4242+ esac
4343+}
4444+4545+# Check and fix each app
4646+while IFS= read -r cask; do
4747+ app_path=$(get_app_path "$cask")
4848+4949+ if [ -z "$app_path" ] || [ ! -d "$app_path" ]; then
5050+ continue
5151+ fi
5252+5353+ echo -n "Checking $(basename "$app_path")... "
5454+5555+ # Check for invalid signature
5656+ if spctl -a -vv "$app_path" 2>&1 | grep -qi "invalid"; then
5757+ echo -e "${RED}INVALID SIGNATURE${NC}"
5858+ echo " → Reinstalling $cask..."
5959+6060+ if brew reinstall --cask "$cask" 2>/dev/null; then
6161+ echo -e " ${GREEN}✅ Fixed${NC}"
6262+ FIXED=$((FIXED + 1))
6363+ else
6464+ echo -e " ${RED}❌ Failed to reinstall${NC}"
6565+ fi
6666+ ISSUES_FOUND=$((ISSUES_FOUND + 1))
6767+ continue
6868+ fi
6969+7070+ # Check for quarantine
7171+ if xattr -l "$app_path" 2>/dev/null | grep -q quarantine; then
7272+ echo -e "${YELLOW}HAS QUARANTINE${NC}"
7373+ echo " → Removing quarantine..."
7474+7575+ if sudo xattr -rd com.apple.quarantine "$app_path" 2>/dev/null; then
7676+ echo -e " ${GREEN}✅ Fixed${NC}"
7777+ FIXED=$((FIXED + 1))
7878+ else
7979+ echo -e " ${RED}❌ Failed${NC}"
8080+ fi
8181+ ISSUES_FOUND=$((ISSUES_FOUND + 1))
8282+ continue
8383+ fi
8484+8585+ echo -e "${GREEN}✅ OK${NC}"
8686+8787+done <<< "$CASKS"
8888+8989+echo ""
9090+echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
9191+echo "Summary"
9292+echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
9393+echo "Issues found: $ISSUES_FOUND"
9494+echo "Fixed: $FIXED"
9595+echo ""
9696+9797+if [ $ISSUES_FOUND -eq 0 ]; then
9898+ echo -e "${GREEN}All apps are healthy! ✅${NC}"
9999+else
100100+ echo "Rebuilding Launch Services database..."
101101+ /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -gc -R -apps u,s,l 2>/dev/null
102102+103103+ echo "Restarting Dock..."
104104+ killall Dock 2>/dev/null
105105+106106+ echo ""
107107+ echo -e "${GREEN}Done! Try opening your apps now.${NC}"
108108+fi
109109+110110+echo ""