# swift-macos-client-debug
> Debug and fix Swift macOS menubar app issues including code signing crashes, MainActor isolation errors, and app termination. Use when the client app won't launch, crashes on startup, shows code signature errors, or has threading/concurrency issues.
- Author: thegaltinator
- Repository: thegaltinator/Alfred
- Version: 20260130193846
- Stars: 0
- Forks: 0
- Last Updated: 2026-02-06
- Source: https://github.com/thegaltinator/Alfred
- Web: https://mule.run/skillshub/@@thegaltinator/Alfred~swift-macos-client-debug:20260130193846
---
---
name: swift-macos-client-debug
description: Debug and fix Swift macOS menubar app issues including code signing crashes, MainActor isolation errors, and app termination. Use when the client app won't launch, crashes on startup, shows code signature errors, or has threading/concurrency issues.
---
# Swift macOS Client Debugging Guide
When the Alfred macOS client (client-prod) isn't working, follow this systematic debugging approach.
## Quick Diagnosis Checklist
1. **Check crash reports**: `ls -t ~/Library/Logs/DiagnosticReports/Alfred*`
2. **Check if running**: `ps aux | grep Alfred | grep -v grep`
3. **Run directly**: `/path/to/Alfred.app/Contents/MacOS/Alfred 2>&1`
4. **Verify signature**: `codesign -vvv /path/to/Alfred.app`
## Common Issues & Fixes
### 1. Code Signature Invalid (SIGKILL)
**Symptoms:**
- App crashes immediately on launch
- Crash report shows: `"signal":"SIGKILL (Code Signature Invalid)"`
- Termination namespace: `CODESIGNING`, indicator: `Invalid Page`
**Fix - Add required entitlements** to `Alfred.entitlements`:
```xml
com.apple.security.cs.disable-library-validation
com.apple.security.cs.allow-unsigned-executable-memory
```
**Fix - Fresh bundle ID** (avoid cache issues):
```bash
# In build-app.sh, change:
BUNDLE_ID="com.bicyclelabs.alfred3-dev" # Use unique ID
```
**Fix - Remove quarantine and re-sign**:
```bash
xattr -cr /path/to/Alfred.app
codesign --force --deep --sign - --entitlements Alfred.entitlements /path/to/Alfred.app
```
### 2. MainActor Isolation Errors
**Symptoms:**
- Build errors: `cannot be called from outside of the actor`
- Runtime crashes with threading violations
**Fix - Wrap calls in MainActor context**:
```swift
// From async context:
await MainActor.run {
UserSession.shared.clearUser()
}
// From sync context:
Task { @MainActor in
UserSession.shared.clearUser()
}
```
**Common files needing fixes:**
- `TalkerService.swift` - UserSession calls in actor methods
- `DeviceAuthService.swift` - UserSession calls in sync methods
- `AlfredApp.swift` - Notification observer closures
### 3. App Terminates Immediately
**Symptoms:**
- App starts, logs appear, then `👋 Alfred app terminating`
- No crash report generated
**Fix - Add `applicationShouldTerminateAfterLastWindowClosed`**:
```swift
// In AppDelegate
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return false // CRITICAL for menubar apps
}
```
**Fix - Mark AppDelegate as @MainActor**:
```swift
@MainActor
class AppDelegate: NSObject, NSApplicationDelegate {
// ...
}
```
### 4. Framework Loading Failures
**Symptoms:**
- Crashes in dyld during startup
- "Library not found" errors
**Fix - Verify framework paths**:
```bash
# Check what the executable expects
otool -L /path/to/Alfred.app/Contents/MacOS/Alfred
# Fix paths if needed
install_name_tool -add_rpath "@executable_path/../Frameworks" /path/to/Alfred.app/Contents/MacOS/Alfred
install_name_tool -change "@rpath/whisper.framework/Versions/A/whisper" "@executable_path/../Frameworks/whisper.framework/Versions/A/whisper" /path/to/Alfred.app/Contents/MacOS/Alfred
```
### 5. Whisper Framework Signing
**The whisper.framework has a non-standard layout. Sign in this order:**
```bash
# 1. Sign dylibs in Libraries/ first
for dylib in Alfred.app/Contents/Frameworks/whisper.framework/Versions/A/Libraries/*.dylib; do
codesign --force --sign - "$dylib"
done
# 2. Sign the versioned binary
codesign --force --sign - Alfred.app/Contents/Frameworks/whisper.framework/Versions/A/whisper
# 3. Sign the framework bundle
codesign --force --sign - Alfred.app/Contents/Frameworks/whisper.framework
# 4. Sign Sparkle
codesign --force --deep --sign - Alfred.app/Contents/Frameworks/Sparkle.framework
# 5. Sign the app
codesign --force --deep --sign - --entitlements Alfred.entitlements Alfred.app
```
## Clean Build Process
When things aren't working, do a completely fresh build:
```bash
# 1. Clean all caches
rm -rf client-prod/.build
rm -rf client-prod/.swiftpm
rm -rf client-prod/dist
rm -rf ~/Library/Developer/Xcode/DerivedData/*Alfred*
rm -rf ~/Library/Caches/com.bicyclelabs.alfred*
# 2. Update bundle ID to avoid stale cache
# Edit scripts/build-app.sh: BUNDLE_ID="com.bicyclelabs.alfred-fresh"
# 3. Build fresh
cd client-prod
bash scripts/build-app.sh
# 4. Remove quarantine
xattr -cr dist/Alfred.app
# 5. Launch
open dist/Alfred.app
```
## Required Entitlements for Ad-Hoc Signing
```xml
com.apple.security.app-sandbox
com.apple.security.network.client
com.apple.security.device.audio-input
com.apple.security.cs.disable-library-validation
com.apple.security.cs.allow-unsigned-executable-memory
```
## Key Files
| File | Purpose |
|------|---------|
| `client-prod/Alfred.entitlements` | Code signing entitlements |
| `client-prod/scripts/build-app.sh` | Build script with bundle ID |
| `client-prod/AppKitUI/AlfredApp.swift` | App lifecycle, StatusBar |
| `client-prod/Bridge/UserSession.swift` | Thread-safe session state |
| `client-prod/Bridge/TalkerService.swift` | Server communication |
| `client-prod/Bridge/DeviceAuthService.swift` | OAuth flow |
## Verification Commands
```bash
# Check signature
codesign -vvv /path/to/Alfred.app
# Check Gatekeeper (will fail for ad-hoc, that's OK)
spctl -a -vvv /path/to/Alfred.app
# Check if running
ps aux | grep Alfred | grep -v grep
# View crash reports
ls -t ~/Library/Logs/DiagnosticReports/Alfred* | head -5
# Read latest crash
cat $(ls -t ~/Library/Logs/DiagnosticReports/Alfred* | head -1)
```