Harbar
a harbour for your fleet of agent sessions.
you run a whole fleet of coding agents at once — Claude Code and Codex sessions scattered
across iTerm and Terminal tabs, VSCode and Cursor panes, JetBrains terminals, wherever they run.
Harbar is the harbour they all report into: one macOS menu bar panel showing every session at a
glance — which are working, which need your input, which are idle — so you stop alt-tabbing through
windows hunting for the one blocked on a prompt. click any session to sail straight to it.
🔐2 💤3 ▸1 ✓5 ← menu bar badge
─────────────────
🔐 PERMISSION (claude) (2)
◆ api@fix-login · refactor session · iTerm · 12s
◆ webapp@feat-search · add filters · Cursor · 1m
💤 IDLE PROMPT (waiting on you) (3)
◆ ...
🛑 APPROVAL (codex) (0)
▸ WORKING (1)
☁ worker@main · add retry logic · VSCode · 4s
✓ IDLE (5)
🔁 ◆ worker@main · clear bug queue · ×6 · every 5m · ⏲ next ~2m
◆ ...
◆ = claude, ☁ = codex. each session shows project@branch · task.
how it works
every Claude Code / Codex session fires hooks from your user-level config. a single dispatcher
(harbar-hook.py) writes a tiny JSON state file per session to ~/.harbar/sessions/. a native menu
bar app (Harbar.app) reads those files, groups by status, and shows the panel. no server, no
polling of the agents — the hooks push state, the app reads it (every 2s, pruning dead sessions by
pid).
states: working (prompt submitted) · needs input split into 🔐 permission · 🛑 codex approval ·
📝 elicitation/form · 💤 idle-prompt · idle (turn done) · error. the label is project@branch
plus the first few words of the latest prompt; a working row also shows the current tool
(editing focus.sh, $ git, searching, …) so the panel stays useful even when nothing's blocked.
🔁 on the loop: a session running /loop is marked 🔁 wherever it sits — the loop is a flag,
not a state, so the row stays in working/idle as usual. it shows the cycle count (×6), the
cadence (every 5m parsed from the command, or avg ~6m measured for self-paced loops), and
either the current tool or a ⏲ next ~2m countdown while it sleeps. a loop that hits a permission
prompt shows in 🔐 tagged 🔁 (it's genuinely blocked — approving resumes the loop); between-cycle
💤 idle-prompts are muted (the loop wakes itself, it's not waiting on you). cancelled loops drop
the mark on their own after a couple of missed cycles. only loops started after harbar was
installed are tracked.
reminders: a session that's been blocked on input keeps getting a reminder banner on an
interval, so a stuck agent never goes silent if you miss the first ping. the interval is set
per kind from the menu (off, 1, 2, 5, 10, 15, 30 min) — defaults: permission / approval /
form = 5 min, idle prompt = 15 min.
hooks it registers
every hook calls harbar-hook.py <agent> --notify, which writes a per-session state file and never
blocks the agent (silent stdout, always exits 0). Claude hooks are registered automatically by the
plugin (option A) or merged into ~/.claude/settings.json by install.sh (option B). Codex hooks
live in ~/.codex/hooks.json and must be trusted with /hooks.
Claude Code:
| hook | matcher | → |
|---|
SessionStart | — | idle (registers the session) |
UserPromptSubmit | — | working (+ captures git branch + prompt label + /loop tracking) |
PreToolUse | — | working (+ shows the current tool: editing X, $ git, searching, …) |
Stop | — | idle |
StopFailure | — | error |
SessionEnd | — | removes the tile |
Notification | permission_prompt|idle_prompt|elicitation_dialog | needs input (🔐 / 💤 / 📝) |
Codex (subset — Codex has no StopFailure / SessionEnd / Notification):
| hook | → |
|---|
SessionStart | idle |
UserPromptSubmit | working |
PreToolUse | working (+ current tool) |
Stop | idle |
PermissionRequest | needs input (🛑 approval) |
requirements
- macOS (uses AppKit,
osascript, launchctl)
- Xcode Command Line Tools (
swiftc) — xcode-select --install
python3
- Claude Code and/or Codex CLI with hooks enabled
terminal-notifier (optional, for clickable notifications) — brew install terminal-notifier;
the installer adds it automatically if Homebrew is present
install
two ways — pick one (don't run both; you'd get duplicate Claude hooks).
option A — Claude Code plugin (no clone)
inside Claude Code:
/plugin marketplace add olexandryermilov/harbar
/plugin install harbar@harbar
/harbar:install-app
/plugin install auto-registers the Claude hooks (no editing settings.json). /harbar:install-app
then builds Harbar.app, adds the login agent, installs terminal-notifier, and wires Codex.
option B — manual (clone)