Claude Code Signal Plugin - Marcel-Bich/marcel-bich-claude-marketplace GitHub Wiki

Claude Code Signal Plugin - Desktop Notifications

Desktop notifications showing what Claude Code is working on - stay informed even when the terminal is not in focus.

Use case: You're working in your IDE or browser while Claude Code runs in a terminal. With this plugin, you'll see desktop notifications about what Claude is doing - no need to constantly switch back to the terminal.

Works great with claude --dangerously-skip-permissions for autonomous workflows where you want to monitor progress without watching the terminal.

Features

  • Live Status - See what Claude is working on without switching to the terminal
  • Desktop Notifications - Non-stacking notifications that replace each other
  • Location Context - Every notification shows the cwd, the git repo the session works in, and the tmux session / kitty tab (see Notification Format)
  • Sound Alerts - Configurable volume, separate for completion and attention sounds
  • AI Summaries - Optional Haiku-powered summaries of completed work (disabled by default)
  • Kitty Tab Indicator - Visual tab title prefix during active Claude sessions (kitty terminal only)
  • Smart Filtering - No spam from subagents, debounced notifications, no "Tool waiting" hints in bypass permissions mode
  • Cross-Platform - Works on Linux and WSL2 (Windows 10/11)

Requirements

Linux

  • Desktop notifications (GNOME, KDE, etc.)
  • jq - JSON processor (install: sudo apt install jq)
  • gdbus or notify-send - For desktop notifications
  • Sound alerts (optional) - the plugin uses the first available player, in this order:
    • paplay + pactl (PulseAudio, pulseaudio-utils) - honours the configured volume
    • pw-play (PipeWire, pipewire-bin on Debian/Ubuntu) - honours the configured volume
    • ffplay (ffmpeg) - last resort, plays at full volume
  • bc - For volume calculations (optional)

WSL2 (Windows 10/11)

  • jq - JSON processor (install: sudo apt install jq)
  • powershell.exe - For Windows toast notifications and sounds. It does not have to be on PATH (v1.5.4+): signal also finds it below the Windows drive mounts (see Delivery and Preflight)
  • Optional: BurntToast PowerShell module for better notifications

Installation

claude plugin marketplace add Marcel-Bich/marcel-bich-claude-marketplace
claude plugin install signal@marcel-bich-claude-marketplace

Configuration

Configure via environment variables in ~/.claude/settings.json:

{
  "env": {
    "CLAUDE_MB_NOTIFY_HAIKU": "false",
    "CLAUDE_MB_NOTIFY_SOUND_COMPLETE": "0.4",
    "CLAUDE_MB_NOTIFY_SOUND_ATTENTION": "0.25"
  }
}

Options

Variable Default Description
CLAUDE_MB_NOTIFY_HAIKU false Enable AI summaries on task completion
CLAUDE_MB_NOTIFY_SOUND_COMPLETE 0.4 Completion sound volume (0-1, 0 = off)
CLAUDE_MB_NOTIFY_SOUND_ATTENTION 0.25 Attention sound volume (0-1, 0 = off)
CLAUDE_MB_NOTIFY_SUBAGENT_TOOLS true "Tool waiting" hints for subagent tool calls (true/false, false silences them)
CLAUDE_MB_NOTIFY_BYPASS_TOOLS false "Tool waiting" hints in bypass permissions mode (true/false, true shows them anyway)
CLAUDE_MB_NOTIFY_TOAST true (v1.5.4+) Toasts and desktop notifications (true/false; off, no, 0, disabled also count as false, any case, surrounding spaces ignored). false skips every attempt and the preflight; sounds are unaffected
CLAUDE_MB_SIGNAL_STATE_DIR ${XDG_STATE_HOME:-$HOME/.local/state}/claude-mb-signal (v1.5.4+) State dir for the cached powershell.exe path, signal.log and the once-a-day markers (mode 0700, owner-checked; below $HOME every level must be a real directory owned by you and not world-writable (unless sticky) and group-writable only for one of your own groups (default umask 002), no symlink below the anchor; files in it are never written through a symlink)
CLAUDE_MB_SIGNAL_PS_TIMEOUT 20 (v1.5.4+) Seconds before a powershell.exe toast/sound run is killed
CLAUDE_MB_KITTY_TAB true Kitty tab title indicator (true/false)

