Build Bartender
A background agent that collapses the menu bar down to the icons you actually watch, keeps the rest one click or one hotkey away, applies per-application and per-condition rules, and is honest in its own interface about the fact that this entire category breaks on major macOS releases.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree if you already own a Mac
Why The entire build is menu bar behaviour, which cannot be developed or tested anywhere else.
Get it Apple menu, then About This Mac, to check the version.
Verify
About This Mac reports macOS 14 or higher - installfree
Why Builds and signs the agent.
Get it Mac App Store or developer.apple.com/xcode. Large download, start it early. open ↗
Verify
xcodebuild -version prints 16 or higher - decidefree
Why Redrawing hidden icons is impossible without it, and users are right to treat the prompt seriously. You need a sentence you believe before you ask anyone else to accept it.
Get it System Settings, then Privacy and Security, then Screen Recording. During development the grant must be re-given whenever the binary path or signature changes.
Verify
Capture returns menu bar pixels rather than a black frame - have readyfree
Why The mechanism is invisible on a tidy bar, and the segmentation code in Phase 2 needs real variety in icon widths to be worth anything.
Get it Install a handful of applications that add menu bar items, or borrow a colleague's cluttered machine for an hour of testing.
Verify
Your menu bar has enough items that some are pushed off on a narrow display - account99 USD per year
Why Product phase only. No Developer ID means no notarization, and for this category the update channel matters more than usual because macOS releases break it.
Get it Enrol at developer.apple.com/programs. Review takes a day or two. open ↗
Verify
A Developer ID Application certificate appears in Xcode settings
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- items(id, bundle_id, title, last_seen_at, hidden, always_visible, position) · one row per menu bar item you have observed - rules(id, item_id, trigger, condition_json, action) · trigger is app_activated, time_of_day, battery_state or manual - profiles(id, name, active) · a named set of hidden and visible assignments, for example presenting versus working - settings(key, value) · hotkey, spacer width, whether the hidden row auto-collapses and after how long - Item identity is the owning bundle identifier plus a stable title where one exists, because index position changes every time any application adds or removes an item.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
BAR_SETTINGS_PATH | required | ~/Library/Application Support/Bar/settings.plist | Where rules, profiles and layout are stored. |
BAR_AUTOCOLLAPSE_SECONDS | required | 8 | How long the revealed row stays open before collapsing. Zero disables auto-collapse. |
BAR_VERIFIED_MACOS | required | 15.4 | The last macOS version this build was tested against. Shown in the interface and used for the untested-version caution. |
SPARKLE_FEED_URL | optional | https://example.com/appcast.xml | Product phase only. Where the signed appcast is published. |
The build, in order
Agent, status item and the spacer
Your own icon sits in the menu bar and can push other icons out of sight.
SwiftUI app with Application is agent set to YES in Info.plist, and a MenuBarExtra so there is something to click before anything else works.
Files
Info.plistApp.swiftNSStatusItem with a length you set programmatically. Animate changes, because an instant jump reads as a glitch rather than an action.
Files
Spacer.swiftWrite the current width and collapsed state to a property list in Application Support and restore it on launch.
Files
Settings.swift
done when · tick each as it passeswatch out- There is no public API to hide another application's menu bar item. Anyone promising one is describing the spacer trick with better marketing. Understanding that early stops you searching for an API that does not exist.
Seeing the bar, which means asking for Screen Recording
You can enumerate and redraw the icons you have displaced, and the user understands why that needs a serious permission.
Your own panel first, saying what is captured and what is not. Then CGRequestScreenCaptureAccess. A permission this broad deserves a sentence you wrote.
Files
Permissions.swiftSCStreamConfiguration limited to the menu bar strip. Segment on the gaps between items rather than assuming a fixed icon width, because widths vary.
Files
BarCapture.swiftDraw the captured icons in your own window below the bar. On click, synthesise a click at the real item's coordinates.
Files
HiddenRow.swiftHiding still works, because the spacer needs no permission. Only the redraw does. Say which half is unavailable rather than disabling everything.
Files
Permissions.swift
done when · tick each as it passeswatch out- Every menu bar manager needs Screen Recording, because redrawing an icon your process did not create means capturing pixels it did not draw. Users are right to hesitate at that prompt. Explain it in your own words before the system asks, and say plainly that you can see the whole screen and choose not to look at it.
- The grant is bound to your code signature, so re-signing invalidates it and macOS will not prompt again. During development this will catch you repeatedly.
Rules and profiles
The bar rearranges itself for the situation instead of needing you to fiddle with it.
NSWorkspace notifications for activation and deactivation. This needs no additional permission and is the most useful trigger.
Files
Rules.swiftStore the owner rather than the slot. Add a test that shuffles observed positions and asserts the same items are chosen.
Files
Items.swiftA named set with one active at a time, switchable from the menu and from a hotkey later.
Files
Profiles.swift
done when · tick each as it passeswatch out- Menu bar items move constantly as applications launch and quit, so a rule keyed to position will act on the wrong icon within a day. Key on the owning bundle identifier and treat position as presentation only.
Hotkey, search and keyboard control
You never have to aim at a small icon with the mouse.
RegisterEventHotKey and a Carbon handler. Confirm in System Settings that your application is not listed under Accessibility.
Files
Hotkey.swiftFilter by application name and item title. Items you have seen before are searchable even when currently hidden.
Files
Search.swiftArrows to move, Return to activate, Escape to dismiss and restore focus.
Files
HiddenRow.swift
done when · tick each as it passeswatch out- Register the hotkey with RegisterEventHotKey rather than a global event monitor. The monitor route needs Accessibility, which is a second serious permission on top of Screen Recording, and asking for two makes users refuse both.
Surviving the operating system
When a macOS release breaks the mechanism, the application says so instead of appearing broken.
Grow the spacer, capture, and assert the bar contents changed. Run it on launch and on demand from the menu.
Files
SelfTest.swiftA banner naming the macOS version and the specific capability that failed, with a link to your release notes.
Files
Diagnostics.swiftBake in the last macOS version you tested and compare at runtime. Show a caution above it rather than a hard block.
Files
Info.plist
done when · tick each as it passeswatch out- Menu bar management sits on undocumented behaviour, and major releases break it for everybody at once. macOS 27 betas broke essentially every application in this category, including the commercial ones. A build that fails silently looks like your bug; a build that says the operating system changed is telling the truth and saves you a support thread.
Signing, notarization and updatesproduct builder
Someone else can install it, and you can ship the fix the next macOS release will demand.
Hardened runtime, Developer ID Application, notarytool, stapler.
terminalcodesign --force --options runtime --sign "Developer ID Application: YOUR NAME" Bar.app xcrun notarytool submit Bar.zip --keychain-profile AC --wait
An EdDSA key pair with the private half outside the repository, and appcast.xml served over HTTPS.
Files
appcast.xmlOne paragraph telling users to remove the stale Screen Recording entry after the first signed update.
Files
RELEASE_NOTES.md
done when · tick each as it passeswatch out- Your first signed release invalidates the Screen Recording grant your testers gave the unsigned build, and macOS will not re-prompt. Put the removal instructions in the release notes rather than in a support reply.
That is the whole plan for Bartender. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Any guarantee across major macOS releases. This category breaks and then gets fixed, every year.
- The interaction polish that commercial alternatives have accumulated.
- Settings sync between machines.
- Support for the cases where the underlying mechanism only half works, which is most of what you are paying for.
- deep macOS menu-bar handling, OS update compatibility, and polished interaction
- years of OS-version edge cases
- large extension ecosystem
- cross-device sync
- commercial support and rapid compatibility fixes
- A presenting profile that hides everything except the clock
- Per-display rules, because an external monitor changes how much bar you have
- Importing an existing configuration from another menu bar manager
Need the files? The project pack on the verdict page hands your agent the whole brief · more productivity utilities.