A tiny macOS menu bar widget that shows which of your Solo projects have a running agent or process, and lets you jump straight into any of them with a single click.
Built as a SwiftBar plugin. Pure Python, no third‑party dependencies, no remote requests.
- Puts the Solo logo in your menu bar.
- Click it to see every project that currently has at least one running process (i.e. an "active" project).
- Groups projects by workspace (Solo 0.10+),
<optgroup>-style: each group opens with a non-clickable header showing the workspace's own icon (its custom image if one is set, otherwise a rounded swatch in the workspace's color) and its full name. The workspace glyph sits flush at the menu's icon position, the project rings beneath it are centered under that glyph, and every name lines up in one fixed-width glyph column. With a single workspace, an older Solo, or the Show Workspaces toggle off, the list stays flat. - Optional toggles to also list idle projects and show per‑project TODO / scratchpad counts; see Options below.
- Each project, and each agent, terminal, or command under it, is a clickable deep link that opens Solo focused on that exact process.
- Groups each project's processes by kind: agents first, then terminals, then commands, with a divider between groups. When an agent spawns subagents, they appear nested underneath it as an indented tree that mirrors Solo's own agent hierarchy.
- Hold ⌥ Option over a running process and the row turns into a submenu with two actions: ■ Stop ends the process but leaves it in Solo, ✕ Close stops it and removes it from Solo. Keep ⌥ held while you slide right into the submenu. Release it and the row snaps back to the plain deep link. Either action refreshes the menu once Solo confirms.
- Refreshes the moment you open the menu instead of polling in the background.
- Shows a friendly error state that tells you whether Solo is closed, its HTTP API is off, or the API just isn't responding.
- macOS
- SwiftBar:
brew install swiftbar - Python 3 (
python3on yourPATH; the plugin uses only the standard library) - Solo 0.8.2 or newer running with its HTTP API enabled
Note
Tested against Solo 0.10.1. Workspace grouping needs Solo 0.10+; on older versions the menu stays flat. The ⌥ submenu's ✕ Close shows up only when Solo's discovery file advertises process removal (the process_delete capability), so on an older Solo the submenu holds ■ Stop alone. Solo's HTTP API is still changing between releases, so a Solo update can break the plugin until it's adapted. If the menu suddenly shows "Solo API changed — update this plugin" (or an error row that won't go away) right after a Solo update, check here for a newer plugin version. You can Watch for new Releases.
The plugin reads Solo's local control plane. Enable the HTTP API in Solo's settings, and Solo writes a discovery file to ~/.config/soloterm/http-api.json, which the plugin reads to find the API's base URL and its local auth token. No setup beyond the toggle: Solo writes the token itself, and nothing ever leaves your machine.
# 1. Clone
git clone https://github.com/slaFFik/solo-menubar.git ~/Projects/solo-menubar
# 2. Make sure it's executable
chmod +x ~/Projects/solo-menubar/solo-menubar.py
# 3. Symlink it into your SwiftBar plugin folder
ln -s ~/Projects/solo-menubar/solo-menubar.py ~/Documents/SwiftBar/solo-menubar.pyPoint SwiftBar at your plugin folder (e.g. ~/Documents/SwiftBar) and the icon appears right away. SwiftBar follows the symlink, so you can keep editing the file in the repo and SwiftBar always runs the latest version.
Each time you open the menu (and once on launch), the plugin:
- Reads the API base URL, bearer token, and capability list from
~/.config/soloterm/http-api.json, so it survives Solo restarting on a different port and never needs credentials from you. The capability list is what decides whether the ⌥ submenu offers Close. - Calls
GET /api/projectsandGET /api/processes?status=running(the unfiltered process list when Show all projects is on) and joins them by project.GET /api/workspaces(Solo 0.10+) supplies each workspace's name, color, and icon for the group headers. TODO/scratchpad counts, when toggled on, come from each list endpoint'stotalCountvia concurrentlimit=1probes: one item per request instead of the full list. - Keeps any project that has a running process (or all projects, if you toggle that on).
- Renders a clickable deep link per project/process:
solo://proj/{project_id}/process/{slug}--{process_id}
It refreshes on open via SwiftBar's refreshOnOpen flag, so the list is always current the instant you click, without polling Solo in the background.
Solo's authenticated HTTP API is the primary source. For the things the API doesn't expose, the plugin takes a read‑only peek at Solo's SQLite database (~/.config/soloterm/solo.db):
| Feature | HTTP API | SQLite DB |
|---|---|---|
| Project & process list, deep links (incl. Show all projects) | ✓ | |
| Workspace grouping (names, colors, custom icons) | ✓ | |
| Stop or close a running process (⌥ submenu) | ✓ | |
| TODO counts | ✓ | |
| Scratchpad counts | ✓ | |
| Nesting spawned subagents under their parent | ✓ | |
| Telling "Solo closed" from "HTTP API off" in the error row | ✓ |
The SQLite reads are opened mode=ro and are best‑effort: Solo records subagent lineage in processes.parent_process_id and the API toggle in settings.raycast_api_enabled, but never serves either over HTTP. If the database is missing, locked, or on an older schema, those features quietly degrade (a flat process list, or the generic error row) rather than break the menu.
The plugin reads workspace custom icon images from the file paths the API serves (Solo copies uploads into ~/.config/soloterm/workspace-icons/), downscales them with macOS's built‑in sips, and lays each one flush‑left on a square transparent canvas so every icon spans the same glyph column. It caches the result in ~/.config/solo-menubar/icon-cache/, so the conversion runs once per icon instead of on every menu open. If an icon can't be read or converted, the header falls back to the workspace's color swatch.
Refresh: by default the file is named solo-menubar.py (no interval), so SwiftBar refreshes it only when you open the menu. The menu bar icon is static, so background polling buys nothing. If you do want it to poll as well, encode an interval in the filename:
| Filename | Behavior |
|---|---|
solo-menubar.py |
Refresh on menu open only (default) |
solo-menubar.10s.py |
Also poll every 10 seconds |
solo-menubar.1m.py |
Also poll every minute |
(Rename the symlink in your SwiftBar plugin folder; SwiftBar reads the interval from the filename it sees there.)
Toggles at the bottom of the menu. The plugin remembers your choices between launches; Show Workspaces starts on, the rest start off.
| Option | What it does |
|---|---|
| Show all projects | List every project, not just those with a running process. Idle projects appear greyed out. The toggle label shows the total project count. |
| Show Workspaces | Group projects under workspace headers (Solo 0.10+). Turn off for the flat list. |
| Show TODOs | Under each project, show its number of open TODOs (only when above zero). |
| Show Scratchpads | Under each project, show its number of scratchpads (only when above zero). |
- "Solo HTTP API not enabled": Solo has never written its discovery file; turn the HTTP API on in Solo's settings.
- "Solo not running": open Solo. If it is open, re-enable its HTTP API so it rewrites the discovery file.
- "Solo is running, but its HTTP API isn't responding": toggle the HTTP API off and on, or restart Solo.
- "Solo API changed — update this plugin": your Solo speaks a newer API contract than this plugin; grab the latest plugin release.
- Nothing shows in the menu bar: confirm SwiftBar's plugin folder is set, the file is executable (
chmod +x), andpython3is installed (xcode-select --install). - Menu doesn't update while it's open: macOS renders a menu at the moment you open it; the plugin re‑reads Solo on each open, so just close and reopen to see fresh data.
- Solo by Aaron Francis.
- Solo Menubar by Slava Abakumov.
