A floating macOS monitor for Claude Code sessions
See what every Claude Code session is doing across all your terminals β at a glance, from one floating window.
/plugin marketplace add Affirm/navi
/plugin install navi@naviHooks are registered automatically. Navi builds and launches itself the first time an event fires.
| Feature | Description |
|---|---|
| Session status | Working (green), Idle (blue), needs attention (orange) at a glance |
| Inline permissions | Approve or deny tool permissions without switching terminals |
| Session discovery | Auto-detects running sessions by scanning ~/.claude/sessions/ |
| Jump to terminal | One-click focus the correct terminal tab for any session |
| Auto-dismiss | Stale permission cards clean up when approved in the terminal |
| Menu bar icon | Toggle the window; icon signals pending permissions |
| Per-event sounds | Configurable alerts for permission, completion, notification events |
| Multi-session | Monitor many concurrent Claude Code sessions side-by-side |
| Session row badges | Optional per-session badges for working folder, git status, permission mode, model, and open PR (each independently toggleable in Settings, all default off) |
- macOS (tested on macOS 15+)
- Xcode Command Line Tools (
xcode-select --install) - Python 3 (ships with macOS)
- Claude Code
Click the gear icon to configure sounds, font size, and experimental features (jump-to-terminal, menu bar icon, session status, instant notifications, etc.). Each feature is independently toggleable; most default on.
Each sound can be set to any macOS system sound (Glass, Ping, Submarine, etc.).
If you'd rather not use the plugin system:
git clone https://github.com/Affirm/navi.git
cd navi
bash build.sh
open Navi.appThen register the hooks from hooks/hooks.json in your ~/.claude/settings.json, replacing ${CLAUDE_PLUGIN_ROOT} with the absolute path to this directory.
Claude Code session
β
βββ UserPromptSubmit βββ userpromptsubmit.sh βββ writes working signal βββ /tmp/navi/events/
βββ PreToolUse βββββββββ pretooluse.sh βββββββββ captures tool_use_id βββ /tmp/navi/pretooluse/
βββ PermissionRequest ββ hook.sh β parse_event.py β event JSON ββββββββββ /tmp/navi/events/
βββ PostToolUse ββββββββ hook.sh β parse_event.py β resolve signal ββββββ /tmp/navi/events/
βββ Stop βββββββββββββββ hook.sh β parse_event.py β event JSON ββββββββββ /tmp/navi/events/
βββ StopFailure ββββββββ hook.sh β parse_event.py β event JSON ββββββββββ /tmp/navi/events/
βββ Notification βββββββ hook.sh β parse_event.py β event JSON ββββββββββ /tmp/navi/events/
βββ PostToolUseFailure β hook.sh β parse_event.py β resolve signal ββββββ /tmp/navi/events/
~/.claude/sessions/*.json βββ Navi session discovery (PID liveness + TTY lookup)
Navi.app
βββ polls /tmp/navi/events/ (instant via kqueue watcher + fallback timer)
βββ discovers sessions from ~/.claude/sessions/
βββ tracks Working/Idle/Dead status per session
βββ displays events in SwiftUI floating window + menu bar popover
β
User clicks Approve/Deny
β
writes response to /tmp/navi/responses/<event-id>
β
hook.sh reads response, returns decision to Claude Code
For permission requests, hook.sh writes an event file and polls for a response file. When you click Approve/Deny, Navi writes the response, the hook picks it up and returns the decision to Claude Code. If no response comes within 120 seconds, it falls back to the terminal prompt.
For architecture details and guidance on extending Navi, see CONTRIBUTING.md.
claude plugin uninstall navi
pkill -x Navi 2>/dev/null
rm -rf /tmp/navigit clone https://github.com/Affirm/navi.git
cd navi
bash build.sh # Compiles main.swift into Navi.app
open Navi.app # LaunchThe app is a single-file SwiftUI app (main.swift) compiled with swiftc. No other dependencies. See CONTRIBUTING.md for the feature-flag system and guidance on adding experimental features.
failed to build module 'SwiftUI', this SDK is not supported by the compiler
(the SDK is built with 'Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.5),
while this compiler is 'Apple Swift version 6.0.3 effective-5.10 (swiftlang-6.0.3.1.10...)'
This is not a Navi bug β it means your Xcode Command Line Tools install is inconsistent: the SDK (.swiftmodule files for SwiftUI, AppKit, etc.) was produced by a sibling build of the Swift compiler than the one swiftc reports. That usually happens after a partial macOS/CLT update, or when Xcode.app and CLT end up on different update cycles.
Check what's active:
xcode-select -p
xcrun swift --version
xcrun --show-sdk-version
xcrun --show-sdk-pathbuild.sh prints the same information at the top of every build, so you can read it from the build output too.
Fix in order of escalation:
-
Re-align the developer directory (30 seconds). If you have Xcode.app installed, point to it; otherwise point to CLT:
# With Xcode.app installed sudo xcode-select -s /Applications/Xcode.app/Contents/Developer # CLT only sudo xcode-select -s /Library/Developer/CommandLineTools
-
Reinstall Command Line Tools (5 minutes). Most reliable fix when you don't have Xcode.app, or when alignment didn't help:
sudo rm -rf /Library/Developer/CommandLineTools xcode-select --install
-
Update macOS + Xcode/CLT to current. If the versions have drifted far apart across major releases, install all pending updates in System Settings β General β Software Update, then reinstall CLT.
After any of these, run bash build.sh again.
Created by @Clast
Navi started inside Affirm's internal plugin catalog before it became this standalone repo, so some contributors don't appear in this repo's git history. Special thanks to:
-
@KieranLitschel β improved session status (Working / Idle), session names, auto-dismiss, jump-to-terminal button
-
@manassarpatwar β menu bar UI, instant filesystem-watcher notifications, plus a long tail of stability fixes
-
@tarkatronic β suggested open-sourcing Navi and helped with open-source setup
BSD 3-Clause β see LICENSE.