Sound Volume

Sound volume is relative to your system volume:

  • 0.4 = 40% of current system volume
  • 0.25 = 25% of current system volume
  • 0 = Sound disabled

AI Summaries (disabled by default)

Cost Warning: Enabling this feature will use your Anthropic API credits. Each notification triggers a Haiku API call which costs real money. You are responsible for monitoring your own API usage and costs.

When enabled (CLAUDE_MB_NOTIFY_HAIKU=true), the plugin uses Haiku to generate a brief summary of the work completed. This:

  • Costs API credits (~0.001-0.01 USD per notification, depending on context size)
  • Requires the claude CLI to be available and authenticated
  • Shows a one-sentence summary in the notification

Notification Types

Completion (Stop)

  • Triggered when a task completes
  • Shows AI summary (if enabled) or generic message
  • Plays complete.oga sound

Tool Waiting (PreToolUse)

  • Triggered when Bash commands need approval
  • Shows the command being executed
  • Plays message.oga sound
  • Skipped in bypass permissions mode (v1.3.0+): PreToolUse fires before Claude Code decides whether to ask at all, so it is only a hint. With permission_mode bypassPermissions (e.g. --dangerously-skip-permissions) no tool ever waits, so no "Tool waiting" notification is sent. Real permission prompts still arrive via the Notification hook (permission_prompt). (v1.5.1+) Set CLAUDE_MB_NOTIFY_BYPASS_TOOLS=true to get the hints in bypass mode anyway.
  • Subagent tool calls (v1.3.0+): notified by default (CLAUDE_MB_NOTIFY_SUBAGENT_TOOLS=true); set it to false to silence "Tool waiting" hints for tool calls made by subagents

Input Required (Notification)

  • Triggered for permission prompts, idle prompts, etc.
  • Shows what type of input is needed
  • Plays message.oga sound

Notification Format

(v1.4.0+) Every notification (Stop, PreToolUse, Notification) shows where the session works:

alice-task | cwd: .../marcel/workstation

git: Marcel-Bich/marcel-bich-claude-marketplace
Bash: ls -la

tmux: workspace | kitty: workspace

Title

<name> | cwd: .../<parent>/<dir> - the last two segments of the hook's cwd. Short paths with nothing to shorten are shown as is (/, /tmp, /home/marcel). What the toast is about (done, tool waiting, permission prompt) is in the body. The Done toast keeps its sparkle in front (<sparkle> <name> | cwd: ...) as the only event marker.

(v1.5.3+) <name> is the same for EVERY toast (Done, Tool waiting, permission prompt, waiting for input, questions). First hit wins:

  1. The session name set by the user: field name of the session file <config dir>/sessions/<pid>.json, only when nameSource is user. A name Claude Code derived on its own never counts. The session transcript (custom-title) is not used as a fallback
  2. The kitty tab title (clean, same source as the last body line)
  3. The tmux session name of the session's pane
  4. The short session id: first character of each dash group joined by -, plus the last character, e.g. a1b2c3d4-e5f6-7890-8bcd-0123456789d8 becomes a-e-7-8-08
  5. Claude Code when no session id is known

The session file is read safely (owned regular file, symlinks are not followed, first 256 KiB only, control characters removed). A file naming another session id, or none while the session id is known, is skipped. Every name (user name, kitty label, tmux label) has all control characters removed and is cut to 20 characters (no ...). Example: alice-task | cwd: .../marcel/workstation.

Older versions used a fixed Tool waiting / ✨ Done text, and (v1.5.0+) the session_name of the hook input, the /rename title, the Limit statusline caption, kitty and tmux for general notifications only. The session_name hook field and the Limit statusline caption are no longer used (the caption could be a name Claude Code derived on its own).

First body line: git repo

git: <parent>/<repo> - the last two path segments of the repo toplevel (same format as the git line of the Limit statusline, path only, no branch). The repo is resolved in this order, the first hit wins:

  1. Work-repo state (limit plugin): the per-session file /tmp/claude-mb-workrepo_<session_id>, i.e. the repo the main agent last worked in - follows the agent even from a non-git hub directory
  2. Git discovery from the cwd: git rev-parse --show-toplevel
  3. Credo session pin (credo plugin): credo-config.sh resolve-project for the session; accepted only if the pinned target is a git repo

