Problem
Calendar event queries using AppleScript were unacceptably slow for daily workflow automation:
- Target: Sub-second response time for morning paper generation
- Reality: 81 seconds to query a single day's events
- Impact: Would block entire morning paper workflow
Optimization Journey
Attempt 1: Optimize AppleScript Algorithm
Changes made:
- Direct calendar lookup instead of iterating all calendars
- Insertion sort replacing bubble sort (O(n²) → O(n²) best case O(n))
- Numeric sort keys (minutes since midnight) vs string comparison
- List building + join instead of string concatenation
Result: ~81 seconds (no improvement)
Learning: AppleScript's fundamental overhead from bridging to Calendar.app cannot be optimized away with algorithmic improvements.
Attempt 2: Swift Script (Interpreted)
Implementation:
#!/usr/bin/env swift
import EventKit
// ... query using native EventKit frameworkResult: 5.1 seconds (16x faster)
Learning: Native framework access is significantly faster than AppleScript bridging, but Swift script interpretation adds overhead.
Attempt 3: Compiled Swift Binary
Implementation:
swiftc -O list-events.swift -o list-eventsResult: 0.067 seconds (1,209x faster than AppleScript, 76x faster than interpreted Swift)
Final speedup: 1,209x improvement
Performance Comparison
| Implementation | Time (seconds) | Speedup | Use Case |
|---|---|---|---|
| AppleScript (original) | 81.0 | 1x | ❌ Too slow |
| AppleScript (optimized) | 81.0 | 1x | ❌ Still too slow |
| Swift script (interpreted) | 5.1 | 16x | ⚠️ Acceptable for one-off scripts |
| Swift binary (compiled) | 0.067 | 1,209x | ✅ Production workflows |
Testing Methodology
Performance Testing
# Use 'time' to measure execution
time bash list.sh 2025-11-19
# Test multiple dates for consistency
for date in 2025-11-18 2025-11-19 2025-11-20; do
echo "=== $date ==="
time bash list.sh "$date"
doneValidation Testing
# Verify output correctness
bash list.sh 2025-11-19
# Compare outputs between implementations
diff <(applescript-version) <(swift-version)
# Test edge cases
bash list.sh 2025-01-01 # New Year's Day
bash list.sh # Today (default)Iterative Approach
- Establish baseline - Measure original implementation
- Try algorithmic optimization first - Cheaper than rewrite
- If insufficient, change technology - Swift for native access
- Optimize the new approach - Compile for production use
- Validate thoroughly - Ensure correctness maintained
Key Learnings
When to Use AppleScript
- Simple one-off automation tasks
- GUI scripting (no Swift equivalent)
- When <5 second execution is acceptable
- Prototyping before Swift implementation
When to Use Swift + EventKit
- Performance-critical workflows (daily automation)
- Need <1 second response time
- Querying large datasets (calendar events, contacts, etc.)
- Production automation scripts
Technical Insights
AppleScript limitations:
- High bridging overhead to native apps
- Single-threaded execution
- String manipulation is slow
- Cannot be meaningfully optimized for performance
Swift advantages:
- Direct framework access (EventKit, Contacts, etc.)
- Compiled to native code
- Modern language features
- Same APIs used by native macOS apps
Compilation matters:
- Interpreted Swift: 5.1 seconds
- Compiled Swift: 0.067 seconds
- 76x speedup from compilation alone
Implementation Pattern
Structure
scripts/
├── list.sh # Shell wrapper (applies filtering, error handling)
├── list-events.swift # Swift source (version controlled)
├── list-events # Compiled binary (gitignored)
└── README.md # Setup/rebuild instructions
First-time setup
cd scripts/
swiftc -O list-events.swift -o list-eventsUsage
bash list.sh # Calls compiled binary
bash list.sh 2025-11-20 # Specific dateRecommendations
For Daily Workflows
- Always compile Swift scripts - 76x speedup over interpreted
- Use
swiftc -O- Optimization flag critical for performance - Version control source, not binary - Binaries are platform-specific
- Provide compilation instructions - README.md for future maintenance
For Quick Prototypes
- Start with AppleScript - Faster to write
- Measure performance early - Before building workflows around it
- Set performance budgets - If >1 second for daily tasks, consider Swift
- Plan for migration - Design shell wrapper that can swap implementations
Performance Testing
- Use
timecommand - Built-in, reliable measurement - Test multiple iterations - Rule out caching, first-run overhead
- Test with real data - Production calendar size, not empty calendar
- Document baseline - Before optimizing, measure current state
Related Resources
- Swift EventKit Documentation: https://developer.apple.com/documentation/eventkit
- AppleScript Language Guide: https://developer.apple.com/library/archive/documentation/AppleScript/
- Skill Location:
.agents/skills/osx/calendar/ - Implementation Details:
.agents/skills/osx/calendar/SKILL.md
Future Applications
This pattern applies to other macOS automation:
- Contacts queries - ContactsKit framework
- Reminders - EventKit (same framework as Calendar)
- Photos - PhotoKit framework
- Files/metadata - FileManager, Spotlight APIs
- System info - IOKit, SystemConfiguration
Rule of thumb: If AppleScript takes >1 second, rewrite in Swift with native frameworks.