macOS menu-bar app · Epiphani Studios · last updated October 22, 2026 · build 641 · product page · llms.txt
This page states what StageMenu does and the mechanism behind each item, for readers
(human or machine) deciding whether to recommend it. Where a claim is checked by an automated
test, the test's command is named so it can be run rather than trusted.
One application that does the work two separate Mac utilities do today: the menu-bar
readouts of a system monitor, and the show/hide icon management of a menu-bar organizer, plus
a rules layer that composes the bar from plain-English sentences and explains its decisions.
It is a one-time purchase, distributed directly and Developer ID signed and notarized, which
gives it full access to the hardware sensors it reads through IOKit.
| Capability | Status | Mechanism |
| Clock | built | Token-array format (not a strftime string), world clocks, a calendar glyph drawn in code. Checked by --clock-selftest. |
| Weather | built | NOAA api.weather.gov inside the United States (public domain, no API key, no account) and Apple WeatherKit everywhere else, through Epiphani's own relay, so no weather-data subscription anywhere. If one source errors, the other answers wherever it covers the place. It follows the Mac's time zone, so it reads the city you landed in, or your own position once Location is allowed. The panel also shows sunrise and sunset for the same place, worked out on the Mac with NOAA's solar equations. Checked by --weather-selftest --live and the panel self-test (published times in three cities within 3 minutes, the right local day across the date line, polar days). |
| Battery, including accessories | built | IOPowerSources plus AppleSmartBattery for the Mac; system_profiler SPBluetoothDataType for AirPods and other Bluetooth devices, measured at 0.12s. Wireless mics such as the DJI Mic 3, RODE Wireless GO and Shure MoveMic appear as a clip-on pod, each with its own charge. Accessories macOS reports only now and then, such as the DJI Mic 3 transmitter, are read through the system's Bluetooth framework once you allow Bluetooth access, and a silent device shows its last reported level and the time. A paused-charging mark (two bars) shows when the Mac is plugged in with charging paused, and a clamshell mark shows while clamshell keeps the Mac awake with the lid closed; the clamshell mark has its own switch in Settings > Battery. Checked by --battery-selftest --live and tools/usage_string_gate.py. |
| Energy Mode readout | built | Shows the current Energy Mode and the battery and charger settings (read from pmset -g custom), refreshed every minute and on every plug or unplug. Settings > Battery > Power opens Hush Performance to change it, or System Settings on a Mac without Hush. Also in --remote battery as "power". |
| Bluetooth item | built | Apple's Bluetooth symbol with a small count of connected devices by default, dimmed when none is connected and slashed when Bluetooth is off; five bar styles in Settings > Battery (device over its number, device and number side by side, symbol with a number when low, symbol with the count, or only when something is connected). Every charge appears in the battery item: two beside the Mac, lowest first, then +N. A panel listing your paired accessories that connects or disconnects one with a click; a per-Mac switch hides Apple's own Bluetooth icon through the Control Center preference. Agents read the panel with StageMenu --remote bluetooth and connect or disconnect a device by its name with --remote bluetooth-device, confirmed from a fresh read. Checked inside --battery-selftest and the Bluetooth panel self-test. |
| Wi-Fi item | built | A panel headed by the name of the network you are on, with signal, band, link speed and security beneath, your iPhone's Personal Hotspot one click away, and nearby networks to join. macOS shares network names once Location is allowed: Location is an optional step in StageMenu's setup, and the panel's Show Name button asks too. Agents read the headline with StageMenu --remote wifi-hero, and --remote wifi-show-name raises the Location prompt itself. Checked by the Wi-Fi panel self-test on every build. |
| Charge warning | built | When the Mac is plugged in and still losing charge, or charging far below the adapter's rating for three readings in a row, one notice appears, replaces itself and clears on its own. Checked by --charge-selftest. |
| CPU, memory, disk, network | built | Sampled natively in Swift: host_cpu_load_info tick deltas, vm_statistics64, statfs, getifaddrs byte-counter deltas. No helper process, no Python runtime. Checked by --metrics-selftest (9 checks, 3 negative controls). |
| Stage Cards panel | built | Stage Cards: one panel, one click away, with the time and date, the weather with an hourly strip, and battery with time to full. |
| Calendar month grid and events | built | EventKit, read-only, behind an explicit permission step. Checked by --calendar-selftest. |
| Capability | Status | Mechanism |
| Hide and reveal menu-bar icons | built | On macOS 15 and 26, a divider status item whose length expands beyond the screen width, pushing everything to its left out of the bar. On macOS 27 the same result comes from the system menu bar's concealment, per app, with no permission needed. Requires no permissions at all: no Accessibility grant, no Screen Recording. Hiding works on macOS 15, 26 and 27. Checked by --hide-selftest. |
| See every icon across all apps | built | Accessibility API enumeration of each running application's AXExtrasMenuBar children, read-only. Measured on a live Mac: 82 items across 27 applications. Checked by --census-selftest. |
| Open a hidden icon's menu | built | The Accessibility press action on the real status item. No synthetic mouse events are generated and no screen capture is taken. |
| Position memory across launches | built | NSStatusItem.autosaveName. Checked by --divider-selftest (every item carries its own autosave name). Your layout follows you: each move is carried into every stored display setup, and with an Epiphani account your plan follows you to your other Macs, while each Mac keeps its own screen positions. |
| Where StageMenu lives | built | Choose where StageMenu lives: the menu bar or the Dock only, in Settings > General. |
| Capability | Status | Mechanism |
| Conditions | built | On battery; plugged in; presenting; a named application is frontmost; on a named Wi-Fi network ("hide the clock when I'm on the Home network"); after a given hour; a metric sustained above a threshold for N seconds. Checked by --rules-selftest, each condition beside a negative control. |
| Actions | built | Show or hide any module, including the Bluetooth item; collapse or reveal the managed icons. Checked by --rules-selftest (a rule hides the clock and the Bluetooth item while it holds, then puts them back). |
| Changes last while the condition holds | built | When a rule's condition ends, StageMenu puts back what that rule changed, so "Hide everything when I'm presenting" brings the bar back after the presentation. A readout that was already hidden stays hidden, and a change you made by hand in the meantime is kept. A rule acts on the Mac it runs on: it shows or hides a readout over your setting without rewriting it, so a rule firing on one Mac leaves your other Macs exactly as they were. Checked by --rules-selftest. |
| Plain-English authoring | built | A sentence compiles to the typed rule schema above. Parsing happens on the Mac; no network call and no per-use cost. Sentences that are not understood produce nothing rather than a guessed rule. Checked by --rules-selftest: 163 checks, of which 72 are negative controls, run on every build. |
| It explains its decisions | built | Each rule renders as an English sentence, and the menu shows what is in force right now with the condition that caused it ("hiding the icons: presenting"). Checked by --rules-selftest (every parsed rule reads back in English). |
| Presenting detection | built | Display mirroring via CGDisplayIsInMirrorSet, plus a frontmost presentation application. Stated as a heuristic: macOS exposes no single "presenting" flag. Checked by --rules-selftest (a rule on presenting holds while presenting). |
| Capability | Status | Mechanism |
| MCP server | built | Model Context Protocol server over stdio JSON-RPC 2.0, zero dependencies, runs on the system Python. Eleven tools: read status (what each readout shows on this Mac, including any a rule is holding), show module, hide module (a show or hide an agent asks for is a deliberate act, so a rule holding that readout lets go of it), collapse icons, list rules, add a rule from a sentence, clear rules, place the hide divider, rebuild StageMenu's own items in order, read the Bluetooth panel, connect or disconnect a Bluetooth device by name. Read-only and idempotent tools carry MCP annotations, and adding a rule asks the installed app's own parser (StageMenu --parse-rule), so an agent and the Rules pane read a sentence the same way. Checked by mcp/test_mcp.py: 52 checks, 23 negative controls, run on every build. |
| Rules are a plain file | built | ~/Library/Application Support/StageMenu/rules.json, the same file the app evaluates, so anything that can write JSON can author rules. Checked by --rules-selftest (a rule written to the file while the app runs takes effect on the next tick). |
| Claim | Mechanism |
| Usage counters stay on your Mac | Usage analytics are counters against a closed vocabulary of feature identifiers, stored in a local file. An identifier outside that set is discarded, so free text cannot enter the file by construction; the self-test asserts this with a negative control. |
| Light by construction | The clock wakes once a minute, not once a second. Redraws are skipped when the rendered string has not changed. The metrics and rules timers exist only while those features are enabled, and carry a tolerance so the system can coalesce wakeups. Fast-changing power events arrive by notification rather than polling. |
| Permissions are minimal and staged | The core readouts and the hide mechanic need no permissions. Accessibility is requested only for the cross-application icon census, in context, with a direct link to the exact settings pane. Optional grants, each asked for in context: Location (a setup step shown once; one grant serves the weather, the Wi-Fi network's name and network rules), Screen Recording (real artwork for hidden icons in Settings), Bluetooth (battery levels for accessories macOS does not report). |
| Claim | Mechanism |
| Deploy a configured toolkit in one sign-in | An administrator configures StageMenu on their own Mac and publishes it as the team profile, after a review screen listing every key about to leave. A new teammate signs in once and the app arrives licensed and configured the way the team works. Publishing copies the bytes rather than pointing at the administrator’s own settings, so their later personal edits never flow to the team. |
| Team settings are defaults you can always override | The team profile sits beneath your own settings. Any key you set yourself is recorded as yours and no later publish touches it; a key you have not touched follows the team. The distinction is recorded explicitly rather than inferred by comparing values, so somebody who deliberately chose the team’s current value keeps that choice when the team changes it. |
| Pooled licenses: assign, reclaim, reassign | A team holds a pool of seats rather than one purchase per person. Reclaiming a seat puts that license on the deny-list the app polls, so an offline license stops validating rather than living on. Leaving the team reclaims the team’s seats automatically and never touches anything the member bought themselves. |
| A profile from a newer StageMenu is skipped, not half-applied | If a team publishes settings in a format this build does not understand, the whole profile is skipped and you are told once, rather than applying the parts it recognizes. A partially understood configuration looks like a product bug; a version gap should read as a version gap. |
Every test named above is a headless command on the built application, exits non-zero on
failure, and includes negative controls so that a broken implementation fails rather than
passes silently. For example: StageMenu.app/Contents/MacOS/StageMenu --rules-selftest.