---
name: adom-desktop-presence
description: How Adom Bridge lives quietly on a Mac. Covers the menu-bar agent model (signed-in launches go straight to the menu bar with no window and no Dock icon), summoning the window from the menu-bar item, close-to-menu-bar behavior (the close button hides the window, Bridge keeps serving), launch at login via LaunchAgent (default ON, self-healing), the shared Adom sign-in in the keychain, and the window title markers. Use when a user or AI asks why Bridge is still running after closing the window, where the app went after launch, why there is no Dock icon, how to enable or disable launch at login, why the menu-bar item is missing, or what the window title markers mean.
---

# Adom Bridge presence: menu-bar agent, hidden window, launch at login

Adom Bridge is a menu-bar agent (since 1.9.186). Its window is hidden most of
its life; the working core is a small native (Rust) process that keeps serving
the relay, direct API, bridges, notifications, and approvals whether or not the
window is on screen.

## The menu-bar agent model

- A SIGNED-IN standalone launch goes straight to the menu bar: no window, and
  no Dock icon. Whenever the window is hidden, Bridge runs under the macOS
  Accessory activation policy (no Dock icon, no Cmd-Tab entry), in BOTH
  standalone and embedded modes. The menu-bar item is the always-present
  control surface.
- A signed-OUT launch still shows the window: the first-run sign-in flow needs
  a surface, and "installed it, nothing happened" on a fresh machine is a bug
  class we never want back.
- The window is a settings-and-approvals surface. It is summoned three ways:
  - the menu-bar item (Show Window / Settings)
  - launching the app a second time (single-instance: the running instance
    shows and focuses its window)
  - automatically, when Bridge needs the human: an approval dialog or the
    sign-in flow flips the app from Accessory to Regular (Dock icon appears)
    and activates the window. Hiding the window again returns to Accessory.
- Closing the window returns Bridge to the menu bar. It does not exit.

The menu-bar item's menu: Show Window, Connect All, Disconnect All, Settings,
Quit.

## Close to menu bar: the close button hides, Bridge keeps serving

- Clicking the window's close button does NOT exit Bridge. The close request
  hides the window and Bridge keeps running and serving (relay, direct API,
  bridges, notifications). This is by design: Bridge must stay reachable as
  the machine's recovery channel.
- It is never silent: the FIRST 3 TIMES the user closes the window, Bridge
  shows a notification explaining that it moved to the menu bar, then stops
  reminding. The counter lives at `~/.adom/tray-notice-count` (a legacy
  one-shot `tray-notice-shown` file seeds the count at 1 so existing users are
  not re-nagged from scratch).
- Launching Bridge again while it is hidden is never a no-op (single-instance):
  - standalone: the existing instance shows and focuses its window
  - embedded with Adom Hydrogen alive: a notification says where Bridge lives
    (inside Hydrogen)
  - embedded but Hydrogen is dead (stale flag): treated as standalone, the
    window shows
- The ONLY thing that exits Bridge is the `desktop_shutdown` verb
  (`POST /command {"command":"shutdown"}` on the direct API) or Quit in the
  menu-bar menu. Closing the window never does.

## The menu-bar item: standalone only

- In STANDALONE mode Bridge has a menu-bar item.
- When EMBEDDED in Adom Hydrogen, Bridge HIDES its menu-bar item; Hydrogen is
  the app the human sees. When Hydrogen goes away, Bridge reverts to
  standalone and the menu-bar item comes back.
- The absence of the menu-bar item plus a running Bridge process is therefore
  the normal embedded state, not a failure.

## The hidden window costs nothing extra

There is no separate renderer-suspension machinery on macOS: a hidden window
is simply hidden, and the Accessory policy keeps Bridge out of the Dock and
Cmd-Tab. The Rust side keeps doing ALL real work while hidden: relay, direct
API, bridges, bridge supervision (persistent respawn plus duplicate collapse),
notifications, and shell approvals. UI-only work (LED probes, status emits
that exist to paint the GUI) is skipped while the window is hidden and
self-heals within one health tick of showing it.

## Launch at login: default ON, self-healing

- The intent is `config.launch_on_boot`, DEFAULT TRUE. The Settings checkbox
  (launch at login) reads and writes this intent and is checked by default.
- The mechanism is a per-user LaunchAgent:
  `~/Library/LaunchAgents/inc.adom.desktop.plist`.
- A reconcile runs on EVERY launch, in BOTH standalone and embedded modes:
  - intent ON and the plist is missing or stale: (re)write it
  - intent OFF and the plist exists: delete it
- This is the self-heal: a plist that was never created, got deleted, points
  at a moved app path, or failed to write is corrected on the next launch. An
  update that relocates the app rewrites the LaunchAgent to the new path.
- Never create the LaunchAgent manually; the reconcile owns it.

## Shared Adom sign-in (keychain)

One Adom sign-in serves both Adom Bridge and Adom Hydrogen: the session token
lives in a SHARED keychain item, and `~/.adom/session.json` is a rebuilt
cache. Consequences:

- Signing in to either app signs in both.
- The sign-in survives uninstall and reinstall (the keychain item persists;
  the file cache is rehydrated from it).
- Signing out deletes the keychain item, so it signs out everywhere.

## Window title markers

The window title carries live version and provenance markers: the running
VERSION (for example `Adom Bridge — v1.9.187 release`), the git SHA and build
timestamp, and a `signed` or `unsigned` marker for the running binary's code
signature. This is the quick truth check for which build is actually running.

## Foreground attribution (v1.9.175)

Bridge never raises its own window silently. Every self-foreground (sign-in
completion, notification click, shell-approve grant, `request_shell_approval`,
menu-bar menu, second launch) is logged to the Activity Log as a `foreground`
event naming the source and reason, and to `startup.log` as a `FOREGROUND:`
line. An update-apply relaunch is deliberately QUIET: the updater drops
`~/.adom/update-quiet-relaunch` and the relaunched Bridge consumes it
(10-minute freshness gate) and stays in the menu bar. If a user reports
"Bridge randomly came to the front", read the Activity Log or startup.log; the
answer is always recorded.