Limit and credo are optional (soft dependencies). If no repo resolves, the line is omitted entirely.

Last body line: tmux session and kitty tab

tmux: <session> | kitty: <tab title>, set off by an empty line, containing only the parts that exist (tmux: workspace, kitty: workspace, or both). Outside tmux and kitty the line is omitted.

  • tmux: the session name of the pane Claude Code runs in (tmux display-message -t "$TMUX_PANE"), not the most recently used client. (v1.5.3+) For sessions hosted by the Claude Code background daemon, or when TMUX_PANE is missing in the hook environment, the pane is taken from the client terminal process (claude daemon run is found in the process ancestry; its parent, else the process named by its --spawned-by link, must be a Claude client of the same user; only TMUX and TMUX_PANE are read from its environment and both are validated). A client that cannot be verified is ignored and the tmux part is omitted. The same pane is used for the title fallback
  • kitty: the tab title without the indicator prefixes ([ai...], [ask], [fin]). Source order:
    1. The clean title saved by the Kitty Tab Indicator (only when the indicator is enabled)
    2. Fallback (indicator disabled or no saved title yet): the real title of the tab containing this window, read via kitty @ ls (needs the kitty socket, see Requirements); indicator prefixes are stripped

Each lookup has a short timeout; any failure silently drops that part.

WSL2

The Windows toast shows the body as a single wrapping text field, so on WSL2 the body lines are joined with | instead of line breaks (e.g. git: Marcel-Bich/repo | Bash: ls -la | tmux: workspace).

GNOME Shell line breaks (v1.5.0+)

