SwitchStation Request early access

Claude Code notifications - know when a session is done

Updated · SSS Flow

Claude Code supports hooks that fire on key session events; the two most useful are Notification (when Claude needs you) and Stop (when a turn ends). You can wire them to a sound or macOS banner in a few lines of settings. One session - a sound is enough. Several sessions - a session rail that shows which one needs you is the next step.

You start a Claude Code task and switch to Slack. Twenty minutes later you check back and Claude has been waiting for permission for eighteen of them. Claude Code (October 2026) supports hooks that can tell you that a session needs you - this guide covers how to wire them, what they can and cannot do, and the one case where sounds and banners stop being enough.

A macOS notification banner from Claude Code and a session rail cell turning yellow; the banner tells you something needs you, the rail tells you which session

What hooks does Claude Code expose?

Claude Code fires six hook events during a session. Each one runs a shell command you configure and receives a small JSON payload on standard input.

EventFires whenCommon use
PreToolUseClaude is about to run a toolAudit log, warning sound
PostToolUseA tool just returnedLog the result
NotificationClaude needs your attention (permission, plan approval, a question)The main "needs you" signal
StopThe current turn endsThe main "done" signal
SubagentStopA subagent turn endsProgress tracking for long plans
UserPromptSubmitYou sent a promptAudit log

The payload Claude passes includes session_id, cwd (the working directory the session started in) and hook_event_name, plus event-specific extras. For a quick notification, you only need the fact that the event fired.

How do you set up a basic sound or banner notification?

Edit ~/.claude/settings.json to add a hooks block. Make a backup first.

{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Ping.aiff && osascript -e 'display notification \"Claude needs you\" with title \"Claude Code\"'"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff"
          }
        ]
      }
    ]
  }
}

For Codex and other agents the pattern is similar, but the hook schema is different; see the agent's own docs.

What does a notification tell you - and not?

A notification tells you that something happened. It does not tell you:

For one or two sessions on one Mac, sound-only is enough. Beyond that, "that" is not useful without "which".

How do you combine notifications with a session rail?

A session rail is a thin UI, always visible, that lists every Claude Code (and Codex) session on your Mac and shows each one's state in real time. SwitchStation Rail by SSS Flow is one such rail: it installs the same hook events (Notification, Stop, PreToolUse, …) through install.sh, which merges the hooks into your ~/.claude/settings.json rather than replacing yours (back up before letting any installer touch that file).

When Notification fires, the cell for that project turns yellow with a dot. Click → focus the exact tab in Cursor, VS Code, Terminal, iTerm2, Ghostty, Warp or SwitchStation Workspace. When Stop fires, the cell goes dark. The hook payload Rail reads is only session_id, cwd and hook_event_name - no prompts, no responses, no code (SwitchStation is local-first by design).

A rail does not replace the sound; it adds the "which" the sound is missing. Keep the sound if you like it; the rail is what lets you act on it in one click.

When does a rail start to earn its place?

For the full setup for parallel sessions, see How to run multiple Claude Code sessions and keep track.

What should you do next?

Add a Notification and a Stop hook today, pick system sounds you can tell apart, back up settings.json first, and start a new session so Claude Code picks up the config. Live with it for a week. When you catch yourself ⌘-Tabbing to find which session beeped, that is your signal to add a rail.