If you’re anything like me, you fire off a task in Claude Code and then flip over to something else — a browser tab, Slack, another terminal. The problem is knowing when Claude is done or needs your attention without constantly checking back.

I put together a simple setup that adds a status indicator right in the Mac menu bar. Three states, zero guesswork:

  • 🤖 Idle/Done — Claude is finished or waiting
  • 🔨 Working — Claude is actively using tools
  • 🔔 Needs Attention — Claude has a question or notification for you

Here’s how to set it up.

Step 1: Install SwiftBar

SwiftBar is a lightweight, open-source menu bar customization tool. All it does is run shell scripts on an interval and display their output in your menu bar — no network calls, no telemetry. You can review the full source on GitHub if you want to see exactly what it’s doing under the hood. Install it with Homebrew:

brew install swiftbar

Step 2: Create a Plugins Directory

SwiftBar needs a directory to look for plugin scripts. Create one:

mkdir -p ~/.swiftbar

Step 3: Create the Status Script

Create a file at ~/.swiftbar/claude-status.3s.sh with the following contents:

#!/bin/bash
FLAG=/tmp/claude-status-flag

if [ -f "$FLAG" ]; then
  case $(cat "$FLAG") in
    notify) echo "🔔 Claude" ;;
    working) echo "🔨Claude" ;;
    done)   echo "🤖 Claude" ;;
  esac
else
  echo "🤖"   # idle state - minimal
fi

The .3s. in the filename tells SwiftBar to refresh the script every 3 seconds. Make it executable:

chmod +x ~/.swiftbar/claude-status.3s.sh

Step 4: Add Hooks to Claude Code

Claude Code supports hooks — shell commands that fire in response to lifecycle events. Open your Claude settings file at ~/.claude/settings.json and add the following hooks section (if you already have content in this file, add this before the closing }):

"hooks": {
  "Notification": [{
    "matcher": "*",
    "hooks": [{
      "type": "command",
      "command": "echo 'notify' > /tmp/claude-status-flag && open -g 'swiftbar://refreshPlugin?name=claude-status'",
      "timeout": 2
    }]
  }],
  "PreToolUse": [{
    "matcher": "*",
    "hooks": [{
      "type": "command",
      "command": "echo 'working' > /tmp/claude-status-flag && open -g 'swiftbar://refreshPlugin?name=claude-status'",
      "timeout": 2
    }]
  }],
  "Stop": [{
    "matcher": "*",
    "hooks": [{
      "type": "command",
      "command": "echo 'done' > /tmp/claude-status-flag && open -g 'swiftbar://refreshPlugin?name=claude-status'",
      "timeout": 2
    }]
  }]
}

Each hook writes a state to a temp file and tells SwiftBar to refresh immediately (rather than waiting for the next 3-second poll). The open -g flag opens the URL in the background so it doesn’t steal focus.

Step 5: Launch SwiftBar and Set the Plugin Directory

Open SwiftBar and point it to the plugin directory you created.

Tip: If you used ~/.swiftbar, the directory will be hidden in Finder. When the “Choose plugin folder” dialog appears, press ⇧⌘G (Shift + Command + G) to open the “Go to folder” input, then type ~/.swiftbar to navigate there directly.

Testing It Out

You can verify everything works without running Claude Code by executing one of the hook commands directly in your terminal:

echo 'notify' > /tmp/claude-status-flag && open -g 'swiftbar://refreshPlugin?name=claude-status'

You should see the 🔔 icon appear in your menu bar. Swap notify for working or done to test the other states.

Once it’s wired up, you’ll always know at a glance whether Claude is heads-down, finished, or waiting on you — no terminal switching required.