Starter¶
A menu bar app whose item is an NSStatusItem plus a nonactivating NSPanel instead of MenuBarExtra,
LSUIElement, no Dock icon. Made with Summon from its menubar-panel template. Same rules as the menubar
template: the app's job in the panel, Settings… and Quit in the footer, every preference in a separate
Settings window, a tested Core.
Which menu bar template?¶
Stay on menubar (MenuBarExtra(.window)) when the panel is opened only by clicking and its content is simple.
Take this one when the app needs any of these:
| Need | Why MenuBarExtra can't |
How this template does it |
|---|---|---|
| Open from a hotkey, URL or CLI | No API to open or close it from code | PanelController.open(), close(), toggle() |
| Typing while another app stays frontmost | Keystrokes need the app active, which takes the other app's menu bar | .nonactivatingPanel + canBecomeKey: the panel is key, the app is not active |
| Over fullscreen apps, on every Space | No control over the window | .statusBar level, .fullScreenAuxiliary, .canJoinAllSpaces |
| A live label (text, number, monospaced) | The label is re-rendered as an image with limited updates | PanelController.setLabel(title:accessibilityLabel:) on the status button |
Layout¶
| Path | What it is |
|---|---|
Sources/Starter/ |
@main only: the invisible opener window and the Settings scene |
Sources/StarterUI/StatusPanel.swift |
StatusPanel (NSPanel), PanelController, SettingsOpener |
Sources/StarterUI/AppDelegate.swift |
Creates the controller; keeps the label live with withObservationTracking |
Sources/StarterUI/PanelView.swift |
The panel: a live-data tile, one command per row, the footer |
Sources/StarterUI/Components.swift |
Menu rows with hover and key hints, the module tile, headers, dividers |
Sources/StarterUI/SummonTheme.swift |
.themed(): the Summon theme's accent on every window root, live |
Sources/StarterUI/Glass.swift |
.glassControl(): Liquid Glass on macOS 26, a material on 15; controls only |
Sources/StarterUI/SettingsView.swift |
Settings window: Open at Login (SMAppService), the menu bar toggle |
Sources/StarterUI/Onboarding.swift |
The first-run window: steps, permission cards with live status |
Sources/StarterUI/CloseOnlyWindow.swift |
.closeOnlyWindow(): dims minimize and zoom, no full screen (Settings, setup) |
Sources/StarterUI/Screenshots.swift |
--screenshot <folder>: the panel to PNGs, used by summon project shots |
Sources/StarterCore/ |
Logic, Foundation only, tested (SummonThemeFile reads the theme) |
Resources/ |
Info.plist (bundle id local.summon.menubar-panel-starter, LSUIElement), AppIcon.icns |
Tests/StarterCoreTests/ |
swift-testing |
scripts/check.sh |
The gate: build, tests (scripts/test.sh, works without Xcode), plist, bundle |
Behavior¶
- Opens on a click on the icon, or from code.
- Closes on Esc, on a click anywhere else (the panel loses key), and on a Space change.
- Settings… closes the panel and opens the Settings window. SwiftUI's
openSettingsonly works inside a scene, so the request goes throughSettingsOpenerin an invisible, always-open window. - Keys while open: Return adds one, ⌘, opens Settings, ⌘Q quits, Esc closes.
- Right-click (or ⌃-click) the icon: a plain menu with Settings… and Quit.
- Show in menu bar (Settings): people decide whether the icon is there. Hidden, the app is reachable from code and by opening it again in the Finder, which shows Settings.
- First run: a 640 × 440 welcome window (
Onboarding.swift) ends by pointing at the menu bar icon. The app shows in the Dock only while it is open. Closing it skips it; Settings › Welcome shows it again. Add a permission card only for a permission the app can't work without (StarterOnboarding.permissions, empty by default). - Settings window: close only (minimize and zoom dimmed), 480 pt, changes apply at once.
To add a global hotkey, register it with Carbon's RegisterEventHotKey (no Accessibility permission needed) and
call panel.toggle().
Build and run¶
Requires macOS 15+ and Swift 6. No third-party dependencies.