Architecture
May 19, 2026 · View on GitHub
This document provides detailed technical information about Trace's architecture and implementation.
Core Components
AppDelegate.swift
Main application controller that manages:
- Launcher window lifecycle
- Global hotkey registration (default: ⌥Space)
- Settings window access
- Launch at login functionality
LauncherWindow/LauncherView
The main search interface:
- Borderless floating window positioned in upper-center of screen
- Uses Liquid Glass for translucent background
- Displays search results with app icons and type badges
- Always includes Google search as fallback result
AppSearchManager
High-performance app discovery and search:
- Singleton pattern for memory efficiency
- Concurrent scanning of /Applications, /System/Applications, ~/Applications
- In-memory caching with lazy icon loading
- Fuzzy search with relevance scoring
QuickLinksManager
Manages user-defined quick links and folder shortcuts:
- Support for both file paths and web URLs
- Built-in system folder defaults (Desktop, Documents, Downloads, etc.)
- Configurable with custom hotkeys and keywords
- Smart icon detection based on file types and domains
ToastManager
Non-intrusive notification system:
- Queue-based toast notifications with thread-safe operations
- Positioned at top-right of screen with auto-positioning
- Auto-dismissal with configurable timing
- Multiple toast types (success, error, warning, info)
HotkeyManager
Carbon API wrapper for global hotkey:
- Uses EventHotKey for system-wide hotkey registration
- Handles hotkey recording and updating without restart
SettingsView
Professional settings interface:
- Launch at login toggle (uses ServiceManagement API)
- Hotkey customization with live recording
- About section with GitHub/Twitter links
Key Technical Decisions
- No SwiftUI Settings Scene: Uses custom NSWindow to avoid duplicate settings windows
- Background Only: App runs as LSUIElement (no dock or menu bar presence)
- Carbon for Hotkeys: Required for global hotkey functionality
- Concurrent App Discovery: Background GCD queues for non-blocking startup
- Search Result Types: Application, Command, Suggestion, Math, QuickLink, SystemCommand
- Hotkey-Only Access: Settings and quit commands accessible through search interface
- Modular Search System: Plugin-based result providers for extensibility
- Toast Notifications: Custom overlay notifications replace system notifications
- Math Evaluation: Real-time math expression evaluation using AppleScript
Data Flow
- User presses hotkey → HotkeyManager triggers → AppDelegate shows LauncherWindow
- User types query → LauncherSearchLogic coordinates multiple result providers
- Result providers (Apps, QuickLinks, Math, Commands, etc.) return scored results
- Results merged and sorted by relevance score
- User selects result → CommandAction executed → Optional toast notification → Window hides
Important Files
trace/Info.plist- Contains LSUIElement key for background-only app behaviortrace/Assets.xcassets/AppIcon.appiconset/- App icons (generated from app.png using sips)- Models:
SearchModels.swiftdefines Application, SearchResult, SearchResultType - Models:
QuickLink.swiftdefines QuickLink model with URL handling and file type detection - Models:
CommandAction.swiftdefines the modular command execution system
UI Components
KeyBindingView
Reusable component for displaying keyboard shortcuts (trace/Components/KeyBindingView.swift):
- Displays keys as separate rounded rectangles with proper macOS styling
- Supports both direct key arrays and automatic conversion from keyCode/modifiers
- Used throughout the app for consistent keyboard shortcut display
ToastView
Modern toast notification component (trace/Views/ToastView.swift):
- Supports multiple toast types with appropriate icons and colors
- Smooth spring animations and drag-to-dismiss gesture
- Auto-dismissal after 4 seconds with manual dismiss option
Result Display Components
Adaptive result display system:
- ResultRowView: Standard result display with full details
- CompactResultRowView: Condensed view for secondary results
- AppIconView: Consistent app icon display with fallbacks
- LauncherFooterView: Status and shortcut hints
State Management
- User preferences:
@AppStoragefor persistence - Hotkey settings: Stored in UserDefaults with keys "hotkey_keyCode" and "hotkey_modifiers"
- Launch at login: SMAppService.mainApp for macOS 26+
Window Management
- LauncherWindow: 810x360 borderless window with 30px padding for shadow
- SettingsWindow: 450x500 standard window, non-resizable
- ToastWindow: 400x80 borderless overlay window, positioned at top-right
- All windows centered on screen, settings window released when closed = false
Project Structure
trace/
├── Core/ # Core application logic
│ ├── AppDelegate.swift
│ ├── Constants.swift
│ ├── FuzzyMatcher.swift
│ ├── HotkeyRegistry.swift
│ ├── Logging.swift
│ ├── ServiceContainer.swift
│ └── traceApp.swift
├── Views/ # SwiftUI views and UI components
│ ├── Components/ # Reusable UI components
│ │ ├── AppIconView.swift
│ │ ├── CompactResultRowView.swift
│ │ ├── KeyBindingView.swift
│ │ ├── LauncherFooterView.swift
│ │ ├── ResultRowView.swift
│ ├── Settings/ # Settings sub-views
│ │ ├── AboutSettingsView.swift
│ │ ├── AppHotkeysSettingsView.swift
│ │ ├── GeneralSettingsView.swift
│ │ ├── QuickLinksSettingsView.swift
│ │ └── WindowHotkeysSettingsView.swift
│ ├── LauncherSearchLogic.swift
│ ├── LauncherView.swift
│ ├── OnboardingView.swift
│ ├── SettingsView.swift
│ └── ToastView.swift
├── Managers/ # Business logic managers
│ ├── AppHotkeyManager.swift
│ ├── AppSearchManager.swift
│ ├── HotkeyManager.swift
│ ├── QuickLinksManager.swift
│ └── WindowHotkeyManager.swift
├── Services/ # System integration services
│ ├── ControlCenterManager.swift
│ ├── NetworkUtilities.swift
│ ├── PermissionManager.swift
│ ├── SettingsManager.swift
│ ├── ToastManager.swift
│ ├── UsageTracker.swift
│ └── WindowManager.swift
├── Search/ # Modular search system
│ ├── Providers/ # Search result providers
│ │ ├── AppResultProvider.swift
│ │ ├── ControlCenterProvider.swift
│ │ ├── MathResultProvider.swift
│ │ ├── NetworkCommandProvider.swift
│ │ ├── QuickLinksProvider.swift
│ │ ├── SearchEngineProvider.swift
│ │ ├── SystemCommandProvider.swift
│ │ └── WindowManagementProvider.swift
│ ├── ResultEventPublisher.swift
│ └── ResultProvider.swift
├── Models/ # Data models
│ ├── CommandAction.swift
│ ├── QuickLink.swift
│ └── SearchModels.swift
├── Utils/ # Utility functions
│ └── MathEvaluator.swift
└── Windows/ # Window management
├── LauncherWindow.swift
└── ToastWindow.swift
Key Features
- Background Operation: Runs as
LSUIElementfor invisible operation - Memory Efficient: Lazy loading and intelligent caching
- Concurrent Processing: Non-blocking app discovery and search
- Modern Swift: Uses async/await, structured concurrency, and SwiftUI
- Modular Architecture: Plugin-based search providers for extensibility
- Math Evaluation: Real-time calculation with AppleScript integration
- Toast Notifications: Custom overlay system replacing system notifications
- Quick Links: User-configurable shortcuts for files and web URLs
Development Guidelines
Memory Management & Safety
NEVER:
- Use implicitly unwrapped optionals - declare as optional and safely unwrap
- Force unwrap URLs or any external data without validation
- Create retain cycles with strong references in closures - always use
[weak self] - Leave event monitors, timers, or observers without proper cleanup in deinit
ALWAYS:
// Use proper optionals and safe unwrapping
private var statusItem: NSStatusItem?
guard let statusItem = self.statusItem else { return }
// Use weak self in closures
hotkeyManager.onHotkeyPressed = { [weak self] in
self?.toggleLauncher()
}
// Clean up resources in deinit
deinit {
timer?.invalidate()
if let monitor = eventMonitor {
NSEvent.removeMonitor(monitor)
}
}
Architecture & Design Patterns
PREFER:
// Settings service instead of direct UserDefaults
protocol SettingsService {
var launchAtLogin: Bool { get set }
var hotkeyConfig: HotkeyConfig { get set }
}
// Dependency injection instead of singletons
class AppSearchManager {
init(settingsService: SettingsService, fileManager: FileManager = .default)
}
Threading & Concurrency
- UI updates ONLY on main queue
- Use structured concurrency (async/await) for new code instead of GCD
- Document thread safety requirements in comments
- Avoid nested dispatch queues
Constants & Configuration
private enum Constants {
enum Window {
static let width: CGFloat = 810
static let height: CGFloat = 360
static let cornerRadius: CGFloat = 12
}
enum Animation {
static let duration: TimeInterval = 0.25
}
}