SwiftBar Integration
Relevant source files
The following files were used as context for generating this wiki page:
SwiftBar Integration provides a macOS-specific menu bar interface for Marginalia. This component acts as a persistent monitor for the background poller's activity and status. It alerts you when a code review is ready and provides quick access to the Review Studio and polling controls.
The integration functions as a plugin for the SwiftBar application. It consumes state data generated by the Marginalia poller and renders it as dynamic menu bar icons and dropdown items.
Sources: PRODUCT.md:33-35, README.md:237-238
System Architecture and Data Flow
The integration relies on a file-based communication bridge between the background poller and the macOS menu bar. The poller continuously writes its operational state to a gitignored file named status.json at the project root.
Data Flow Diagram
The following diagram illustrates how status information moves from the core bot to the user's menu bar.
The diagram shows the periodic polling mechanism where SwiftBar reads the local status.json file to update the UI.
Components
status.json: The shared state repository containing the current process ID (pid), current phase (e.g.,idle,reviewing), and details of the specific Merge Request (MR) being processed.swiftbar/marginalia.10s.sh: A Zsh wrapper script that sets the execution environment for Node.js and invokes the rendering logic. The.10ssuffix in the filename instructs SwiftBar to refresh the display every 10 seconds.menubar.mjs: The script (invoked by the wrapper) that parses the JSON state and formats it into the SwiftBar plugin API format.
Sources: README.md:239-242, swiftbar/marginalia.10s.sh:1-12, studio/public/openapi.yaml:526-550
Status Indicators and Icons
The menu bar icon changes dynamically based on the phase attribute found in status.json. This provides immediate visual feedback on the bot's health and activity.
| Icon | Meaning | Internal Phase |
|---|---|---|
| ✓ seal | The bot is idle and waiting for the next scheduled poll. | idle |
| Circular arrows | The bot is currently polling the GitLab API for changes. | polling |
| Eye + !iid | The bot is actively reviewing the specified Merge Request. | reviewing |
| Red triangle | The last poll failed due to network issues or invalid tokens. | error |
| Grey octagon | The Marginalia background process is not running. | stopped |
Sources: README.md:247-254, studio/src/lib/api.ts:133-140
User Interactions
The SwiftBar dropdown menu provides two primary interactive commands that control the Marginalia process:
Poll Now
This action sends a SIGUSR1 signal to the process ID recorded in status.json. If the bot is currently idle, this signal triggers an immediate poll of GitLab, bypassing the standard POLL_INTERVAL_MINUTES timer. The system ignores this signal if a poll is already in progress.
Open Reviews
This command opens the local Review Studio web application in the default browser at http://localhost:4477. The Studio provides the primary interface for reading generated reports and posting comments to GitLab.
Sources: README.md:255-263, studio/src/App.tsx:210-215
Installation and Setup
To enable the integration on macOS, you must link the provided script to your SwiftBar plugins directory.
- Install SwiftBar via Homebrew:
brew install --cask swiftbar. - Create a symbolic link from the repository to your SwiftBar plugin folder:
ln -s ~/marginalia/swiftbar/marginalia.10s.sh ~/SwiftBarPlugins/ - Configure the environment: The wrapper script explicitly adds Homebrew and
nvmpaths to thePATHvariable to ensure the correct Node.js binary is available to SwiftBar. - Automation: Running
npm run autostartcreates a LaunchAgent (com.marginalia.swiftbar) that ensures SwiftBar opens automatically at login alongside the Marginalia bot.
Sources: README.md:242-246, README.md:299-301, swiftbar/marginalia.10s.sh:10-11
State Data Structure
The SwiftBar integration consumes the BotStatus structure. This structure is also defined in the Studio's API layer to ensure consistent status reporting across the web UI and the menu bar.
// From studio/src/lib/api.ts:133-140
export interface BotStatus {
pid: number;
phase: 'idle' | 'polling' | 'reviewing' | 'error' | 'stopped';
current: { iid: number; title: string; startedAt: string; progress?: string[] } | null;
lastPoll: { at: string; ok: boolean; error: string | null } | null;
nextPollAt: string | null;
mrs?: { iid: number; status: string; reviewPath?: string | null }[];
}
Sources: studio/src/lib/api.ts:133-140, studio/public/openapi.yaml:526-550