A macOS menu bar app that monitors running Claude Code instances and displays their status.
Be alerted when a Claude Code instance is working (orange), needs input (red), or when it's idle and needs new instructions (green).
Important
This is alpha software that works on my machine. Don't install yet unless you have some time to spend debugging early release issues.
The current version is optimized for a workstation setup where:
- You're using multiple spaces, and have tend to keep one or a few Claude Code instances in each space
- You're running Claude Code CLI in iTerm2
- Colored status indicators - Colored boxes show each instance's state at a glance
- Space numbers - Shows which macOS Space each instance is on (if running in iTerm2)
- Focus detection - Highlights the currently focused instance (rounded square vs circle)
- Real-time updates - Status changes appear immediately via Claude Code hooks
| Status | Color | Meaning |
|---|---|---|
| Working | Orange | Claude is processing/using tools |
| Waiting | Yellow | Claude needs your input (question or permission prompt) |
| Idle | Green | Turn complete, ready for next prompt |
Nice Semaphore has two components that communicate via a JSON status file:
Claude Code hooks trigger shell commands on specific events. The nice-semaphore-status.sh hook script runs on each event and updates ~/.claude/nice-semaphore-status.json with the current state of each Claude instance.
| Hook | Status Change |
|---|---|
SessionStart |
Adds instance, sets to idle |
UserPromptSubmit |
Sets to working |
PreToolUse |
If AskUserQuestion/ExitPlanMode, sets to waiting |
PostToolUse |
Ensures working state after tool completes |
Notification |
If permission prompt, sets to waiting |
Stop |
Sets to idle (turn complete) |
SessionEnd |
Removes instance |
The status file stores each instance's session ID, project path, status, PID, and TTY (for focus detection).
The Swift app monitors ~/.claude/nice-semaphore-status.json for changes using a DispatchSource file watcher. When the file changes, it:
- Parses the JSON to get all active instances
- Detects which instance is focused (by matching TTYs to the frontmost terminal window)
- Looks up Space numbers using macOS private CGS APIs
- Renders colored indicators in the menu bar
The menu bar shows colored shapes with Space numbers. Click to see the full list with project paths.
- macOS 13+
- Claude Code CLI
- iTerm2 (for focus detection)
jq(usually pre-installed on macOS)
git clone https://github.com/nice-computer/nice-semaphore.git
cd nice-semaphoreswift build -c release./install-hooks.shThis installs a hook script to ~/.claude/hooks/ and configures Claude Code to call it on session events. Your existing ~/.claude/settings.json is backed up before modification.
swift run -c releaseTo run at login, add the binary to System Settings > General > Login Items:
.build/release/NiceSemaphore
Because Claude Code only reloads hooks on startup, you'll need to restart any Claude Code instances you'd like tracked.
You can resume an exited Claude Code session by running claude --continue in the same working directory.
Coming soon.
Remove the hooks from ~/.claude/settings.json:
{
"hooks": {
"SessionStart": [...],
"UserPromptSubmit": [...],
"PreToolUse": [...],
"PostToolUse": [...],
"Notification": [...],
"Stop": [...],
"SessionEnd": [...]
}
}Optionally delete:
~/.claude/hooks/nice-semaphore-status.sh~/.claude/nice-semaphore-status.json
- Iron out bugs
- Install hooks as Claude Code plugin
- macOS app image
- Support terminals other than iTerm
- Support remote Claude Code instances
- Support other coding agents (Codex, Gemini, OpenCode, Aider, etc)
- Homebrew
-
brew install bats-core
Run the test suite:
make testTests are written using Bats and cover the hook script's state transitions.
Set the NICE_SEMAPHORE_DEBUG environment variable in the terminal session before starting Claude Code:
export NICE_SEMAPHORE_DEBUG=1
claudeThe hook script inherits the environment from the Claude Code process, so the variable must be set before claude starts. To enable permanently, add the export to your ~/.zshrc or ~/.bashrc.
Logs are written to /tmp/nice-semaphore.log:
tail -f /tmp/nice-semaphore.logView the current state of all tracked instances:
cat ~/.claude/nice-semaphore-status.json | jqSimulate a hook event:
echo '{"session_id": "test-123", "cwd": "/tmp/test", "hook_event_name": "SessionStart"}' | ~/.claude/hooks/nice-semaphore-status.shCheck that hooks are configured in Claude Code settings:
cat ~/.claude/settings.json | jq '.hooks'- SpaceId
A macOS menu bar app that shows the current Space number. - yabai and skhd
for i3wm-like tiling window management on macOS, keyboard driven and space aware - i3wm
The og X11 tiling window manager
Thanks to:
- Nice Computer Company (nicecomputer.company) for sponsoring the coffee ☕️
- Autographical (autographical.ai) for the context engineering 🧠
