← ClaudeAtlas

swift-menubar-notarized-applisted

Use when building a macOS menu-bar (status item) app in Swift with SwiftPM and no Xcode project — covers bundling the .app, LSUIElement agent setup, login items, the NSStatusItem/popover gotchas, and Developer ID signing + notarization for sharing.
AnywaySolutionsSro/claudemeter · ★ 1 · AI & Automation · score 67
Install: claude install-skill AnywaySolutionsSro/claudemeter
# Building a notarized macOS menu-bar app with SwiftPM A menu-bar utility with no Xcode project. SwiftPM builds a bare executable; a shell script wraps it into a signed `.app`. Split a pure, testable **core** library from the AppKit **app** target. ## Bundle assembly (no Xcode) `swift build -c release` produces an executable, not an app. Assemble the bundle: ``` ClaudeMeter.app/Contents/ MacOS/ClaudeMeter # the built binary Info.plist # LSUIElement=true, CFBundleIconFile, bundle id, NSPrincipalClass=NSApplication Resources/AppIcon.icns ``` - `Info.plist` must set `LSUIElement = true` (menu-bar agent: no Dock icon / window) and `CFBundleIconFile`. In `main.swift` also call `NSApp.setActivationPolicy(.accessory)`. - Build with `MainActor.assumeIsolated { ... NSApplication.shared.run() }` in `main.swift` to construct a `@MainActor` app delegate from the nonisolated top-level entry. - Generate `.icns`: draw PNGs at the iconset sizes (16…1024 + @2x) via Core Graphics, then `iconutil -c icns AppIcon.iconset -o AppIcon.icns`. ## Status item + popover gotchas (the important part) - **`.transient` popovers don't auto-close for an agent app** — the window never becomes key. Add a global mouse-down monitor (`NSEvent.addGlobalMonitorForEvents`) and close on outside click. - **No menu bar ⇒ no Cmd+V/C/X/A in text fields.** Install a minimal Edit menu with the standard selectors (`NSText.paste(_:)` etc., nil target → responder chain), set `NSAp