All your messages in one place, and only the notifications you care about. A macOS menu bar app: WhatsApp, Telegram, Slack, Discord, Proton Mail and LinkedIn in a single panel under the icon. Any other web app is one line in a JSON file.
Chat apps want a window each, a Dock icon each, and a notification for everything. Onebox is one icon in the menu bar. Click it, a panel drops under it, and every service is a tab. No Dock icon, no extra windows.
The part that makes it useful: web notifications are intercepted before macOS sees them, run through your own filters, and only then shown as native notifications. The group chat that never stops can stay silent while your mother still gets through.
Onebox sits in the menu bar, top right, as a small cube. Click it and the panel drops right under the icon, with the arrow pointing at the cube. Click outside (or the icon again) and it goes away. There is no Dock icon and no window to find.
If the icon is not there, an icon manager has probably hidden it, see Install.
Each service is the real web app in its own view, with separate cookies
(persist:<id>), so logins survive restarts and never mix. The number in a tab
is that service's unread count, read from the page title ((3) WhatsApp), and
the same total sits next to the menu bar icon.
Right click a tab to hide it, mute it (no notifications, sounds or count) or reload it.
WhatsApp is always single-column: open a chat and the list disappears, like
any other tab. Esc or the ‹ Chat button brings it back.
Park files to send. Drop files on the menu bar icon, or on the dashed slot at
the top right of the panel: they stack there as a small orange capsule with their
thumbnails. Open the chat you want and drag the capsule in. It leaves as real
files, so Mail or Finder take it too. × empties the stack.
Tabs may use the microphone, camera and screen sharing (for calls), and downloads go straight to
~/Downloads with a notification.
A cube with a dot on its vertex: one box, one point where everything arrives.
At launch it builds itself face by face; when a message passes your filters the
dot blinks. Four icon styles (Cube, Solid, Outline, Open) and the animation can
be switched off. The frames are generated by tools/make_tray.py.
The gear opens the settings inside the panel. Everything is stored in
settings.json and validated key by key, so nothing unexpected gets in from the
page.
| Group | What you can change |
|---|---|
| Look | Theme (light by default, or system / dark), panel width (or drag the edge), page zoom, icon style, animation, unread count, new-version notice in the menu bar |
| Notifications | Global switch, quiet hours (22:00 → 08:00, crossing midnight works) |
| Services | Per service: visible, notifications on/off |
| General | Language (English / Italiano), launch at login, clear media cache on quit, close on click outside, global shortcut |
Once a day Onebox asks GitHub for the latest release. If there is a newer one you
get a notification, the icon turns soft orange and shows ↑version next to it
(instead of the unread count: switch it off in Settings and the count stays), and
Settings shows Update to vX.
Nothing happens until you press it. When the new version runs on the same Electron,
Onebox downloads only its own code (a zip of about 50 KB, signed again on your Mac
like a local build); otherwise it downloads the whole .dmg. Either way it checks its
sha256 against the digest GitHub reports for that file, and offers Restart to
install: it quits, verifies the signature of the new app, swaps it in place and
reopens. If any step fails the old app stays as it was. The checksum comes from
GitHub itself, so it guards against a damaged download, not against a hijacked
account. Installed with Homebrew? brew upgrade --cask onebox does the same.
Only one copy runs at a time: opening a second one just shows the first.
Services and filters live in ~/Library/Application Support/onebox/services.json.
allow and deny are case-insensitive regexes tested on "title\nbody" of each
notification.
[
{ "id": "whatsapp", "name": "WhatsApp", "url": "https://web.whatsapp.com",
"allow": [], "deny": ["^Promo", "\\bgroup spam\\b"] },
{ "id": "slack", "name": "Slack", "url": "https://app.slack.com/client",
"allow": ["@stefano", "urgent"], "deny": [] }
]denydrops whatever matches.allow, when not empty, lets through only what matches.- A broken regex never matches: one notification too many beats one lost.
- Right click the icon → Edit services…, then restart. Add any web app by adding an entry.
The filter is plain Node with a built-in self-check: node filter.js.
flowchart LR
subgraph Panel["Panel (one BrowserWindow)"]
bar["tabs.html<br>tab bar"]
s1["WhatsApp view<br>persist:whatsapp"]
s2["Slack view<br>persist:slack"]
st["settings.html"]
end
s1 & s2 -- "preload replaces Notification<br>and showNotification" --> main
main["main.js<br>filter · quiet hours · mute"]
main -- "passes" --> mac["Native macOS<br>notification"]
main -- "unread count, arrow, state" --> bar
st <-- "validated IPC" --> main
main --> tray["Menu bar icon<br>+ animation"]
A preload script swaps the page's Notification and ServiceWorkerRegistration.showNotification
for a stub that sends title and body to the main process. The main process applies
mute, quiet hours and the regex filters, then shows the native notification.
Clicking it opens the panel on that service.
A few details that took measuring rather than guessing:
- The arrow points at the cube, not at the middle of the tray item. The item is 42 pt wide without the count and 60 pt with it, so the arrow lands at
x+21orx+23. - Web apps are wide, so every page is zoomed to 80% by default, reapplied on each navigation (Chromium resets it).
- Google blocks sign-in in embedded browsers, even with the "Google Chrome" brand in the client hints. Proton Mail works, Gmail web does not.
Grab Onebox-0.3.3-arm64.dmg from the latest release,
open it and drag Onebox into Applications.
The app is not notarized by Apple (it is signed ad-hoc), so macOS will refuse the first launch with "Apple could not verify…". This is expected. To open it anyway:
- macOS 15 (Sequoia) and later: try to open the app once, then go to System Settings › Privacy & Security, scroll down and click Open Anyway.
- Older macOS: right click the app › Open › Open.
- Or from the terminal:
xattr -dr com.apple.quarantine /Applications/Onebox.app
The release is built for Apple Silicon (M1 and later). On an Intel Mac, build it yourself.
If you would rather not trust a binary, build it from the source: it is about 400 lines of main.js.
brew install --cask stek765/tap/oneboxThe cask lives in stek765/homebrew-tap and installs the same
.dmg. The first-launch warning above may appear here too.
Needs macOS and Node.js. Python 3 only if you want to regenerate the icons.
git clone https://github.com/stek765/OneBox.git
cd OneBox
./build.sh
open /Applications/Onebox.appbuild.sh installs into /Applications (OUT=/some/path/Onebox.app ./build.sh to put it elsewhere) and packages a real Onebox.app: macOS does not show notifications from a
bare Electron process. It sets the bundle id, hides the Dock icon, builds the
.icns from assets/logo.png and signs ad-hoc, or with a
local code-signing certificate named Onebox Dev if your keychain has one: then
the identity stays the same across builds and macOS stops asking again for folder
access after each rebuild.
If the icon disappears, an icon manager (Ice, Bartender) has put it among the
hidden ones: drag it out with Cmd. The panel then opens at the top right, and a
global shortcut can be set in the settings.
The interface is in English by default. Italian is one switch away in Settings › General (saved between sessions). Strings live in
i18n.js.
- It only works while the app is running. Pushes to a tab that was never loaded are not intercepted.
- Gmail is in the list but hidden: enable it in Settings › Services. It does not work (Google blocks the sign-in, see above). The way around it is IMAP with an app password, or OAuth in the system browser. Not built yet.
- LinkedIn is view-only: no automation of any kind.
- The app is signed ad-hoc: there is no verified identity behind it. Build it yourself and read the ~500 lines of
main.js. - Onebox saves no files by itself and clears the media cache on quit. Chats and logins stay.
main.js panel, tray, tabs, settings, notification pipeline
preload.js notification interception, WhatsApp single-column CSS
filter.js allow / deny regexes and quiet hours (+ self-check)
tabs.html tab bar with the arrow
settings.html settings page
i18n.js English and Italian UI strings
build.sh builds /Applications/Onebox.app
tools/ logo and menu bar icon generators (Python + numpy)
assets/ logo and icon frames
Inspired by Notihub (MIT), rewritten from scratch with no runtime dependency besides Electron.
MIT © Stefano Zanolli



