Architecture

June 11, 2026 ยท View on GitHub

Hidden Bar is a single-process, sandboxed AppKit menubar utility (~1.5k lines of Swift, one dependency: HotKey). There is no helper app, no daemon, no network. Everything happens inside three NSStatusItems and one window.

The core trick

macOS offers no API to hide other apps' menubar icons. Hidden Bar fakes it with geometry: a separator status item whose length is inflated to roughly the width of the widest attached screen, shoving every icon to its left off-screen. Collapsing and expanding is just flipping that length between ~20pt and the inflated value.

flowchart LR
    subgraph menubar [menu bar, right to left]
        direction RL
        ARROW["arrow item\n(toggle, variable length)"]
        SEP["separator item\n20pt expanded / ~2x screen width collapsed"]
        HIDDEN["other apps' icons\npushed off-screen when collapsed"]
        ALWAYS["always-hidden separator\n(optional)"]
    end
    ARROW --- SEP --- HIDDEN --- ALWAYS

Key consequences of this design:

  • The menubar replicates on every display, so the collapse length derives from the widest screen (NSScreen.screens), never NSScreen.main, and is re-applied to the live item on didChangeScreenParametersNotification (display hot-plug).
  • The length is bounded: max(500, min(widestFrameWidth * 2, 10_000)). macOS enforces a hard 10,000pt maximum on NSStatusItem.length.
  • isCollapsed is derived state: separator.length > 20, deliberately not an equality check, so it survives the length being recomputed while collapsed.
  • Icons macOS inserts to the LEFT of the separator (where new status items appear) are in the hidden zone by default; that is inherent to the trick.

Topology

flowchart TD
    AD[AppDelegate] -->|owns| SBC[StatusBarController]
    AD -->|registers| SM["SMAppService.mainApp\n(login item, macOS 13+)"]
    AD -->|global hotkey| HK[HotKey lib]
    SBC -->|3 status items| NSB[NSStatusBar.system]
    SBC -->|auto-hide| T["one-shot Timer\n(re-arms while pointer in menubar)"]
    SBC -->|opt-in| HM["global mouseMoved monitor\n(hover-to-expand, only if pref on)"]
    PREFS[Preferences facade] -->|UserDefaults| UD[(UserDefaults)]
    PREFS -->|posts| NC{{NotificationCenter\n.prefsChanged / .alwayHideToggle}}
    NC --> SBC
    PVC[PreferencesViewController] --> PREFS
    SBC -->|context menu| PVC
  • AppDelegate (entry): registers default prefs, sets up the global hotkey, runs the one-shot legacy login-item migration, owns the StatusBarController.
  • StatusBarController (the product, ~370 lines): the three status items, collapse/expand, auto-hide timer, interaction-awareness, hover-to-expand, self-restore of dragged-off items.
  • Preferences (facade enum): typed accessors over UserDefaults; setters post NotificationCenter notifications that the controller and prefs window observe. There is no other state store.
  • PreferencesViewController / PreferencesWindowController: the only window (storyboard-based), shown on demand from the context menu.

Behavior layers on the core trick

LayerMechanismCost when unused
Auto-hideone-shot Timer after expand; at fire, if the pointer sits in any screen's menubar band (visibleFrame.maxY ... frame.maxY), it re-arms instead of collapsingnone (single point-in-rect check at fire)
Hover-to-expand (opt-in)global .mouseMoved monitor + 0.5s dwell timer; installed only when the hoverToExpand default is true at launchzero: monitor not installed
Self-restoreisVisible = true forced on our items at launch; Cmd-dragging them off otherwise bricks the app (its only UI is those items)none
Always-hidden sectiona second separator item; its own length games, gated by alwaysHiddenSectionEnableditem not created

Autostart

macOS 13+ SMAppService.mainApp: the app registers itself; the login item is visible and revocable in System Settings > General > Login Items. On first launch after upgrade, a one-shot migration deauthorizes the legacy com.dwarvesv.LauncherApplication helper registration (the BTM database never garbage-collects those; see Apple TN3111). The helper app itself is gone.

Security posture

Sandboxed (com.apple.security.app-sandbox), hardened runtime, no network entitlement, no file I/O, no IPC surface, no shell or subprocess use. The only dependency is HotKey (a small Carbon RegisterEventHotKey wrapper) locked by the committed Package.resolved. The opt-in hover monitor observes pointer position only and discards event payloads. About-window links are hardcoded. A full-tree audit (2026-06) scored 9/10 with hygiene-level findings only.

Known architectural limits

  • The notch: hidden icons sit "under" the notch area on notched Macs; the trick cannot reveal them there. The real fix is a spillover/second-bar design (tracked in issues #357/#341/#148; candidate implementations in PRs #350/#358).
  • macOS 27: the menu bar re-architecture in macOS 27 betas (NSMenuBarNavigationSceneExtension) breaks length-inflation hiding entirely (issue #360). A different mechanism may be required.
  • Other apps' open menus: interaction-awareness is pointer-position-based; a pointer deep inside another app's open dropdown is below the menubar band, so the collapse can still fire there.