Files
simpletopbar/README.md
T
TZGyn 4bc6b333dc Put the hamburger at the left of the visible icons
The hamburger was landing among the system icons. Move it to the left
edge of the visible group so it reads as the entry point rather than one
more status item.

💘 Generated with Crush

Assisted-by: Crush:deepseek-v4.1-flash
2026-09-27 10:40:27 +08:00

4.0 KiB

SimpleTopBar

A native macOS menu bar app: a hamburger menu in the menu bar whose panel collects every other app's menu bar (tray) icons, plus every app running on your Mac, into three sections:

  • Menu Bar — a tray of all other apps' menu bar items, discovered through the Accessibility API. It is split into Apps and System sections. Click one to open its real menu. Optionally hide the items from the menu bar so they only live inside this panel (best-effort; see below).
  • Apps — regular apps that live in the Dock.
  • Background Apps — accessory/agent apps without a Dock icon. This section is a dropdown: it stays collapsed to a single header, and when you expand it only the first few apps are shown. The rest are hidden behind a Show N more row so the list never overflows the panel.

Click any row to activate the app, or right-click for Activate / Hide / Quit.

Accessibility permission

Collecting and opening other apps' menu bar items needs Accessibility permission (System Settings → Privacy & Security → Accessibility). The panel prompts for it; without it the Menu Bar section is empty and everything else still works.

Hiding menu bar items (best-effort)

macOS has no public API to move another app's status item. The Hide items from the menu bar toggle uses the spacer technique: a zero-width status item is created at launch whose length is expanded to push the other icons off-screen so they only live in this panel. It is on by default (the choice is remembered), always undone on quit, and if the app dies macOS removes the spacer automatically.

What it can and cannot hide:

  • It hides other third-party apps' icons (cmux, Kapture, moomoo, WireGuard).
  • It keeps Wi-Fi, Now Playing, Spotlight, Clock, Battery and Control Center visible, with the hamburger at the left edge of that group. The spacer's boundary (preferred position 300) falls just left of Now Playing. macOS reserves the far-right area, so an item can never be placed to the right of the system icons.
  • The input-source indicator is the one system icon that ends up hidden (it sits immediately left of where the hamburger can go). To keep it, set defaults write dev.tzgyn.simpletopbar debug.spacerPos -float 350 (and debug.hamburgerPos -float 100), which moves the hamburger one slot right.
  • Newly launched apps are placed to the left of the spacer, so they are hidden automatically.
  • Advanced: set defaults write dev.tzgyn.simpletopbar debug.spacerPos -float <n> to move the boundary (larger = keep more icons; > ~400 starts leaking app icons back into the bar).

Install with Homebrew

brew tap TZGyn/tap https://gitea.tzgyn.dev/TZGyn/homebrew-tap.git
brew trust TZGyn/tap
brew install --cask simpletopbar

The tap is hosted on Gitea, so the full URL is required. Homebrew may print an "Unsupported tap" warning — it's harmless.

Upgrade

brew update
brew upgrade --cask simpletopbar

If Gatekeeper still blocks the app after upgrading (it is not notarized yet):

xattr -dr com.apple.quarantine /Applications/SimpleTopBar.app

Build from source

swift build                 # debug build
swift run SimpleTopBar      # run from terminal (app appears in the menu bar)
swift run SimpleTopBar --self-test   # headless check of the dropdown logic
./build-app.sh 0.2.0        # release build + SimpleTopBar.app bundle + icon + codesign
./release.sh 0.2.0          # build-app.sh + dist/SimpleTopBar.zip + sha256

Around the Background dropdown

The background section is collapsed by default. Expanding it reveals AppListModel.backgroundPageSize (5) apps at a time; when more are running a Show N more button reveals the next page. Collapsing resets the page.

Releases

./release.sh <version> builds and zips the app to dist/SimpleTopBar.zip and prints its sha256. Tag v<version>, attach the zip to a release on the Gitea repo, and bump version/sha256 in the cask in TZGyn/homebrew-tap.