Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
93 lines
4.5 KiB
Markdown
93 lines
4.5 KiB
Markdown
---
|
|
summary: "Menu bar status logic and what is surfaced to users"
|
|
read_when:
|
|
- Tweaking mac menu UI or status logic
|
|
title: "Menu bar"
|
|
---
|
|
|
|
## What is shown
|
|
|
|
- The current agent work state renders in the menu bar icon and in the first status row of the menu.
|
|
- Health status is hidden while work is active; it returns once all sessions are idle.
|
|
- A root "Context" item opens a submenu with recent sessions instead of expanding them in the root menu.
|
|
- A "Nodes" block in the root menu lists paired **devices** only (from `node.list`), not client/presence entries.
|
|
- A root "Usage" section appears below Context when provider usage snapshots are available, followed by cost details when available.
|
|
|
|
## State model
|
|
|
|
- Source: `WorkActivityStore` (`apps/macos/Sources/OpenClaw/WorkActivityStore.swift`).
|
|
- Events arrive as `ControlAgentEvent` with a `runId`; the handler (`ControlChannel.routeWorkActivity`) reads `sessionKey` from the event payload and defaults to `"main"` if absent.
|
|
- Priority: the main session (`sessionKey == "main"` by default) always wins. If main is active, its state shows immediately. If main is idle, the most recently active non-main session shows instead. The store does not flip mid-activity; it only switches when the current session goes idle or main becomes active.
|
|
- Activity kinds:
|
|
- `job`: high-level command execution (`state: started|streaming|done|error|...`).
|
|
- `tool`: `phase: start|result` with `name`, optional `meta`/`args`.
|
|
|
|
## IconState enum (Swift)
|
|
|
|
- `idle`
|
|
- `workingMain(ActivityKind)`
|
|
- `workingOther(ActivityKind)`
|
|
- `overridden(ActivityKind)` (debug override)
|
|
|
|
### ActivityKind -> badge symbol
|
|
|
|
`ActivityKind` wraps a `ToolKind` (`bash`, `read`, `write`, `edit`, `attach`, `other`) or a bare `job`. Each maps to an SF Symbol badge drawn over the critter icon (`IconState.badgeSymbolName`):
|
|
|
|
| Kind | Symbol |
|
|
| --------------- | ---------------------------------- |
|
|
| `bash` | `chevron.left.slash.chevron.right` |
|
|
| `read` | `doc` |
|
|
| `write` | `pencil` |
|
|
| `edit` | `pencil.tip` |
|
|
| `attach` | `paperclip` |
|
|
| `other` / `job` | `gearshape.fill` |
|
|
|
|
### Visual mapping
|
|
|
|
- `idle`: normal critter, no badge.
|
|
- `workingMain`: badge with symbol, full tint (`.primary` prominence), leg "working" animation.
|
|
- `workingOther`: badge with symbol, muted tint (`.secondary` prominence), no scurry.
|
|
- `overridden`: uses the chosen symbol/tint regardless of real activity.
|
|
|
|
## Context submenu
|
|
|
|
- The root menu shows one "Context" row with a session count/status; it opens a submenu (`MenuSessionsInjector`).
|
|
- The submenu header shows the active session count for the last 24 hours.
|
|
- Each session row keeps its token bar, age, preview, thinking/verbose toggle, reset, compact, and delete actions.
|
|
- Loading, disconnected, and session-load error messages render inside the Context submenu.
|
|
- Usage and cost sections stay root-level below Context so they remain glanceable without opening the submenu.
|
|
|
|
## Status row text (menu)
|
|
|
|
- While work is active: `<Session role> · <activity label>` (`"\(roleLabel) · \(activity.label)"` in `MenuContentView`), where role label is `Main` or `Other`.
|
|
- When idle: falls back to the health summary.
|
|
|
|
## Event ingestion
|
|
|
|
- Source: control-channel `agent` events, routed by `ControlChannel.routeWorkActivity(from:)`.
|
|
- Parsed fields:
|
|
- `stream: "job"` with `data.state` for start/stop.
|
|
- `stream: "tool"` with `data.phase`, `data.name`, optional `data.meta`/`data.args`.
|
|
- Tool labels come from `ToolDisplayRegistry.resolve(name:args:meta:)`; unresolved names fall back to the raw tool name.
|
|
|
|
## Debug override
|
|
|
|
- Settings > Debug > "Icon override" picker:
|
|
- `System (auto)` (default)
|
|
- `Working: main` / `Working: other` (per tool kind: bash, read, write, edit, other)
|
|
- `Idle`
|
|
- Stored under `UserDefaults` key `openclaw.iconOverride`; mapped to `IconState.overridden`.
|
|
|
|
## Testing checklist
|
|
|
|
- Trigger main session job: icon switches immediately and status row shows the main label.
|
|
- Trigger non-main session job while main is idle: icon/status shows the non-main session; stays stable until it finishes.
|
|
- Start main while another session is active: icon flips to main instantly.
|
|
- Rapid tool bursts: badge does not flicker (2s grace window before clearing a finished tool, `WorkActivityStore.toolResultGrace`).
|
|
- Health row reappears once all sessions are idle.
|
|
|
|
## Related
|
|
|
|
- [macOS app](/platforms/macos)
|
|
- [Menu bar icon](/platforms/mac/icon)
|