Wire Claude Code hooks to macOS notifications via terminal-notifier
Rashwan Lazkani shows how to connect Claude Code's lifecycle hooks to native macOS notifications using `terminal-notifier`, so you're alerted the moment Claude needs input instead of constantly checking VS Code.
Score breakdown
This configuration replaces constant manual monitoring of Claude Code sessions with async macOS notifications, making it possible to genuinely step away while Claude works and return only when input is needed.
- 01The setup uses `terminal-notifier`, installed via `brew install terminal-notifier`, to post native macOS notifications from Claude Code hooks.
- 02Hooks are configured in `~/.claude/settings.json` under a `hooks` block covering the `Stop` and `PermissionRequest` events.
- 03Three notification types are supported: permission required, plan ready for review, and task completed.
Rashwan Lazkani identifies a core usability gap in Claude Code's VS Code extension: when Claude pauses to request a permission or present a plan for review, nothing alerts the user. The default setup forces a choice between staying glued to the editor or walking away and returning to find Claude has been idle for minutes. The fix connects three existing pieces — macOS's notification system, VS Code extension support, and Claude Code's shell-command hooks — without any custom tooling beyond `terminal-notifier`.
Two hook types are used: `Stop` fires when Claude finishes a turn (covering task completion), and `PermissionRequest` fires when Claude needs approval — covering both tool permission requests and plan-mode reviews.
The configuration lives in `~/.claude/settings.json` under a `hooks` block. Two hook types are used: `Stop` fires when Claude finishes a turn (covering task completion), and `PermissionRequest` fires when Claude needs approval — covering both tool permission requests and plan-mode reviews. The `PermissionRequest` hook reads the `tool_name` field from stdin via `jq` and switches the notification message between "Permission required" and "Plan ready for review" depending on whether the tool is `ExitPlanMode`. Each hook calls `/opt/homebrew/bin/terminal-notifier` with the `-activate com.microsoft.VSCode` flag so clicking the notification refocuses the editor.
Lazkani highlights two critical implementation details: always use the absolute path `/opt/homebrew/bin/terminal-notifier` because VS Code launched from the Dock does not inherit shell `PATH`, causing silent failures; and use the `CLAUDE_PROJECT_DIR` environment variable rather than `$PWD` because hooks are not guaranteed to run with the project as the working directory. He also notes that the `Stop` hook fires on every response including quick replies, so users who find "Task completed" too noisy can remove that block and keep only the `PermissionRequest` hook.
Key facts
- 01The setup uses `terminal-notifier`, installed via `brew install terminal-notifier`, to post native macOS notifications from Claude Code hooks.
- 02Hooks are configured in `~/.claude/settings.json` under a `hooks` block covering the `Stop` and `PermissionRequest` events.
- 03Three notification types are supported: permission required, plan ready for review, and task completed.
- 04Clicking a notification triggers `-activate com.microsoft.VSCode`, bringing the editor back into focus.
- 05The absolute path `/opt/homebrew/bin/terminal-notifier` must be used because VS Code launched from the Dock does not inherit shell PATH.
- 06`CLAUDE_PROJECT_DIR` is the reliable env variable for the project name, as hooks may not run with the project as the working directory.
- 07Plan-mode approval events go through `PermissionRequest`, not `PreToolUse`; the hook checks `tool_name` via `jq` to distinguish plan reviews from tool permission requests.
Topics
Summary and scoring are generated automatically from the original article. We always link back to the publisher and never republish images or paywalled content. Last processed Jun 15, 2026 · 11:57 UTC. How this works →