A macOS status bar application for Pi with a local daemon for process discovery, telemetry aggregation, and one-click session jump/focus.
This repository contains:
pi-statusd(Python daemon): discovers Pi agents, merges telemetry, and handles jump/focus actions.PiStatusBar(SwiftUI app): menu bar UI that visualizes agent state and context pressure.
pi-statusbarconsumes telemetry from@jademind/pi-telemetryand reliable plain-session messaging from@jademind/pi-bridge. The iOS client is PiPulse.
Latest tagged release: 0.1.16
- macOS (menu bar app)
- Swift toolchain (
swift --version) - Python 3 (
python3 --version) - Pi installed (recommended for realistic testing)
git clone https://github.com/jademind/pi-statusbar.git
cd pi-statusbarswift builddaemon/pi-statusbar daemon-restart
daemon/pi-statusbar daemon-ensure
daemon/pi-statusbar daemon-status
daemon/pi-statusbar daemon-pingExpected: status shows running daemon + healthy socket, and ping returns {"ok": true, "pong": true, ...}.
swift run PiStatusBarThe π icon should appear in the macOS menu bar.
pi install npm:@jademind/pi-telemetryThen, in an active Pi session:
/pi-telemetry --dataIf telemetry is active, the app should show source: telemetry.
pi install npm:@jademind/pi-bridgeThen restart active Pi sessions and verify in each session:
/pi-bridge-statusUse the LaunchAgent management script for clean startup/login behavior:
daemon/pi-statusbar daemon-service-install
daemon/pi-statusbar daemon-service-start
daemon/pi-statusbar daemon-service-statusIt verifies:
- plist is registered (
~/Library/LaunchAgents/dev.jademind.pi-statusd.plist) - service is loaded in
launchd - daemon socket health is OK
Useful commands:
daemon/pi-statusbar daemon-service-restart
daemon/pi-statusbar daemon-service-doctor
daemon/pi-statusbar daemon-service-uninstall- This README avoids machine-specific absolute paths and credentials.
- Runtime data is stored locally under
~/.pi-statubar. - Do not commit local logs, telemetry dumps, or screenshots that expose private paths/session names.
- Shows a live menu bar indicator of overall Pi agent state
- Lists active agents with:
- mux/session + telemetry session name + activity
- cwd path
- pid + window attachment status (including detected terminal app)
- model + token metrics (when telemetry is available)
- context pressure line with clear health/mood signal
- Supports Jump to the correct terminal window/session
- Provides a dedicated detail panel for the selected agent with:
- rich HTML/Markdown rendering of the latest assistant output
Replytext field (Entersends immediately) +SendactionJump,Refresh, andCollapsecontrols
- Falls back gracefully when telemetry is unavailable
Telemetry discovery now prefers the canonical ~/.pi/agent/telemetry/instances path (with backward-compatible fallback), restoring model metadata and latest assistant messages in the menu UI. pi-statusbar status continues to provide a formatted multi-section view (Daemon/App/HTTP), configurable HTTP ports via --http-port/--https-port, and http-logs streaming/export support.
- Red: all agents running/working
- Green: all agents waiting for input
- Yellow: mixed states
- White/neutral: no agents
- Unix socket:
~/.pi-statubar/statusd.sock - Commands:
statuspingjump <pid>latest <pid>send <pid> <message>(delivery order: zellij/tmux → pi-bridge → tty/ui fallback)watch [timeout_ms] [fingerprint]
- iOS client: PiPulse uses this bridge to read status/watch updates and send messages to running Pi sessions.
- Script:
daemon/pi_statusd_http.py - Control via
daemon/pi-statusbar:http-starthttp-stophttp-restarthttp-statushttp-token [value]
- Config file:
~/.pi-statubar/statusd-http.json - Exposed endpoints:
GET /statusGET /watch?timeout_ms=...&fingerprint=...GET /latest/<pid>POST /sendwith JSON body{ "pid": <int>, "message": <string> }
- Security defaults:
- bearer token for non-loopback clients
- optional CIDR allowlist (
allow_cidrs) sendrate limiting and payload validationjumpis intentionally not exposed over HTTP
- Status payload version:
2 - Source field values:
pi-telemetryprocess-fallback
- Polls daemon every 2 seconds
- Renders status chips:
- source (
telemetry | fallback | offline) - active/running/waiting counts
- context pressure (
close to limit/at limit)
- source (
- Shows attention banners for close-to-limit/at-limit context pressure
Each agent row is rendered as:
- Primary line: mux/session + telemetry session name (when available) + activity
- Workspace line: cwd path
- Attachment line:
PID <pid> · window attached|no attached window · <terminal app> - Model metrics line: model name/id + token usage (
used/contextWindow) when telemetry provides it - Context line: context percent + classification (
healthy,close to limit,at limit) with emoji indicator
When telemetry is unavailable, the row gracefully falls back to process-only metadata.
pi-statusd follows this data source strategy:
- Primary: per-process telemetry files at:
~/.pi-statubar/telemetry/instances/*.json
- Optional fallback:
pi-telemetry-snapshot - Final fallback: process heuristics via
ps+lsof
Compatibility notes:
- Supports telemetry activity mapping (
working,waiting_input, fallback inference) - Reads context metrics (
tokens,contextWindow,remainingTokens,percent,pressure,closeToLimit,nearLimit) - Reads model/session metadata for richer UI rows (
model.*,session.name) - Adds window attachment/app metadata in daemon responses (
attached_window,terminal_app) - Applies stale/alive filtering when reading telemetry files
- Defensively handles malformed telemetry entries
Install telemetry:
pi install npm:@jademind/pi-telemetryWhen jump <pid> is requested, the daemon uses this order:
- Focus attached mux client window
- Fallback focus via Pi ancestry
- Ghostty hint fallback (split pane support)
- TTY/title fallback for iTerm2/Terminal
- If no attached client exists, open terminal + attach/open shell
- Never Finder fallback
Terminal preference config:
- Config file:
~/.pi-statubar/statusd.json - Env override:
PI_STATUS_TERMINAL - Values:
auto | Ghostty | iTerm2 | Terminal - Auto order:
Ghostty → iTerm2 → Terminal
A Homebrew formula is provided at Formula/pi-statusbar.rb (currently HEAD-capable).
brew install --HEAD ./Formula/pi-statusbar.rbThis installs:
PiStatusBar(menu bar app launcher; first run compiles with Swift locally)pi-statusbar(single unified CLI for daemon control, HTTP bridge, LaunchAgents, and setup flows)
brew services start pi-statusbar
brew services list | rg pi-statusbarOr use:
pi-statusbar daemon-service-start
pi-statusbar daemon-service-statuspi-statusbar app-start
pi-statusbar app-statusTo disable app autostart:
pi-statusbar app-uninstallTo let anyone install with brew install, publish a dedicated tap repo:
- Create repository:
jademind/homebrew-tap - Add formula at:
Formula/pi-statusbar.rb - Use stable
url+sha256(recommended) for a tagged release tarball - Commit and push
Then users install with:
brew tap jademind/tap
brew install jademind/tap/pi-statusbarOr one-line install:
brew install jademind/tap/pi-statusbarIf only head is defined in the formula, users install with:
brew install --HEAD jademind/tap/pi-statusbarOne-command setup (start now + start at login):
pi-statusbar startStart now only (no login autostart):
pi-statusbar start --login noVerify:
pi-statusbar statusWhy not auto-start during
brew install? Homebrew formulas should not silently start background services or register user LaunchAgents without explicit user consent.pi-statusbarkeeps this explicit while minimizing setup friction.
Stop now (keep login settings):
pi-statusbar stopStop now + remove login autostart:
pi-statusbar stop --remove yesRemove package:
brew uninstall jademind/tap/pi-statusbardaemon/pi-statusbar daemon-restartdaemon/pi-statusbar daemon-status
daemon/pi-statusbar daemon-pingswift run PiStatusBardaemon/refresh-all.shOptional: also reinstall latest published bridge package before re-testing plain terminal delivery:
daemon/refresh-all.sh --bridgeswift builddaemon/pi-statusbar is the single unified CLI.
Common commands:
start [--login yes|no]stop [--remove yes|no]removestatus
Daemon direct:
daemon-startdaemon-stopdaemon-restartdaemon-ensuredaemon-statusdaemon-pingdaemon-latest <pid>daemon-send <pid> <message>daemon-watch [timeout_ms] [fingerprint]daemon-terminal [auto|Ghostty|iTerm2|Terminal]
HTTP bridge:
http-starthttp-stophttp-restarthttp-statushttp-token [value]http-cert-fingerprinthttp-portshttp-logs [--follow] [--lines N] [--console | --file <path>]- Optional port overrides on relevant commands:
--http-port <port> --https-port <port>
Service management:
daemon-service-install|start|stop|restart|status|doctor|uninstallapp-install|start|stop|restart|status|uninstall
daemon/refresh-all.sh supports:
- no args: restart daemon + app, then verify daemon health
--bridge: same as above, pluspi install npm:@jademind/pi-bridge
- Keep daemon and app restarted after daemon/UI changes
- If UI shows fallback unexpectedly, verify active Pi sessions are emitting telemetry (
/pi-telemetry) - Socket is user-local (
0600permissions) - Detail HTML rendering uses a sandboxed
WKWebViewconfiguration:- content JavaScript disabled
- non-persistent web data store
- external navigation blocked (
about:/data:only) - script tags and inline event handlers stripped before load
- Performance notes:
- daemon status polling runs every 2s
- selected detail panel refreshes incrementally using
latest_message_at - latest message text/html are cached per PID in the UI
daemon/pi-statusbar daemon-restart
daemon/pi-statusbar daemon-statusIf status is unhealthy, inspect ~/.pi-statubar/statusd.log.
- Confirm telemetry is installed:
pi install npm:@jademind/pi-telemetry - In an active Pi session run:
/pi-telemetry --data - Ensure telemetry files exist under
~/.pi-statubar/telemetry/instances
- This is expected in process-fallback mode (no telemetry session metadata)
- With telemetry enabled,
session.nameis shown in the row primary line
- Ensure Accessibility permissions are granted for terminal apps and automation
- If using Ghostty split panes, keep session hints in titles/session names
- Verify terminal preference via:
daemon/pi-statusbar daemon-terminal
daemon/pi-statusbar daemon-terminal Ghostty- Use scoped packages in docs and scripts:
@jademind/*. - Keep security defaults on (local socket perms, token auth for HTTP bridge, no HTTP jump endpoint).
- Prefer reproducible release flow:
- tag
pi-statusbarrelease - update
Formula/pi-statusbar.rb(url,sha256,version) - update
jademind/homebrew-tap - verify
brew install+brew services+pi-statusbar app-status
- tag
- Include clear migration notes when changing package names, command behavior, or service startup logic.
MIT — see LICENSE.
