Files
TZGyn 30d5aff906 Notarize releases so macOS opens the app without a warning
Gatekeeper blocked the app on other machines because it was signed but
not notarized. Sign with a secure timestamp and submit to Apple during
release, so a stapled ticket ships in the zip.

💘 Generated with Crush

Assisted-by: Crush:deepseek-v4.1-flash
2026-09-28 12:19:39 +08:00

96 lines
3.9 KiB
Markdown

# 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, the input-source indicator, Spotlight, Clock,
Battery and Control Center** visible, with the **hamburger at the left edge of
that group**. The spacer's boundary (preferred position 330) falls just left
of the input-source indicator. macOS reserves the far-right area, so an item
can never be placed to the right of the system icons.
- 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
```bash
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. Releases from 0.4.8 on are notarized,
so the app opens without a Gatekeeper warning.
## Upgrade
```bash
brew update
brew upgrade --cask simpletopbar
```
If Gatekeeper still blocks the app after upgrading (it is not notarized yet):
```bash
xattr -dr com.apple.quarantine /Applications/SimpleTopBar.app
```
## Build from source
```bash
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](https://gitea.tzgyn.dev/TZGyn/homebrew-tap).