A macOS menu bar app that tracks actively-running Claude Code background sessions, grouped by project folder and by category (Working / Needs input / Completed / Failed), with native notifications when a session finishes or needs your attention.
Important
Claudette relies on Claude Code's Agent View preview feature, which exposes the
claude agents command it polls. You must have Agent View enabled in Claude Code for
Claudette to detect any sessions — without it, the menu bar will always read empty.
Grab the latest signed & notarized build from the
Releases page (.dmg or .zip).
Claudette polls claude agents --json on an interval and parses the live session list.
It rolls worktree sessions (<project>/.claude/worktrees/...) back up under their parent
project, sorts attention-needing sessions to the top, and fires a UserNotifications
alert whenever a session transitions to needs input, finished, or failed.
It can monitor the local Mac and remote hosts over SSH at the same time — see Remote hosts below.
Data source reference (verified against Claude Code 2.1.179):
claude agents --json— active sessions:id, sessionId, cwd, name, kind, startedAt, state, status, pidclaude agents --json --all— includes completed (dropsstatus/pid)~/.claude/daemon/roster.json— richer daemon state incl. dispatched agent type (unofficial)
Requires XcodeGen (brew install xcodegen) and Xcode.
xcodegen generate # creates Claudette.xcodeproj from project.yml
xcodebuild -project Claudette.xcodeproj -scheme Claudette -configuration Release build
open build/Claudette.appOr just open Claudette.xcodeproj in Xcode and hit Run.
The app is ad-hoc signed (CODE_SIGN_IDENTITY = "-"), so no Apple Developer team is
needed to build and run it locally. On first launch, approve the notification prompt.
It runs as a menu bar accessory (LSUIElement) — no Dock icon. The menu bar glyph shows
a count of working + needs-input sessions; click it for the grouped breakdown.
Claudette can poll Claude Code sessions running on other machines over key-based, passwordless SSH. Click the server icon in the footer to open Remote hosts, then Add remote host and fill in:
| Field | Notes |
|---|---|
| Label | Optional display name; defaults to user@host. |
| User / Host | The SSH target (user@hostname). |
| Port | Defaults to 22. |
| Key file | Optional explicit identity file, e.g. ~/.ssh/id_ed25519. Leave blank to use your SSH defaults / agent. |
| Claude path | Optional. Leave blank and Claudette resolves claude through a remote login shell (bash -lc). Set it explicitly if claude isn't on the remote login PATH. |
Use the ⚡️ test button on each host to verify connectivity before relying on it. Remote sessions appear under a per-host header and their notifications are tagged with the host label.
For each enabled host Claudette runs:
ssh -o BatchMode=yes -o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new \
[-p PORT] [-i KEYFILE] user@host 'bash -lc "claude agents --json"'BatchMode=yesmeans it never prompts for a password — set up an SSH key first (ssh-copy-id user@host). Password-only hosts will fail fast rather than hang. For a smoother experience, use anssh-agentorControlMasterso auth happens once.ConnectTimeoutkeeps a dead host from stalling the menu; hosts are polled in parallel.accept-newtrusts a new host key on first connect and pins it thereafter.
Hosts are stored in UserDefaults (com.vfilby.Claudette.hosts). The local Mac is always
monitored and can't be removed.
Click any session row — or click the notification it fired — to open Claude Code's
interactive agent view (claude agents --cwd <project>) in a terminal, filtered to
that session's project. Background agents are daemon workers with no foreground TTY, so
there's no pane to "switch" to and claude --resume <id> refuses them; the agent view is
the canonical place to read output and reattach (SessionLauncher.swift).
The terminal is selectable from the window picker (the macwindow button in the footer):
Ghostty, iTerm, Terminal, kitty, WezTerm, Alacritty are launched directly; Automatic
picks the first installed; System default writes an executable .command file and
lets the OS open it, so any other terminal works as your default handler.
- Poll interval —
AgentPoller.pollInterval(default 4s). - Which transitions notify —
AgentPoller.detectTransitions. - Terminal to open sessions in — the footer picker, persisted as the
terminalAppdefault; add a new terminal by giving it abundleID+ launch strategy inTerminalApp. - Binary location —
AgentPoller.resolveClaudeBinarychecks~/.local/bin,/opt/homebrew/bin,/usr/local/bin,~/.claude/local, then a login shell. - SSH options —
AgentPoller.sshArguments(timeout, host-key policy, identity).
- Launch at login (
SMAppService). - Click a session to
claude attach <id>in a new terminal (ssh -tfor remotes). - Read
roster.jsondirectly to group by agent type, and avoid spawning the CLI. - Per-project mute, and a "needs input" sound distinct from "finished".
- Edit existing remote hosts in place (currently delete + re-add).