docs: plan — move macOS menu bar into a gxserver-owned agent#39
Conversation
Implementation plan for relocating the menu bar status item out of Ghostex.app into a standalone gxserver-owned GxserverBar.app that controls the daemon (start/stop/restart/logs) and shows session-status counts. Includes multi-persona review findings and open design questions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Persistence: daemon-driven bootstrap, drop SMAppService/login item
- Interaction: menu-first ("Open Ghostex" first item), no badge click
- Restart: wait-for-stopped between stop and start (stop is async)
- Launcher path: fixed bundle-relative + validated, not runtime metadata
- Rendering: preserve available-suppression (available only when all-idle)
- Preference: agent needs hideMenuBar only; menu-bar size is hard-coded
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks — all six are real contradictions; fixed in the latest commit (plan only, still draft).
One decision left open for you: dev/prod flavor isolation (R-H) — should |
- Summary/Scope: floating indicators are preserved-with-care (share a protocol message per R-A), not "out of scope / if any" - Reorder KTDs into sequence (KTD5/6/7) - HLD: open -g runs each start (idempotent), not "first run" only Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Agent uses one fixed bundle id and the standard local endpoint/token; ghostex-dev does not get a separate menu bar agent. Closes the last open plan decision (R-H). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Resolved the last open decision: dev/prod flavor → single-instance-on-prod. The agent ships one fixed bundle id ( With that settled, no plan-level decisions remain open — only implementation-time security details (token/metadata 0600, loopback-binding assertion). Ready to move to implementation when you are. |
What
Implementation plan only (no code) for moving the macOS menu bar status item out of
Ghostex.appand into a standalone, gxserver-ownedGxserverBar.app(LSUIElement) that controls the daemon (Start / Stop / Restart, Open Logs) and shows the session-status indicator, driven by gxserver's own presentation state over127.0.0.1:58744. The oldSessionStatusIndicatorControlleris removed fromGhostex.app; floating / in-window indicators are preserved.Adds:
docs/plans/2026-06-12-001-feat-gxserver-menubar-agent-plan.mdTracking issue: #38
Why
gxserver is the long-lived process that survives the app closing, yet the only menu bar presence today lives in the window app and has no server control. A control surface for the server should live with the server. gxserver (a Node daemon) can't draw an
NSStatusItem, so it owns/launches a thin native agent instead.Planned units
{attention, working, available}counts; serves/api/ui/statusIndicators+ broadcasts on/api/events.GxserverBar.app: status item, control menu, HTTP/WS client, badge rendering moved from the old controller.gxserverlauncher.build-ghostex-host.sh, macOS-only.ghostex://scheme.SessionStatusIndicatorController, preserving floating indicators.Open design questions (from multi-persona plan review)
Forks to settle before implementation — full detail in the plan's Open Questions section:
SMAppServicecan't register a standalone staged.app) — LaunchAgent vs. daemon-driven bootstrap vs. relocate bundle.NSStatusItemclick-vs-menu model (can't have both).ghostex-dev).size/hideMenuBarIndicatorspreference source for the agent.ghostex://focus-session route (doesn't exist yet) — define or defer per-session focus.ghostex://input validation, login-item cleanup).Notes
.app; bootstrap no-ops when the bundle is absent.🤖 Generated with Claude Code