GNOME Shell (46 and older) replaces every \n in a notification body with a space, in the banner and in the expanded message list alike (gnome-shell#7705). Only \n is replaced, so signal sends the line breaks as carriage returns (\r) when the notification server reports itself as gnome-shell. Result: every line and every empty line is shown as intended, and the notification is shown fully without expanding. GNOME offers the expand arrow only when a line is too long and gets cut with .... Other servers (KDE, dunst, ...) keep \n and get the body unchanged.

Tested alternatives that do not work on GNOME 46: <br> / <br/> (only <b>, <i>, <u> markup is allowed, other tags are shown as text); Unicode U+2028 / U+2029 break lines but show a box glyph in the collapsed view.

Delivery and Preflight (v1.5.4+)

Before this release signal called powershell.exe bare and swallowed every error, so on a WSL where powershell.exe is not on PATH the toasts silently never appeared.

Finding powershell.exe (WSL2)

  1. powershell.exe on PATH
  2. The path cached in the state dir (powershell-path), used only while it is still an absolute, executable file named powershell.exe
  3. A scan of /proc/mounts for Windows drive mounts (type 9p or drvfs with path=<Letter>: in the options or a <Letter>: device) and Windows/System32/WindowsPowerShell/v1.0/powershell.exe below each of them. The WSL drivers mount has no drive letter and is skipped. No drive letter or mount point is hardcoded

When nothing is found, toasts and sounds are skipped and one warning per day goes to stderr and signal.log in the state dir.

Exit codes and warnings

  • powershell.exe runs happen in the background (detached, stdin /dev/null) and are killed after CLAUDE_MB_SIGNAL_PS_TIMEOUT seconds (default 20); a non-zero exit code is logged and reported once a day by the next notification
  • The PowerShell script is passed with -EncodedCommand (UTF-16LE base64), never as a multi-line argv string. The toast tag (session id) is restricted to [A-Za-z0-9-] before it reaches the script, and title and body are flattened to one line each
  • On Linux, a gdbus Notify call that returns exit code 0 counts as delivered even when the reply cannot be parsed (no duplicate via notify-send)
  • On Linux the gdbus Notify call is checked, then notify-send is tried; when both are missing or fail, one warning per day is emitted
  • Hooks never wait for any of this and keep their timeouts

Toast switch

CLAUDE_MB_NOTIFY_TOAST=false turns off every toast and desktop notification attempt (also the toast-history cleanup at session start and the preflight). Sounds keep working.

Preflight

At session start, at most once a day and only with the toast switch on, signal checks that a toast can show up at all:

  • WSL2: read-only registry reads through powershell.exe under HKCU:\Software\Microsoft\Windows\CurrentVersion: PushNotifications ToastEnabled, Notifications\Settings NOC_GLOBAL_SETTING_TOASTS_ENABLED and the per-app key of the toast sender (Notifications\Settings\{1AC14E77-...}\WindowsPowerShell\v1.0\powershell.exe, value Enabled). A value of 0 means disabled, an absent value means enabled. Focus Assist is not checked. The script is passed to powershell.exe with -EncodedCommand (one single-line argument). A cold powershell.exe start can take longer than the 5 second SessionStart timeout, so the read runs detached in the background (stdin /dev/null, killed after CLAUDE_MB_SIGNAL_PREFLIGHT_TIMEOUT seconds, default 20) and writes its result to the state dir; the NEXT session start reports it. The daily stamp is only set once a usable result was reported. A failed read (no output, killed by the timeout) or a powershell.exe that cannot be found leaves a short-lived marker (the latter is logged and mentioned once a day), the next session retries but at most once per hour
  • Native Linux: only whether gdbus or notify-send exists; powershell.exe is never used
  • If toasts look disabled, powershell.exe cannot be found or no Linux tool exists, signal adds one short line to the session context. Claude then tells you once and asks whether it should open ms-settings:notifications; it only runs open-settings after you said yes, never on its own. Nothing is ever changed automatically. To enable toasts yourself: Settings > System > Notifications > "Get notifications from apps and other senders" = On (German: "Benachrichtigungen von Apps und anderen Absendern abrufen" = Ein)
  • No other fallback (such as a push service) is used

Commands (replace <plugin> with the plugin directory):

Command Effect
bash <plugin>/scripts/toast-preflight.sh decline No further hints (marker preflight-declined in the state dir)
bash <plugin>/scripts/toast-preflight.sh reset Removes the decline, the daily stamp, the probe state (result, failure and pending markers) and the warning markers, so hints and warnings come back
bash <plugin>/scripts/toast-preflight.sh open-settings Opens the Windows notification settings (WSL2 only, changes nothing)

Kitty Tab Indicator

When running Claude Code inside the kitty terminal, the plugin can mark the tab title with a prefix so you can see at a glance which tab has an active session -- even when you have many tabs open.

How it works

  • Session start: The tab title is prefixed with [ai...] (e.g. [ai...] my-project)
  • Input required: The prefix changes to [ask] when user input or permission is needed
  • Session end: The prefix changes to [fin] (e.g. [fin] my-project)
  • Tab focused for 3 seconds: The original title is restored automatically

The clean kitty tab title (without prefix) is also shown in the last line of the notification body, so you can see which tab a notification belongs to (see Notification Format).

This makes it easy to spot which tab Claude is working in and whether the session is still running or finished.

Configuration

The indicator is enabled by default when kitty is detected. To disable it:

{
  "env": {
    "CLAUDE_MB_KITTY_TAB": "false"
  }
}

Requirements

Your kitty.conf must have remote control enabled:

allow_remote_control yes
listen_on unix:/tmp/mykitty

Without these settings, kitty does not expose the socket needed to read and set tab titles. The plugin will silently skip the indicator if the socket is not found.

tmux support

The indicator also works inside tmux sessions running in kitty. The plugin detects the tmux client of the current pane (-t "$TMUX_PANE", so the right client is used even with many attached clients) and resolves the correct kitty window PID through the process tree. Kitty is recognized by its process name or by its executable, so kitty started via the x-terminal-emulator alternative (process name x-terminal-emul) is detected as well.

Troubleshooting

No notifications appearing

  • Check if notify-send or gdbus is installed
  • Verify your desktop environment supports notifications

No sound

  • Check if a supported player is installed: paplay (PulseAudio), pw-play (PipeWire), or ffplay (ffmpeg)
  • For PulseAudio, verify it is running: pactl info
  • On PipeWire-only systems (e.g. Ubuntu 24.04 without pulseaudio-utils), install pipewire-bin for pw-play
  • Check sound volume isn't set to 0

Notifications stacking

  • The plugin uses gdbus for notification replacement: one slot per session and hook type (/tmp/claude-mb-notify-id-session-<session_id>-<hook>, falls back to the directory name without a session id). Tool waiting, general notifications and Done keep separate slots on purpose
  • (v1.5.0+) The read-close-send-store sequence is serialized per slot with flock. Before, hooks firing at the same moment (e.g. parallel tool calls) all read the same old ID and each left its own notification behind
  • If falling back to notify-send, stacking may occur

WSL: No notifications appearing

  • (v1.5.4+) powershell.exe does not need to be on PATH, signal finds it below the Windows drive mounts. Look at signal.log in the state dir (default ~/.local/state/claude-mb-signal/) for "powershell.exe not found" or failed runs with their exit code
  • Check that CLAUDE_MB_NOTIFY_TOAST is not set to false
  • If the session context mentions that toasts look disabled, switch them on in the Windows notification settings (see Preflight); to stop the hint run toast-preflight.sh decline
  • Verify powershell.exe is accessible from WSL: which powershell.exe (older versions needed it on PATH)
  • Install BurntToast for better notifications: powershell.exe -c "Install-Module -Name BurntToast -Scope CurrentUser"
  • Check Windows notification settings (Settings > System > Notifications)

Kitty tab indicator not appearing

  • Verify allow_remote_control yes is set in your kitty.conf
  • Verify listen_on unix:/tmp/mykitty is set in your kitty.conf
  • Check that the socket exists: ls /tmp/mykitty*
  • Make sure CLAUDE_MB_KITTY_TAB is not set to false
  • Enable debug logging with CLAUDE_MB_SIGNAL_DEBUG=true for details

WSL: No sound

  • Windows sounds are played via PowerShell's MediaPlayer API
  • Check if Windows sounds are enabled in your system settings
  • Volume is converted from Linux scale (0.4 Linux = 0.05 Windows)

Updating

  1. Run /plugin in Claude Code
  2. Go to Marketplaces tab and select "Update marketplace"
  3. Go to Installed tab and update the signal plugin
  4. Restart Claude Code

Disclaimer

This software is provided "as is", without warranty of any kind. Use at your own risk.

  • The author is not responsible for any costs, damages, or issues arising from use of this plugin
  • You are solely responsible for any API costs incurred (especially when enabling Haiku summaries)
  • You are solely responsible for ensuring this plugin is compatible with your system
  • No support or maintenance is guaranteed

License

MIT - See LICENSE for full terms.


See also: Dogma | Limit | All Plugins


Keywords / Tags

Claude Code, Claude Code Plugin, Claude Code Extension, Claude Code Kitty, Claude Code Kitty Tab, Claude Code Tab Indicator, Kitty Terminal, Kitty Tab Title, Claude Code Notifications, Claude Code Desktop Notifications, Claude Code Terminal Notifications, Claude Code Alerts, Claude Code Sound, Claude Code Audio, Claude Code Toast, Claude Code Status, Claude Code Progress, Claude Code Monitoring, Claude Code Background, Claude Code Autonomous, Claude Code Dangerously Skip Permissions, Anthropic CLI, Anthropic Plugin, Anthropic Extension, Anthropic Claude, Anthropic AI, AI Agent Notifications, AI Agent Alerts, AI Agent Status, AI Agent Monitoring, AI Code Assistant, AI Coding, AI Programming, AI Development, Desktop Notifications, Terminal Notifications, System Notifications, Toast Notifications, Push Notifications, Sound Alerts, Audio Alerts, Notification Sound, Complete Sound, Attention Sound, WSL, WSL2, WSL Notifications, Windows Subsystem Linux, Windows 10, Windows 11, Windows Notifications, Linux Notifications, GNOME Notifications, KDE Notifications, Ubuntu Notifications, Debian Notifications, notify-send, gdbus, BurntToast, PowerShell Notifications, PulseAudio, paplay, pactl, Cross Platform, Background Tasks, Autonomous Coding, Haiku Summary, AI Summary, Task Completion, Tool Waiting, Permission Prompt, Input Required, Claude Code Hooks, Stop Hook, PreToolUse Hook, Notification Hook, Marcel Bich, marcel-bich-claude-marketplace, signal plugin, notification plugin

⚠️ **GitHub.com Fallback** ⚠️