Skip to content

Latest commit

Β 

History

History
699 lines (537 loc) Β· 39.8 KB

File metadata and controls

699 lines (537 loc) Β· 39.8 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.33.0] - 2026-03-15

Fixed

  • macOS Tahoe: click-to-focus for all terminals β€” replaced AppleScript-based window activation with the focus-window binary subcommand (AXTitle + CGS APIs) for regular terminals (iTerm2, Terminal.app, Alacritty, Warp, Hyper, etc.). macOS Tahoe (26.x) broke Automation permission prompts for notification click handlers, causing osascript to fail silently. The new approach uses Accessibility + Screen Recording instead of Automation, with graceful fallback to app-level activation when permissions are not granted (#47)
  • macOS: app always activates on click β€” when window title doesn't match the project folder name, the terminal app now still gets activated (app-level focus) instead of doing nothing
  • Symlink resolution β€” focus-window now resolves symlinks via filepath.EvalSymlinks for more robust binary path handling

Changed

  • CI: real-network E2E tests non-blocking β€” marked real-network install E2E tests as continue-on-error across all platforms to prevent flaky network timeouts from failing CI jobs

[1.32.0] - 2026-03-07

Added

  • Local plugin development tooling β€” new scripts (dev-local-plugin.sh, dev-real-plugin.sh, e2e-real-claude.sh) and Makefile targets for isolated and real-Claude plugin workflows, so contributors can reproduce plugin updates and click-to-focus issues with less setup
  • Linux focus diagnostics β€” linux-focus-debug.sh script for troubleshooting click-to-focus issues on Linux
  • Developer documentation β€” docs/LOCAL_DEVELOPMENT.md guide, expanded CONTRIBUTING.md, docs/CLICK_TO_FOCUS.md, and docs/troubleshooting.md

Fixed

  • Linux: exact window targeting for click-to-focus β€” notification clicks now capture exact window hints (X11 window ID, WM class, PID) from the hook process and use them before falling back to generic terminal title matching, significantly improving reliability on multi-window setups
  • Bootstrap plugin updates β€” hardened marketplace checkout and installed plugin version verification during bootstrap, so one-line installs recover cleanly when Claude leaves an older cached plugin version in place

[1.31.0] - 2026-03-07

Added

  • Linux: X11 window ID for click-to-focus β€” notifications now pass the terminal's X11 window ID ($WINDOWID) to the daemon, enabling direct xdotool windowactivate targeting instead of unreliable title-based matching. Includes TryFocusWithWindowID priority path and automatic fallback to existing methods
  • tmux pane target fallback β€” GetTmuxPaneTarget now uses the resolved tmux binary and explicit socket path for better compatibility across environments (e.g., when TMUX_PANE is not set)

Fixed

  • Notification suppression default β€” changed default SuppressQuestionAfterAnyNotificationSeconds from 0 to 7 seconds, preventing repeated "question" notifications immediately after other notifications

Changed

  • Improved installation instructions and error handling in install.sh β€” better diagnostic messages for curl/transport failures, especially for Windows users behind corporate proxies
  • Clarified README and setup.sh to specify commands should be run inside Claude Code

[1.30.0] - 2026-03-03

Added

  • macOS: iTerm2 + tmux -CC (control mode) click-to-focus β€” when using iTerm2's tmux integration (tmux -CC), clicking a notification now switches to the correct iTerm2 tab via the iTerm2 Python API. Standard tmux select-window doesn't work in control mode; the plugin auto-detects -CC mode and falls back gracefully if the Python API is unavailable (#41)
  • Automatic iTerm2 Python venv setup β€” bootstrap.sh and install.sh now create a Python venv with the iterm2 module for tmux -CC support (macOS only, when iTerm2 and tmux are detected)

[1.29.2] - 2026-03-03

Fixed

  • Linux: click-to-focus reliability β€” focus methods (activate-window-by-title, GNOME FocusApp, xdotool) now properly validate activation results instead of silently succeeding when no window was actually focused. xdotool windowactivate uses --sync to ensure the activation request completes (#44)
  • Linux: terminal detection in hook process β€” focus target is now detected in the hook process instead of the daemon, since the daemon may have been started from a different environment where terminal-specific env vars (e.g. TERMINATOR_UUID) are not available (#44)
  • "Updated to" message shown repeatedly β€” the [claude-notifications] Updated to vX.Y.Z system message is now shown only once per version, using a stamp file to prevent duplicates across hook invocations

Changed

  • bootstrap.sh: shim directories replace symlinks β€” old cached version paths now use a lightweight shim hook-wrapper.sh that forwards to the current install, instead of symlinks (which are unreliable on Windows)

[1.29.1] - 2026-03-02

Fixed

  • Linux: click-to-focus for Terminator β€” Terminator does not set TERM_PROGRAM, causing the daemon to fall back to generic "Terminal" and fail to find any Terminator window. Now detects Terminator via its TERMINATOR_UUID environment variable, which it always sets (#44)

[1.29.0] - 2026-03-02

Added

  • macOS: click-to-focus support for Cursor IDE β€” Cursor (VS Code fork) is now recognized as an Electron-based editor, using the binary focus-window subcommand instead of AppleScript (which fails on Electron apps with error -1708). Bundle ID com.todesktop.230313mzl4w4u92 is auto-detected via __CFBundleIdentifier (#39)

Changed

  • Renamed internal isVSCodeBundleID β†’ isElectronEditorBundleID and buildVSCodeFocusScript β†’ buildElectronEditorFocusScript to better reflect that the logic applies to all Electron-based editors, not just VS Code

[1.28.0] - 2026-03-02

Added

  • Linux: desktop-entry notification hint β€” GNOME now correctly identifies the source app when clicking notifications, focusing the terminal/VS Code instead of opening Nautilus. Also adds suppress-sound hint to prevent duplicate notification sounds (#42) β€” contributed by @ductrantrong

Fixed

  • tmux: click-to-focus targets wrong pane β€” GetTmuxPaneTarget() now reads $TMUX_PANE env var (stable, per-process) instead of tmux display-message (returns whichever pane is active). Fixes click-to-focus switching to the wrong tmux tab when the user has navigated away (#41)
  • bootstrap.sh: respect CLAUDE_CONFIG_DIR β€” bootstrap now checks CLAUDE_CONFIG_DIR (official Claude Code env var) before CLAUDE_HOME when locating the plugins directory (#43)

[1.27.0] - 2026-02-27

Added

  • Configurable suppress filters β€” new suppressFilters config array lets users suppress notifications matching specific conditions (status, git branch, folder name). All specified fields in a rule must match (AND logic); omitted fields act as wildcards. Contributed by @ekain-fr (#40)

Fixed

  • Suppress filter check before dedup lock β€” moved ShouldFilter() before AcquireLock() in hook handler to prevent filtered events from consuming dedup lock slots and blocking subsequent legitimate notifications

[1.26.0] - 2026-02-24

Added

  • Suppress notifications for subagents β€” new suppressForSubagents config option (default: true) detects subagent sessions by /subagents/ in transcript_path and suppresses notifications from both Stop and SubagentStop hooks. Covers in-process subagents, teammates, and Task tool completions

Fixed

  • Cooldown 0 was impossible to set β€” ApplyDefaults() could not distinguish "not configured" from explicit 0, silently overwriting it with 12. Changed suppressQuestionAfterTaskCompleteSeconds and suppressQuestionAfterAnyNotificationSeconds from int to *int so null = default, 0 = disabled (#37)
  • permission_prompt notifications never fired β€” suppressQuestionAfterAnyNotificationSeconds default of 12 was too aggressive, suppressing mid-task question notifications. Changed default to 0 (disabled). suppressQuestionAfterTaskCompleteSeconds (12s) remains sufficient for duplicate protection
  • Validate both cooldown fields β€” Validate() now checks suppressQuestionAfterAnyNotificationSeconds for negative values (previously only checked suppressQuestionAfterTaskCompleteSeconds)

[1.25.2] - 2026-02-21

Fixed

  • Windows: remove redundant sh prefix from hook commands β€” Claude Code already spawns a shell for hooks; the extra sh was misinterpreted as a script filename on some Windows environments, causing "cannot execute binary file" (#35)

[1.25.1] - 2026-02-21

Fixed

  • Windows: "cannot execute binary file" in non-MSYS shells β€” added fallback Windows detection via $OS environment variable (set to Windows_NT on all Windows), fixing hook failures when uname -s doesn't return MINGW/MSYS/CYGWIN
  • Git text-symlink detection β€” hook-wrapper.sh now detects when bin/claude-notifications is a Git text-symlink stub (plain text file containing a target path) instead of a real symlink, and resolves or invalidates it to prevent "cannot execute binary file" errors
  • Windows: re-detect binary after auto-install β€” after run_install on Windows, hook-wrapper.sh re-runs detect_windows_binary to prefer the freshly downloaded .exe over the .bat wrapper

[1.25.0] - 2026-02-21

Fixed

  • Windows: "cannot execute binary file" on Stop hook β€” Git Bash (MINGW) cannot exec .bat files directly; they require cmd.exe for interpretation. Added detect_windows_binary to prefer the native .exe over the .bat wrapper, and run_windows_bat to route .bat execution through cmd.exe /c call
  • CI race condition β€” real-network E2E tests now skip gracefully when the latest release binary isn't yet available (happens when CI and Release workflow run in parallel)

[1.24.0] - 2026-02-21

Added

  • Session ID prefix in notification titles β€” notifications now show [bold 06ddb8f7] instead of just [bold], making it easy to distinguish sessions even when Claude Code assigns different session IDs within the same conversation (e.g. plan mode β†’ implementation)
  • Duration and actions for all notification types β€” question, plan, review, and session limit notifications now consistently show tool counts and elapsed time (e.g. πŸ“ 2 new ⏱ 45s), not just task_complete

Changed

  • Refactored summary generation: extracted getActionsString() and appendActions() helpers to eliminate duplicated duration/tool-count logic across all status types

[1.23.0] - 2026-02-21

Added

  • Ghostty click-to-focus β€” clicking a notification focuses the correct Ghostty window via AXDocument (OSC 7 CWD file:// URL) (#34)
    • raiseWindowByAXDocument C function matches windows by AXDocument attribute
    • cwdToFileURL converts CWD to RFC-3986-compliant file:// URL via net/url
    • One-time Accessibility permission prompt on first use
  • Retry with backoff for AX window focus β€” both Ghostty and non-Ghostty paths now retry up to 3 times (150/250/400ms) instead of a single fixed sleep
    • Best case: 150ms (was 800ms for Ghostty, 600ms for others)
    • 3 chances to find the window instead of 1

Fixed

  • raiseWindowByAXTitle now checks AXIsProcessTrusted() and returns -1 on missing Accessibility permission instead of silently failing with "window not found"
  • cwdToFileURL strips trailing slash to avoid double-slash in file:// URLs

Changed

  • Split raiseWindowByTitle into findSwitchAndActivate (one-shot) + raiseWindowByAXTitle (retriable)
  • Updated documentation: README, Click-to-Focus guide, added Plugin Compatibility doc

[1.22.0] - 2026-02-20

Added

  • Zellij click-to-focus support β€” clicking a notification switches to the correct zellij tab (#33)
    • Detects $ZELLIJ / $ZELLIJ_SESSION_NAME environment variables
    • Parses active tab name from zellij action dump-layout (KDL format)
    • Executes zellij -s <session> action go-to-tab-name <tab> on notification click
  • Multiplexer registry architecture β€” extensible system for terminal multiplexer integrations
    • Adding a new multiplexer = one file + one line in the registry
    • notifier.go no longer needs changes when adding multiplexer support
    • Priority order: tmux (first), zellij (second) β€” first detected wins
  • E2E tests for zellij β€” full end-to-end tests with real zellij sessions via creack/pty

Changed

  • Refactored tmux integration β€” tmux click-to-focus now uses the shared multiplexer registry instead of hardcoded if IsTmux() checks

[1.21.0] - 2026-02-20

Added

  • Window-specific click-to-focus β€” clicking a notification now focuses the exact project window instead of just activating the app (#31)
    • macOS VS Code: CGo AXUIElement API via focus-window subcommand with cross-Space support (private CGS APIs)
    • macOS other terminals: AppleScript title search by folder name with exit repeat fix
    • Linux: folder name threaded through daemon IPC to xdotool/wlrctl/gdbus focus methods
  • Screen Recording permission prompt β€” one-time notification when Screen Recording access is needed, with click-to-open System Settings
  • SendQuickNotification() β€” standalone function for one-off notifications without a Notifier instance
  • Emoji-based compact notification format β€” shorter, more readable notification messages

Fixed

  • Window title matching β€” replaced substring matching with component-based matching (split by " β€” " / " - ") to prevent false positives (e.g., folder app no longer matches my-app)
  • AppleScript escaping β€” sanitizeForAppleScript now properly escapes ", \, and ' instead of stripping them
  • Double punctuation β€” notification messages no longer end with duplicate periods
  • Timestamp-filtered summaries β€” task and review summaries now use only recent messages

Changed

  • SendDesktop signature β€” now accepts cwd for window-specific focus: SendDesktop(status, message, sessionID, cwd)

[1.20.0] - 2026-02-19

Added

  • ClaudeNotifier.app Swift rewrite β€” full rewrite of the macOS notifier as a Swift package with UNUserNotificationCenter, hybrid fallback to osascript, and click-to-focus via NSWorkspace
  • Notification subtitle β€” git branch and folder name shown as native subtitle (main Β· my-project) instead of being crammed into the title
  • Notification actions β€” "Open" and "Dismiss" buttons on long-press/swipe via UNNotificationCategory
  • Thread grouping β€” notifications grouped by session ID via threadIdentifier, no longer replacing each other
  • Time-sensitive notifications β€” API errors and session limits break through Focus Mode via interruptionLevel = .timeSensitive (macOS 12+)
  • -nosound flag β€” suppresses Swift notification sound so Go audio player is the single sound source (fixes double sound)
  • tmux click-to-focus β€” clicking a notification in tmux switches to the correct window and pane via -execute
  • tmux E2E tests β€” comprehensive integration tests for tmux pane detection, args building, and socket path extraction
  • install.sh ClaudeNotifier.app support β€” downloads signed+notarized ClaudeNotifier.app.zip from GitHub Releases

Fixed

  • tmux shell quoting β€” tmux path and socket path properly quoted with single quotes in -execute commands
  • ARC delegate lifetime β€” withExtendedLifetime(appDelegate) prevents premature deallocation in callback mode
  • AppleScript newline escaping β€” newlines and carriage returns stripped from title/message/subtitle before passing to osascript
  • build-app.sh codesign β€” CODESIGN_FLAGS converted from string to bash array to handle spaces in entitlements path
  • Flaky CI connectivity check β€” SKIP_CONNECTIVITY_CHECK env var for E2E tests to avoid flaky curl https://github.com timeouts on macOS runners

Changed

  • SendDesktop signature β€” now accepts sessionID for thread grouping: SendDesktop(status, message, sessionID)
  • Notification title β€” cleaned up to show only status emoji + session name, metadata moved to subtitle

[1.19.0] - 2026-02-17

Fixed

  • Config survives plugin updates β€” config.json moved to ~/.claude/claude-notifications-go/config.json outside the plugin cache, so settings are no longer lost when bootstrap.sh clears the cache during updates (#30)
  • Automatic migration β€” existing config is auto-migrated from the old location on first run (atomic write with temp file + rename)
  • Resilient fallback chain β€” corrupted config never crashes the plugin; falls back to legacy path or defaults with stderr warnings
  • Cross-platform test isolation β€” setTestHome helper correctly sets both HOME and USERPROFILE for Windows compatibility
  • Lint errcheck β€” fixed unchecked os.Chmod return value in test cleanup

Changed

  • Settings wizard β€” now writes config to both stable and legacy paths for backward compatibility with older binary versions
  • Documentation β€” all config path references updated across README, webhook guides, and architecture docs

[1.18.0] - 2026-02-16

Added

  • ntfy.sh webhook documentation β€” custom webhook example for push notifications via ntfy.sh (#29)

Fixed

  • Bootstrap: version symlinks β€” after update, creates symlinks from old version dirs to the new one so running Claude Code sessions don't break before restart
  • Bootstrap: Bash 3.2 compatibility β€” fixed empty array handling for macOS default bash

Changed

  • Updating section in README β€” simplified to use the same bootstrap command as installation
  • Bootstrap success message β€” clarifies that update command is same as install

[1.17.0] - 2026-02-16

Added

  • One-command bootstrap installer β€” curl -fsSL .../bootstrap.sh | bash handles marketplace setup, plugin install, and binary download in a single command
  • error.mp3 sound β€” dedicated error alert sound for API errors and session limit notifications (replaces reused question.mp3)

Changed

  • Session names β€” simplified from two-word bold-cat to single-word cat format for cleaner notification titles
  • Notification title format β€” session ID moved after branch name: βœ… Completed main [cat] instead of βœ… Completed [bold-cat] main
  • README installation section β€” bootstrap method is now primary, manual install moved to collapsible fallback

[1.16.0] - 2026-02-16

Added

  • Terminal bell for tab indicators πŸ”” (#28, thanks @retr0h!)
    • Sends BEL character (\a) to trigger terminal tab indicators (Ghostty tab highlight, tmux window bell flag)
    • Works independently of desktop notifications β€” bell fires even when desktop notifications are disabled
    • New terminalBell config option (default: true)
    • Cross-platform: /dev/tty on Unix, os.Stdout on Windows
    • Graceful degradation: silently skipped if TTY unavailable (Docker, CI, piped environments)
  • list-sounds CLI utility β€” lists all available notification sound files (#23)
  • /sounds skill command β€” interactive sound browser with preview from Claude Code

Changed

  • Updated notification sound files for plan readiness and review completion statuses

[1.15.1] - 2026-02-15

Added

  • GNOME Terminal detection β€” detect GNOME Terminal via GNOME_TERMINAL_SCREEN / GNOME_TERMINAL_SERVICE env vars for click-to-focus support on Linux (#22, thanks @ductrantrong)

Fixed

  • Windows checksum verification β€” strip leading backslash from sha256sum output on Windows (MSYS2/Git Bash/Cygwin) which caused checksum mismatch (#26)

[1.15.0] - 2026-02-07

Changed

  • Unified API Error notifications β€” merged api_error (401) and api_error_overloaded into a single API Error type in documentation
  • Updating section β€” documented auto-update mechanism via hook-wrapper.sh with manual fallback
  • Release checklist β€” added docs/RELEASE.md with version bump locations, auto-update explanation, and full release steps

Fixed

  • install.sh β€” install_gnome_activate_window_extension() now returns failure code when GNOME shell/extensions not found or extension couldn't be enabled (#19)

[1.14.0] - 2026-01-16

Added

  • Per-status notification control πŸŽ›οΈ (#16)
    • Disable individual notification types (e.g., disable only task_complete while keeping others)
    • New enabled field in status config: "enabled": false to disable a specific type
    • Backward compatible: missing enabled field defaults to true
    • Updated /notifications-settings wizard with Step 4.5 for selecting notification types
    • Example config to disable task_complete:
      {
        "statuses": {
          "task_complete": { "enabled": false, "title": "...", "sound": "..." }
        }
      }

Technical

  • Added Enabled *bool field to StatusInfo struct (pointer for nil = true default)
  • New methods: IsStatusEnabled(), IsStatusDesktopEnabled(), IsStatusWebhookEnabled()
  • Updated sendNotifications() to check per-status enabled
  • 14 new tests for per-status enabled functionality

[1.13.0] - 2026-01-11

Added

  • Console notification on plugin update - shows warning message in Claude Code console when binary is installed or updated
    • First install: [claude-notifications] Installed v1.13.0
    • Update: [claude-notifications] Updated to v1.13.0
    • Uses systemMessage JSON format for Claude Code hook response

Technical

  • Added systemMessage output to hook-wrapper.sh for user-visible notifications
  • New E2E test for systemMessage output

[1.12.0] - 2026-01-11

Added

  • Automatic version-aware updates - wrapper now checks if binary version matches plugin version
    • After Claude auto-updates plugin files, binary is automatically updated on next hook call
    • Compares claude-notifications version output with plugin.json version
    • Uses --force flag to replace outdated binaries
    • Fallback: if version check fails, still works based on file existence

Technical

  • Added version comparison logic to hook-wrapper.sh
  • 4 new E2E tests for version checking (mismatch triggers update, match skips update, etc.)

[1.11.0] - 2026-01-11

Added

  • Auto-download after plugin auto-update - binaries now download automatically when hook is first called
    • Previously: after Claude auto-updated the plugin, binary was missing and hooks failed
    • Now: hook-wrapper.sh detects missing binary and triggers download on first use
    • Zero downtime: if download fails, hooks exit gracefully without blocking Claude
    • POSIX-compatible wrapper works on macOS, Linux, and Windows (Git Bash)

Technical

  • New bin/hook-wrapper.sh - lazy binary download wrapper
  • Updated hooks/hooks.json - all hooks now use wrapper
  • 17 new E2E tests for hook-wrapper covering offline, mock, and real network scenarios

[1.10.0] - 2026-01-10

Added

  • notifyOnTextResponse config option - notifications now arrive for text-only responses (e.g., extended thinking "Baked for 32s")
    • Default: true (enabled)
    • Set to false in config to disable notifications when Claude responds without using tools

Fixed

  • Fixed test flakiness on Go 1.25+ by cleaning up stale state files between test runs

[1.9.0] - 2026-01-10

Added

  • Windows CI tests - install.sh now tested on all 3 platforms (macOS, Linux, Windows)
  • Binary execution verification - installer now verifies downloaded binary actually runs (--version check)
  • Network error diagnostics - detailed hints for DNS, SSL, timeout, and firewall issues
  • Graceful offline mode - if GitHub is unreachable but binary exists, uses existing installation

Improved

  • Cross-platform compatibility for install.sh:
    • Windows-compatible ping syntax (-n/-w instead of -c/-W)
    • Portable temp directory (${TMPDIR:-${TEMP:-/tmp}})
    • Proper .bat wrapper creation on Windows
    • Extended regex with grep -E for portability
  • E2E test coverage - 35+ tests covering offline, mock server, and real network scenarios
  • Utility downloads are now non-blocking - if sound-preview or list-devices fail, main install continues

Fixed

  • Fixed installer hanging when optional utility downloads fail
  • Fixed checksum verification for cross-platform builds

[1.8.0] - 2026-01-10

Added

  • double-shot-latte compatibility 🀝
    • Notifications are now automatically suppressed when running in background judge mode
    • Detects CLAUDE_HOOK_JUDGE_MODE=true environment variable set by double-shot-latte plugin
    • Zero configuration required - just update the plugin and it works automatically
    • Other plugin developers can use the same mechanism to suppress notifications in background Claude instances

Documentation

  • Added 🀝 Plugin Compatibility section to README
  • Documented how other plugins can suppress notifications using CLAUDE_HOOK_JUDGE_MODE=true

[1.7.2] - 2026-01-10

Improved

  • Auto-update now always works - /claude-notifications-go:notifications-init reliably updates binaries even from old cached plugins
    • Downloads latest install.sh directly from GitHub before running
    • Uses --force flag to replace existing binaries
    • Cross-platform temp directory ($TMPDIR, $TEMP, /tmp fallback)
    • Fixes: old cached plugins used outdated installer without utility download support

[1.7.1] - 2026-01-10

Fixed

  • Installer now downloads utility binaries (#14)
    • sound-preview and list-devices were missing after /claude-notifications-go:notifications-init
    • Installer script now downloads all three binaries
    • Creates proper symlinks for all utilities

[1.7.0] - 2026-01-10

Added

  • Audio device selection support πŸ”Š (thanks @tkaufmann!)
    • Route notification sounds to a specific audio output device
    • New audioDevice config option in notifications.desktop section
    • New list-devices CLI tool to enumerate available audio devices
    • New --device flag for sound-preview utility

Changed

  • Audio backend replacement - Replaced oto/v3 (beep/speaker) with malgo (miniaudio bindings)
    • Better cross-platform audio support
    • Native device enumeration and selection
    • More reliable playback on all platforms

Fixed

  • Windows CI test failures - Fixed .exe extension handling in cross-platform tests
  • Memory safety - DeviceID now properly copied instead of storing pointer to freed memory
  • Player state check - Play() now returns error if player is already closed
  • WaitGroup race condition - Added closing flag to prevent race between Close() and playSoundAsync()
  • CI test resilience - Audio tests now skip gracefully in CI environments without audio backend

[1.6.6] - 2026-01-10

Fixed

  • Ghost notifications after 60 seconds πŸ‘» (#11)
    • idle_prompt hook was firing 60 seconds after PreToolUse(AskUserQuestion)
    • This caused duplicate "Question" notifications with delay
    • Now Notification hook only responds to permission_prompt, ignoring idle_prompt
    • AskUserQuestion is already covered by PreToolUse hook (instant notification)

[1.6.5] - 2025-12-31

Fixed

  • Proper Unicode handling for multibyte characters 🌍 (thanks @patrick-fu!)
    • Text truncation now uses rune count instead of byte count
    • Emoji, CJK, Cyrillic and other multibyte characters no longer get cut mid-character
    • truncateText and extractFirstSentence work correctly with international text

[1.6.4] - 2025-12-31

Fixed

  • CI tests now pass in GitHub Actions πŸ§ͺ
    • TestGetGitBranch_RealRepo failed in CI due to detached HEAD from PR checkout
    • Now uses isolated temporary git repository with known branch name
    • Added TestGetGitBranch_DetachedHead to verify empty string for detached HEAD

[1.6.3] - 2025-12-26

Fixed

  • Fixed fallback logic in content lock πŸ”’
    • v1.6.2 had a bug: when lock was busy, code still proceeded without lock
    • Now correctly exits when another process holds the lock
    • Only uses fallback on actual errors (e.g., /tmp unavailable)

[1.6.2] - 2025-12-26

Fixed

  • Race condition in content-based deduplication πŸ”’
    • Stop and Notification hooks were running simultaneously, both passing duplicate check
    • Added shared content lock to serialize duplicate check and state update
    • Now only one hook can check and save notification state at a time
    • Prevents duplicate notifications when different hooks fire near-simultaneously

[1.6.1] - 2025-12-26

Fixed

  • Version numbers no longer break sentence extraction πŸ”§
    • Text like "Π‘ΠΈΠ½Π°Ρ€Π½ΠΈΠΊ v1.6.0 установлСн!" was incorrectly cut at "v1."
    • Now correctly handles version numbers, decimals, IP addresses
    • Dots after digits are no longer treated as sentence endings

[1.6.0] - 2025-12-26

Added

  • Folder name in notification titles πŸ“

    • Notification titles now show the project folder name
    • Format: βœ… Completed [session-name] main my-project
    • Helps identify which project the notification is from
  • Content-based duplicate detection πŸ”‡

    • Prevents duplicate notifications with similar text within 3 minutes
    • Normalizes messages (ignores trailing dots, case differences)
    • Example: "Completed" and "Question" with same text won't both show
    • Fixes issue where different hooks sent near-identical notifications

[1.5.0] - 2025-12-25

Added

  • Git branch name in notifications 🌿
    • Notification titles now show the current git branch
    • Format: βœ… Completed [session-name] main
    • Only shown when working in a git repository

[1.4.2] - 2025-12-24

Fixed

  • Click-to-focus now works on macOS Sequoia (15.x) 🎯
    • Removed -sender option that was conflicting with -activate
    • Trade-off: notifications no longer show custom Claude icon
    • Click-to-focus now reliably activates terminal window

[1.4.1] - 2025-12-24

Fixed

  • Skip terminal-notifier integration test in CI (no NotificationCenter available)

[1.4.0] - 2025-12-24

Added

  • Click-to-focus notifications on macOS 🎯

    • Clicking a notification activates your terminal window
    • Auto-detects terminal app (Warp, iTerm, Terminal, kitty, Alacritty, etc.)
    • Uses terminal-notifier under the hood
    • Enable with "clickToFocus": true in desktop config (enabled by default)
    • Manual override: "terminalBundleID": "com.your.terminal"
  • Claude icon in notifications πŸ€– (removed in 1.4.2 due to macOS Sequoia conflict)

    • Custom Claude icon displayed on the left side of macOS notifications
    • Auto-creates ClaudeNotifications.app on first notification
    • ⚠️ Removed in v1.4.2: -sender option conflicted with click-to-focus on macOS 15.x

Changed

  • Shorter notification titles
    • βœ… Task Completed β†’ βœ… Completed
    • πŸ” Review Completed β†’ πŸ” Review
    • ❓ Claude Has Questions β†’ ❓ Question
    • πŸ“‹ Plan Ready for Review β†’ πŸ“‹ Plan

Technical

  • Terminal bundle ID detection via __CFBundleIdentifier and TERM_PROGRAM
  • Uses -sender com.claude.notifications for reliable icon display (removed in 1.4.2)

[1.3.0] - 2025-12-24

Added

  • Lark/Feishu webhook support - New webhook preset for Lark (飞书) notifications
    • Interactive card format with colored headers based on notification status
    • Supports all notification types (Task Complete, Review Complete, Question, Plan Ready)
    • Wide screen mode for better readability
    • Session ID included in notifications
    • Add "preset": "lark" to webhook configuration to enable

[1.2.1] - 2025-12-14

Fixed

  • Webhook notifications never sent (#6)
    • Shutdown() now waits for in-flight HTTP requests to complete before exit
    • Added defer webhookSvc.Shutdown(5s) to HandleHook() for graceful shutdown
    • Previously: cancel() was called immediately, interrupting HTTP requests
    • Now: cancel() is only called after completion or on timeout

Added

  • E2E test TestE2E_WebhookGracefulShutdown - deterministic graceful shutdown verification
  • Unit tests for Shutdown() + SendAsync() combination
  • Updated webhookInterface to include Shutdown(timeout) method

[1.2.0] - 2025-11-03

Added

  • Subagent notification control - New config option notifyOnSubagentStop
    • Prevents premature "Completed" notifications when Task agents (subagents) finish
    • Main Claude session continues working without distracting notifications
    • Default: false (notifications disabled for subagents)
    • Users can enable via "notifyOnSubagentStop": true in config if desired
    • Fixes issue where Plan/Explore agents triggered completion notifications while Claude was still thinking

Changed

  • SubagentStop hook now checks config before sending notifications
  • Split SubagentStop and Stop hook handling for better control

Technical Details

  • Added NotifyOnSubagentStop boolean field to NotificationsConfig struct
  • Updated hook handler in internal/hooks/hooks.go to respect config setting
  • Added comprehensive tests for both enabled and disabled states
  • All existing tests pass with new functionality

[1.1.2] - 2025-10-25

Fixed

  • Volume control on macOS πŸ”Š
    • Replaced effects.Volume with effects.Gain for reliable volume control
    • Volume settings (e.g., 30%) now work correctly on macOS
    • Simplified volume conversion logic (linear instead of logarithmic)
    • Affects both notification sounds and sound-preview utility
    • All tests passing with new implementation
  • GitHub Actions build step - Windows builds now work correctly
    • Added shell: bash to build step for all platforms
    • Resolved PowerShell syntax error preventing Windows builds from completing

Changed

  • Simplified volumeToGain() function - removed complex logarithmic calculations
  • Updated documentation in code to reflect linear gain formula: output = input * (1 + Gain)

[1.1.1] - 2025-10-25

Fixed

  • Missing sound-preview binary - fixes /notifications-settings sound preview
    • Added sound-preview utility to build system
    • Now built for all platforms (darwin, linux, windows)
    • Included in GitHub Releases
    • Supports interactive sound preview during settings configuration
    • Handles MP3, WAV, FLAC, OGG, AIFF formats

[1.1.0] - 2025-10-25

Added

  • New notification type: API Error 401 πŸ”΄
    • Detects authentication errors when OAuth token expires
    • Shows "πŸ”΄ API Error: 401" with message "Please run /login"
    • Triggered when both "API Error: 401" and "Please run /login" appear in assistant messages
    • Priority detection (checks before tool-based detection)
    • Added comprehensive tests for API error detection

Improved

  • Binary size optimization - 30% smaller release binaries
    • Production builds now use -ldflags="-s -w" -trimpath flags
    • Binary size reduced from ~10 MB to ~7 MB per platform
    • Faster download times for users (5 seconds instead of 8 seconds)
    • Better privacy (no developer paths in binaries)
    • Deterministic builds across different machines
    • Development builds unchanged (still include debug symbols)

Changed

  • Updated notification count from 5 to 6 types in README
  • All tests passing with new features

[1.0.3] - 2025-10-24

Fixed

  • Critical bug in duration calculation ("Took" time in notifications)
    • User text messages were not being detected in transcript parsing
    • GetLastUserTimestamp now correctly parses string content format
    • Duration now shows accurate time (e.g., "Took 5m" instead of "Took 2h 30m")
    • Tool counting now accurate (prevents showing inflated counts like "Edited 32 files")
  • Added custom JSON marshaling/unmarshaling for MessageContent to handle both string and array content formats

Technical Details

  • Fixed pkg/jsonl/jsonl.go: Added ContentString field and custom UnmarshalJSON/MarshalJSON methods
  • User messages with "content": "text" format now properly parsed (previously only array format worked)
  • All existing tests pass + added new tests for string content parsing

1.0.2 - 2025-10-23

Added

  • Linux ARM64 support for Raspberry Pi and other ARM64 Linux systems (#2)
    • Native ARM64 runner (ubuntu-24.04-arm) for reliable builds
    • Full audio and notification support via CGO
    • Automatic binary download via /claude-notifications-go:notifications-init command

Fixed

  • Webhook configuration validation now only runs when webhooks are enabled (#1)
    • Previously caused "invalid webhook preset: none" error even with webhooks disabled
    • Preset and format validation now conditional on webhook.enabled flag

Changed

  • Documentation updates for clarity and platform-specific instructions

1.0.1 - 2025-10-22

Added

  • Windows ARM64 binary support
  • Windows CMD and PowerShell compatibility improvements

Fixed

  • Plugin installation and hook integration issues
  • Plugin manifest command paths
  • POSIX-compliant OS detection for better cross-platform support

1.0.0 - 2025-10-20

Added

  • Initial release of Claude Notifications plugin
  • Cross-platform desktop notifications (macOS, Linux, Windows)
  • Smart notification system with 5 types:
    • Task Complete
    • Review Complete
    • Question
    • Plan Ready
    • Session Limit Reached
  • State machine analysis for accurate notification detection
  • Webhook integrations (Slack, Discord, Telegram, Custom)
  • Enterprise-grade webhook features:
    • Retry logic with exponential backoff
    • Circuit breaker for fault tolerance
    • Rate limiting with token bucket algorithm
  • Audio notification support (MP3, WAV, FLAC, OGG, AIFF)
  • Volume control (0-100%)
  • Interactive setup wizards
  • Two-phase lock deduplication system
  • Friendly session names
  • Pre-built binaries for all platforms
  • GitHub Releases distribution

Fixed

  • Error handling improvements across webhook and notifier packages
  • Data race in error handler
  • Question notification cooldown system
  • Cross-platform path normalization