Technical Documentation: dwarvesf/hidden
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (`README.md`)
Hidden Bar
Hidden Bar lets you hide menu bar items to give your Mac a cleaner look.
π Install
ο£Ώ App Store
Others
The Hidden Bar is notarized before distributed out side App Store. It's safe to use π
Using Homebrew
brew install --cask hiddenbarManual download
- Download latest version
- Open and drag the app to the Applications folder.
- Launch Hidden and drag the icon in your menu bar (hold CMD) to the right so it is between some other icons.
πΉ Usage
β+ drag to move the Hidden icons around in the menu bar.- Click the Arrow icon to hide menu bar items.
π Documentation
- Manual: every setting, the hidden Terminal-only options, and troubleshooting.
- Architecture: how the hiding trick works, topology, and known limits.
- Maintainer runbook: build, behavioral verification, and release process.
β¨[Contributors](https://github.com/dwarvesf/hidden/graphs/contributors)
This project exists thanks to all the people who contribute. Thank you guys so much π
Please read this before you make a contribution.
Requirements
macOS version >= 13.0 (Ventura)
Running an older macOS? The last release supporting macOS 10.13 High Sierra
through 12 Monterey is v1.10.
Later versions require macOS 13 because autostart moved to the SMAppService
API introduced there.
You may also like
- Blurred - A macOS utility that helps reduce distraction by dimming your inactive noise
- Micro Sniff - An ultra-light macOS utility that notify whenever your micro-device is being used
- VimMotion Vim style shortcut for MacOS
License
MIT © Dwarves Foundation
ARCHITECTURE (`docs/ARCHITECTURE.md`)
Architecture
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 threeNSStatusItems 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 --- ALWAYSKey consequences of this design:
- The menubar replicates on every display, so the collapse length derives from
the widest screen (NSScreen.screens), neverNSScreen.main, and is
re-applied to the live item ondidChangeScreenParametersNotification
(display hot-plug). - The length is bounded:
max(500, min(widestFrameWidth * 2, 10_000)). macOS
enforces a hard 10,000pt maximum onNSStatusItem.length. isCollapsedis 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| PVCAppDelegate(entry): registers default prefs, sets up the global hotkey,
runs the one-shot legacy login-item migration, owns theStatusBarController.StatusBarController(the product, ~370 lines): the three status items,
when to collapse/expand, auto-hide timer, interaction-awareness, hover-to-expand,
self-restore of dragged-off items.MenuBarEngine(Features/StatusBar/Engine/): how hiding is achieved.
The controller callscollapse/expand/updateAlwaysHiddenSection/invalidateLayoutand never writes a status-item length itself.MenuBarEngineFactoryis the one place that picks an engine for the running
OS; today that is alwaysLegacyLengthEngine(the length trick below).Preferences(facade enum): typed accessors overUserDefaults; setters
postNotificationCenternotifications 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
| Layer | Mechanism | Cost when unused |
|---|---|---|
| Auto-hide | one-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 collapsing |
none (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 launch |
zero: monitor not installed |
| Self-restore | isVisible = true forced on our items at launch; Cmd-dragging them off otherwise bricks the app (its only UI is those items) |
none |
| Always-hidden section | a second separator item; its own length games, gated by alwaysHiddenSectionEnabled |
item 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 legacycom.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.
BACKLOG (`docs/BACKLOG.md`)
Backlog
Durable, committed index of open work. The detailed planning layer
(_meta/megagoals/issue-list-clearing/ and .claude/) is local-only and gitignored,
so this file is the version that survives a machine switch and a fresh clone. Keep it
short: one line per item, pointing at the issue, SPEC, or file that holds the detail.
Source of the current state: the v1.11 issue-clearing pass (2026-06-12), branchfix/v1-11-batch / draft PR #365, and SPEC-003. Core-model changes (separator length
math, collapse state machine) are HIGH RISK and require a mandatory review-team pass.
macOS 27 (#360)
- Direct build ships native hiding (
NativeVisibilityEngine, Debug-Direct /
Release-Direct configurations). Uses privateMenuBarClientCore; not App Store safe. - App Store build still broken on 27. The sandbox denies
mach-lookup com.apple.axserver, so the sections cannot be read even with Accessibility granted
(measured 2026-09-18). Options: a user-picked list of visible apps instead of β-drag
(no Accessibility, still private API), or a public mechanism if Apple ships one. - Direct build bundle id. Tested as
com.dwarvesv.minimalbar.direct; decide whether
release keepscom.dwarvesv.minimalbar(shared prefs, cannot coexist with the App
Store copy) or ships separately. - Tutorial text still describes the
|separator; the direct build on 27 uses the
arrow as the boundary. Needs a per-build string. - Adaptive-width experiment (
fix/macos27-adaptive-engine, local only): calibrating
the separator width does not hide on a 1920pt non-notched display. Kept for reference.
Blocked on external-display hardware
- #351 external-monitor visible-bar (26.4) verification. The widest-attached-screen
fix is code-only; the 26.4 + external-display reproduction was never run. Confirm no
full-width bar leak on a real second monitor.
Actionable now (no special hardware)
- UAT + merge draft PR #365. Per the local
UAT.md(one row per fix, click-through
steps). Merge order matters (stacked dependency). Merge is Han's action, not the agent's. - Cut the v1.11 release. Version + CHANGELOG staged in #365. Needs a Developer ID for
notarization + App Store submission. Shipping answers the "is this still maintained?"
issues and unblocks the round-2 close sweep. - Upgrade-path BTM verification before any signed release. Install a pre-v1.11 build,
update to v1.11, confirm Login Items shows no leftoverLauncherApplicationrow (the
one-shotSMLoginItemSetEnabled(..., false)deauth was added but never run on hardware). - AXPress accessibility defect. VoiceOver users cannot toggle the bar: the arrow's
AXPresshandler readsNSApp.currentEvent, which is nil under assistive synthesis. hoverToExpandPreferences checkbox. Shipped as a Terminal-onlydefaults write;
add a proper checkbox inPreferencesViewController.- Surface the
SMAppServiceerror contract in the prefs UI. Onregister()failure
(unsigned build, or user denies in System Settings), the checkbox stays on while the
system says off; the error is swallowed into NSLog. Fix when the prefs UI is next touched.Common/Util.swift:29-31. - Round-2 issue close sweep (~35 issues). Obsolete-OS + meta/support candidates,
deferred until v1.11 ships so the closures carry the strongest answer. - 24h memory dogfood (#361). Instruments stress-cycling found no leak; run v1.11 as
the daily driver for 24h on the Air to close the open report. - Old branch decision.
feature/menubarDetection(PR #115) andfeature/ghost-mode
(PR #57) were kept per never-delete. Review or discard, Han's call.
v1.12 standalone wins (no Option D needed)
- #207 show clock/date when collapsed. Loudest single feature ask (18+ comments).
- #355 prefs window layout overlap. #324 single-instance guard. #276 Cmd+W
closes the prefs window. Appearance bundle via community PR #194.
Architectural epic (Option D, #366)
- Managed-overflow / second-bar redesign. The real fix that gates ~30 issues across
four clusters: icon-drift (#28, #156, #181, #230, #231, #239, #252, #254, #275, #283,
#321, #334), always-hidden (#171, #224, #242, #288), notch (#206, #225, #228, #245,
#267, #269, #280, #292, #330), and macOS 27 (#360). Replaces length-inflation with a
managed overflow bar, likely via Accessibility. Needs a design decision from Han +
macOS 27 hardware. Design + folded M1 (pin icons, persist order) / M2 (decouple
always-hidden fromareSeparatorsHidden, recover stuck items) in SPEC-003. - Security + behavior review of community PRs #358 and #350 first. #358 (second bar,
+1160 lines) and #350 (notch overflow, +429 lines) are the existing starting points.
Do not merge on description alone; #358 especially needs a real review. - #242 permanent icon-loss repro. Needs a throwaway defaults profile (live repro
risks losing real menu-bar icons). Required before the always-hidden decouple lands.
MANUAL (`docs/MANUAL.md`)
Manual
Everything Hidden Bar can do, including the parts with no UI.
Basics
- Left-click the arrow (
</>): expand or collapse the hidden section. - Right-click the arrow or left-click the separator (
|): context menu
(Preferences, Toggle Auto Collapse, Quit). - β-drag icons in the menu bar to move them across the separator: icons to
the separator's left are hidden when collapsed. - Option-click the arrow: show/hide the separators and the always-hidden
area without expanding.
macOS 27, direct download build
The direct (non-App Store) build hides icons natively on macOS 27, and the
arrow itself is the boundary: there is no | separator. β-drag icons to
the arrow's left to hide them when collapsed, to its right to keep them
visible. The always-hidden separator still appears (while expanded) when that
section is enabled.
- Needs Accessibility permission (System Settings βΊ Privacy & Security βΊ
Accessibility) to see where your icons are. Without it the bar stays
expanded. - Hiding is per app: an app with several icons hides or shows them together.
- macOS's own items (clock, Wi-Fi, Sound, Control Center) always stay visible.
- Run Hidden Bar from
/Applications; macOS only recognizes that copy as
Hidden Bar, and a copy elsewhere hides its own arrow.
Preferences window
| Setting | What it does |
|---|---|
| Start Hidden Bar when I log in | Login item via System Settings (macOS 13+ SMAppService); revocable in System Settings > General > Login Items |
| Show preferences on launch | Open this window at app start |
| Auto collapse | Re-hide automatically after the chosen delay |
| Global shortcut | System-wide expand/collapse hotkey (F-keys display as F18, not Fn18) |
| Enable always hidden section | A second zone whose icons stay hidden even when expanded; revealed by option-clicking the arrow |
| Use full menu bar on expanding | App becomes briefly "regular" while expanded (helps on tight menubars) |
Always-hidden section, current behavior: items in the always-hidden zone
are reliably pushed off-screen only when "hide separators" is also on
(option-click the arrow). With the separators visible, always-hidden items can
still appear after expanding. This coupling is a known limitation being
reworked alongside the menu-bar redesign; for now, option-click to hide the
separators if always-hidden items keep showing. Avoid placing critical icons in
the always-hidden zone until the rework lands, since a stuck off-screen item has
to be recovered by β-dragging it back (macOS persists its position per app).
Behaviors you get for free
- It won't collapse mid-use: while your pointer is anywhere in the menu bar,
the auto-collapse countdown defers and restarts; it resumes when you leave. - Self-repair: if the arrow or separator was β-dragged off the bar (which
used to make the app unreachable forever), they come back on next launch. - Display changes: plugging in or removing monitors re-sizes the hidden zone
for the widest attached screen automatically.
Hidden settings (Terminal)
All via defaults; quit and relaunch the app after changing them.
# expand by hovering the menu bar for ~0.5s (off by default)
defaults write com.dwarvesv.minimalbar hoverToExpand -bool true
# auto-collapse delay in seconds (the UI offers a fixed list; any value works)
defaults write com.dwarvesv.minimalbar numberOfSecondForAutoHide -float 5
# force the app language regardless of system order (issue #287)
defaults write com.dwarvesv.minimalbar AppleLanguages '(en)'To undo any of them: defaults delete com.dwarvesv.minimalbar <key>.
Troubleshooting
| Symptom | Fix |
|---|---|
| Icons I want visible got hidden after an update | β-drag them to the right of the separator |
| Login item missing after denying it once | System Settings > General > Login Items: re-enable Hidden Bar, then toggle the pref off/on |
| A ghost "LauncherApplication" login item from old versions | Launch the current version once; it deauthorizes the legacy item automatically |
| App language stuck | See the AppleLanguages command above, or System Settings > General > Language & Region > Applications |
| Nothing hides on a macOS 27 beta | Known (issue #360); the menu bar re-architecture broke the hiding mechanism, fix under investigation |
| A new or just-updated app's icon shows up already hidden | Expected, see "Why new icons start hidden" below; β-drag it to the right of the separator once |
Why new icons start hidden
Hidden Bar hides icons by widening its separator so everything to the left of
it slides off-screen. macOS always inserts a brand-new menu-bar icon at the
far-left slot, which is inside that hidden zone, so a freshly launched or updated
app can appear "swallowed". This is macOS positioning behavior, not Hidden Bar
moving your icon: there is no way for one app to reposition another app's menu-bar
icon. The one-time fix is to β-drag the icon to the right of the separator;
macOS remembers that placement per app. A built-in way to keep chosen icons
pinned is being explored as part of the larger menu-bar redesign.
Requirements
macOS 13 Ventura or later. Pre-Ventura (10.13 - 12.x): use
v1.10, the last release
on the old autostart mechanism.
RUNBOOK (`docs/RUNBOOK.md`)
Maintainer runbook
Build, verify, and release Hidden Bar. Assumes current Xcode on macOS 13+.
Build
# CI-style build, no signing required
xcodebuild -project 'Hidden Bar.xcodeproj' -scheme 'Hidden Bar' \
-configuration Debug CODE_SIGNING_ALLOWED=NO build
# runnable local build (uses your Apple Development identity)
xcodebuild -project 'Hidden Bar.xcodeproj' -scheme 'Hidden Bar' \
-configuration Debug buildBoth must exit 0 with no MACOSX_DEPLOYMENT_TARGET override; the floor is
13.0 in the project file. The single expected warning is the deliberately
deprecated SMLoginItemSetEnabled(false) call that cleans up legacy installs.
Behavioral verification (no test target exists; this is the methodology)
The repo has no unit-test infrastructure; behavior is verified against the real
menu bar. Two building blocks make that scriptable:
- Truth signal: the separator's AX size.
osascript -e 'tell application "System Events" to tell process "Hidden Bar" to get size of menu bar item 2 of menu bar 2'
reads ~20pt expanded vs ~2x-screen-width collapsed. Item 1 is the arrow. - Real clicks, not AXPress:
AXPresson the arrow is a no-op because the
action handler readsNSApp.currentEvent(nil under assistive synthesis;
known accessibility defect). Post realCGEventmouse clicks at the arrow's
AX-reported coordinates instead.
Standard checks before any release:
- expand/collapse toggle flips the separator size both ways;
- with
numberOfSecondForAutoHideset to 3, an expanded bar survives 2x the
window while the pointer is parked in the menubar band, collapses within the
window once the pointer leaves, and collapses normally if the pointer never
entered; hoverToExpandoff: no monitor log line, hover does nothing; on: dwell
expands (synthesize amouseMovedstream: cursor warping alone fires no
events);- autostart pref on ->
AutoStart: SMAppService.mainApp.status = 1on stderr;
off ->= 0(run the binary directly to capture stderr); - localization tables stay parseable:
plutil -lint hidden/*.lproj/*.strings.
When testing on a machine that runs Hidden Bar daily: export the prefs domain
first (defaults export com.dwarvesv.minimalbar backup.plist), quit the
installed app, test the dev build, then re-import and relaunch.
Release
Verify the stack: every PR reviewed, builds green, behavioral checks above run.
Bump
MARKETING_VERSION(all four Hidden Bar configurations) andCURRENT_PROJECT_VERSIONin the project file.Archive the GitHub build with the Hidden Bar scheme
(Release-Direct), then notarize (Developer ID), staple, zip, and publish a
GitHub release with notes listing closed issues. The Hidden Bar App Store
scheme archivesRelease, the sandboxed App Store build, which cannot hide
on macOS 27. v1.11 shipped that build to GitHub by mistake. Before zipping,
confirm the app is unsandboxed:shcodesign -d --entitlements - 'Hidden Bar.app' | grep app-sandbox # must print nothingApp Store (separate lane, Hidden Bar App Store scheme): the MAS listing
has lagged GitHub since v1.8 (issues #281/#202); decide deliberately whether
a release goes there too.Homebrew cask (
brew install --cask hiddenbar) follows the GitHub release
artifact; notarization matters (issue #219).Before any public release after the SMAppService migration: one
upgrade-path run from a launcher-era build (v1.9 or older) verifying System
Settings shows no ghost LauncherApplication login item.
Stacked-PR hygiene
Feature stacks land as chained PRs (develop <- A <- B). Merge the base PR
first, then retarget the next PR's base to develop BEFORE merging it;
deleting a merged branch auto-closes dependents otherwise.
Issue triage map
The live clusters and their code areas are documented at the end of
ARCHITECTURE.md: notch, macOS 27
mechanism break, and pointer-vs-open-menu limits. Memory reports (#361 et al.)
have so far not reproduced as leaks (constraint-leak fix landed; leaks clean
over toggle stress); re-check with a 24h+ uptime footprint sample before
chasing further.
--- METRICS ---
- Files Extracted: 5
- Estimated Token Budget: ~6062 tokens
- Canonical Reference: https://codewiki.google/github.com/dwarvesf/hidden