How stonerl/thaw works
1. What this repo is
Thaw is a macOS menu bar management app, split into a primary GUI app and a small helper/service target. The core product hides, shows, reorders, and restyles menu bar items, with extra features like hotkeys, search, profiles, and automation.
2. Top-level runtime shape
The main executable is the Thaw app target. It owns app state, settings, navigation, onboarding, permissions UI, notifications, and the visible menu bar controls. A separate MenuBarItemService process handles low-level menu bar item discovery and monitoring so the GUI app does not do all of that work in-process.
3. System event ingestion
Input comes from macOS event infrastructure: event taps, HID event monitoring, local event monitors, and hotkey handling. These feed the app’s interaction model for showing hidden items, toggling sections, invoking search, and responding to mouse/keyboard gestures. Accessibility and related permissions are first-class because the app needs to inspect and manipulate other apps’ menu bar items.
4. Menu bar item discovery boundary
MenuBarItemService is the system-facing boundary for enumerating and tracking menu bar items. It includes a listener and PID cache, and the app connects to it through MenuBarItemServiceConnection. This is the most important process boundary in the architecture: the service observes the OS/menu bar space, while the main app consumes item metadata and turns it into layout decisions.
5. Item model and layout engine
The Thaw/MenuBar/MenuBarItems subsystem contains the core layout logic. LayoutSolver and LayoutReconciler decide where each item belongs, how hidden/always-hidden sections are formed, and how changes are applied over time. Supporting pieces like PendingLedger, tag types, and image caches track unresolved moves, identities, and item rendering state.
6. Menu bar presentation layer
Rendering is split into dedicated visual components: LayoutBar for arranged menu bar content, IceBar for the separate bar shown below or around the menu bar, and overlay/panel types for transient UI. The ControlItem views and icons represent the app’s own controls inside the bar. The layout UI is clearly separated from the discovery and reconciliation logic.
7. Appearance customization subsystem
Appearance is handled by a dedicated set of managers, editor panels, and configuration models. This covers tint, gradients, shadows, borders, shapes, and dark/light variants. The MenuBarAppearanceManager and the versioned configuration types indicate persistence/migration of appearance settings over time rather than a purely ephemeral UI state.
8. Settings and profiles
The settings system is broad and modular: general, advanced, automation, hotkeys, display, menu bar appearance, menu bar layout, and profile panes each map to their own model layer. ProfileManager and related models support applying different layouts/configurations, while SettingsResetter, import/export helpers, and migration utilities show that settings are treated as durable app data with compatibility concerns.
9. Automation, hooks, and behavior policy
Beyond manual toggles, the app supports behavior rules such as re-hide strategies, app conflict detection, focus filtering, and hook scripts. HookRunner and automation settings suggest user-defined actions or scripts that run in response to menu bar state changes. This creates a policy layer above the raw layout engine.
10. UI structure and navigation
The app uses SwiftUI-style window and pane structure for onboarding, permissions, settings, and specialized editors/search panels. AppState and AppNavigationState coordinate what the user sees, while custom UI components under Thaw/UI provide consistent macOS-style controls, tooltips, recorders, and list/panel primitives. The app is not just a single window; it is a set of coordinated windows and sheets.
11. Lower-level platform support
VirtualDisplay and the Objective-C/bridging files indicate platform-specific support code for display-related behavior that macOS APIs alone do not fully provide. Shared utility code includes accessibility helpers, screen capture, mouse helpers, swizzling, localization, and window/space metadata extraction. These modules are the glue between macOS internals and the higher-level menu bar logic.
12. Data persistence and shared domain types
Shared models and utilities define the common language of the app: windows, sections, modifiers, keys, commands, profiles, settings, and diagnostic logging. These types are used across the UI, layout engine, hotkey system, and helper service, which keeps the architecture cohesive even though the app is split across multiple targets.
13. Notifications, onboarding, and updates
User-facing lifecycle concerns are handled separately from the menu bar engine. Onboarding introduces the app, permissions screens explain required access, notifications communicate important state, and an updates module manages version-related behavior. This keeps setup and maintenance flows distinct from the steady-state menu bar management path.
14. Build, packaging, and automation boundary
The repo includes GitHub Actions for build, DMG creation, signing, notarization, release, translation checks, and CI. ThawCtl is a separate SwiftPM-based companion utility likely used for control/packaging workflows. Tests are extensive and cover layout planning, profiles, menu bar shapes, settings, gates, and replay fixtures, which suggests the architecture is heavily algorithmic and regression-sensitive.
15. Overall request/response flow
In steady state, macOS events and hotkeys drive the main app; the app queries or receives menu bar item data from the helper service; layout/reconciliation computes the target arrangement; the UI presents bars, overlays, and settings; and persistent settings/profiles determine how the system behaves across launches. The cleanest diagram would show the helper/service, the event/input layer, the layout engine, the UI/appearance layer, and the persistence/settings layer as separate but connected subsystems.
Main entry points: AppState.swift App State · MenuBarItemManager.swift Item Manager · SettingsView.swift Settings · LayoutReconciler.swift Reconciler
Components 24
Main App
Primary Thaw application runtime and UI shell
- Thaw App · Main executable and app lifecycle
Thaw/Main/IceApp.swift - App State · Central application state and coordination
Thaw/Main/AppState.swift - Navigation · Window and pane navigation state
Thaw/Main/Navigation/AppNavigationState.swift - Onboarding · Introductory setup flow
Thaw/Onboarding/OnboardingSheet.swift - Permissions · Access prompts and status screens
Thaw/Permissions/PermissionsView.swift - Appearance · Theme, tint, shape, and overlay management
Thaw/MenuBar/Appearance/MenuBarAppearanceManager.swift - Updates · Version-related app behavior
Thaw/Main/Updates.swift
Menu Bar System
Discovery, layout, rendering, and search for menu bar items
- Layout Solver · Plans positions and hidden sections
Thaw/MenuBar/MenuBarItems/LayoutSolver.swift - Reconciler · Applies layout changes over time
Thaw/MenuBar/MenuBarItems/LayoutReconciler.swift - Item Manager · Coordinates item model and layout state
Thaw/MenuBar/MenuBarItems/MenuBarItemManager.swift - Layout Bar · Arranged menu bar content view
Thaw/MenuBar/LayoutBar/LayoutBar.swift - Ice Bar · Secondary bar and spacing presentation
Thaw/MenuBar/IceBar/IceBar.swift - Search · Search model and panel for items
Thaw/MenuBar/Search/MenuBarSearchPanel.swift
Settings & Policy
Persistent configuration, profiles, automation, and permissions
- Settings · Persistent settings models and panes
Thaw/Settings/SettingsView.swift - Profiles · Profile application and configuration sets
Thaw/Settings/Models/ProfileManager.swift - Automation · Hooks, re-hide rules, and conflict policy
Thaw/Utilities/HookRunner.swift
Shared & Platform
Cross-target services and lower-level macOS support
- Event Input · Event taps, HID, and local monitors
Thaw/Events/EventMonitor.swift - Hotkeys · Global shortcut definitions and registry
Thaw/Hotkeys/HotkeyRegistry.swift - Service Conn · App-side connection to the helper process
Thaw/MenuBar/MenuBarItems/MenuBarItemServiceConnection.swift - Shared Types · Cross-target constants, models, and helpers
Shared/Utilities/SharedConstants.swift - Platform Glue · Accessibility, display, window, and swizzling helpers
Thaw/Utilities/Helpers.swift
Helper Service
Separate process that observes menu bar items
- Item Service · Menu bar item discovery and monitoring service
MenuBarItemService/main.swift - Listener · Listens to system menu bar events
MenuBarItemService/Listener.swift - PID Cache · Tracks process identifiers for menu bar items
MenuBarItemService/SourcePIDCache.swift
Connections 26
- Thaw App → App State: owns · App lifecycle drives the shared app state
- App State → Navigation: coordinates · App state controls navigation and visible panes
- App State → Onboarding: presents · First-run flow is controlled by app state
- App State → Permissions: requests · Permission screens are surfaced from app state
- App State → Settings: binds · Settings are loaded and edited through the app
- Event Input → Hotkeys: feeds · Input events and shortcuts drive interactions
- Hotkeys → App State: triggers · Hotkey actions update app state and UI
- Event Input → Platform Glue: uses · Low-level event handling depends on platform helpers
- App State → Service Conn: queries · Main app consumes item metadata from helper process
- Service Conn → Item Service: connects · IPC boundary to the helper process
- Item Service → Listener: observes · Helper process listens to menu bar space events
- Item Service → PID Cache: tracks · Helper process maintains PID lookup state
- Service Conn → Item Manager: updates · Received item data updates the item domain model
- Item Manager → Layout Solver: plans · Item manager delegates arrangement to the solver
- Layout Solver → Reconciler: hands off · Planned layout is reconciled into incremental changes
- Reconciler → Layout Bar: renders · Reconciled state is shown in the arranged bar
- Reconciler → Ice Bar: renders · Secondary bar presentation reflects layout state
- Item Manager → Search: supports · Search operates over managed menu bar items
- App State → Appearance: configures · Appearance settings affect the visible menu bar UI
- Settings → Profiles: contains · Profiles are part of persistent settings
- Settings → Automation: contains · Automation and behavior policy live in settings
- Profiles → Item Manager: applies · Profiles reshape menu bar layout and item state
- Automation → Item Manager: influences · Hooks and policy modify layout and re-hide behavior
- Settings → Shared Types: uses · Settings reuse shared domain types and constants
- Platform Glue → Item Manager: supports · Platform helpers back item inspection and control
- Updates → App State: signals · Update lifecycle affects app state and user flow