Pushary

Claude Code notifications
not working.

There are four causes and they are easy to tell apart. The OS is blocking the app that raises the alert, preferredNotifChannel names a channel your terminal cannot serve, the config command in most guides was removed, or the hook sits on Stop and fires every turn.

The OS permission is yours to grant. For the other three, npx @pushary/agent-hooks bell raises the alert itself on the right event, so the channel setting stops mattering. No account, no API key, no network call.

The four causes, in the order they happen

The OS is blocking the app that raises it

Claude Code has no application bundle of its own, so a desktop alert is raised by whatever is hosting the session: your terminal emulator, or the Claude app if you are on Claude Desktop. The permission lives against that app, not against something called Claude Code. Open System Settings, then Notifications, find Ghostty, iTerm2, Kitty, Terminal or Claude, and switch Allow notifications on.

preferredNotifChannel is on a channel your terminal cannot serve

The default is auto, which raises a real desktop notification in iTerm2, Ghostty and Kitty and does nothing at all anywhere else. In Terminal.app, Warp, tmux or the VS Code integrated terminal, auto is silence. Set terminal_bell there instead and you get an audible bell that every terminal can ring.

The config command in most guides no longer exists

claude config set --global preferredNotifChannel terminal_bell is still the command in most blog posts and it now fails with error: unknown option '--global', because the config subcommand was removed. The setting is a plain top-level key in ~/.claude/settings.json, so write it there instead of through the CLI.

The hook is on Stop, which fires on every turn

Stop looks like the finished event and is not: it fires after every assistant turn, so a bell there rings constantly and gets muted within an hour, which reads later as notifications not working. The Notification event carries the moments you actually want, matched on idle_prompt, agent_needs_input and agent_completed.

Which channel your terminal can actually serve

preferredNotifChannel is a top-level key in ~/.claude/settings.json. The accepted values are auto, terminal_bell, iterm2, iterm2_with_bell, kitty, ghostty and notifications_disabled.

TerminalSet preferredNotifChannel toWhat you get
Ghosttyauto or ghosttyDesktop notification
iTerm2auto, iterm2 or iterm2_with_bellDesktop notification
Kittyauto or kittyDesktop notification
Terminal.appterminal_bellAudible bell only
Warpterminal_bellAudible bell only
VS Code terminalterminal_bellAudible bell only
tmux or sshterminal_bellAudible bell only

Every one of these fixes stops at your desk

Once the banner works, it works in front of the screen you walked away from. Every preferredNotifChannel value is local to the machine Claude Code is running on, so the moment you leave the desk the notification system is doing nothing for you again. That is the design, not a fault.

Pushary takes the same three moments, idle_prompt, agent_needs_input and agent_completed, and sends them to your phone. When Claude is blocked on a question it holds the call until you answer from the lock screen, and writes every question and answer to a log you can replay.

Questions people ask when the bell stays quiet

Why does it say notifications are turned off for Claude?

That message comes from macOS, and it refers to the application that tried to raise the alert rather than to Claude Code itself. Claude Code is a CLI with no app bundle, so the alert is raised by your terminal emulator; on Claude Desktop it is raised by the Claude app. Open System Settings, then Notifications, find that app in the list, and turn Allow notifications on. If the app is missing from the list entirely it has never attempted a notification, which usually means preferredNotifChannel is set to a channel it cannot serve.

How do I enable Claude Code notifications?

Two things have to be true. The app raising the alert needs OS permission, set in System Settings then Notifications. And preferredNotifChannel has to name a channel your terminal can actually serve: auto for iTerm2, Ghostty and Kitty, terminal_bell for everything else. Write it as a top-level key in ~/.claude/settings.json. Or run npx @pushary/agent-hooks bell, which sidesteps the second half by raising the alert itself rather than relying on the channel. The OS permission is still yours to grant either way.

Why do I get no notification in Ghostty or iTerm2?

Ghostty, iTerm2 and Kitty are the three terminals where the default auto channel raises a real desktop notification, so if one of them is silent the cause is almost always OS permission rather than configuration. Check System Settings, then Notifications, for that terminal. The other common cause is a Focus mode or Do Not Disturb schedule that suppresses the banner without changing any Claude setting.

How do I get a terminal bell when Claude Code finishes?

Set preferredNotifChannel to terminal_bell in ~/.claude/settings.json. This is the channel to use in Terminal.app, Warp, tmux, over ssh and in the VS Code integrated terminal, because none of them can raise a desktop notification through the auto channel. The command most guides still show, claude config set --global preferredNotifChannel terminal_bell, fails with error: unknown option '--global' because the config subcommand was removed.

Why does my notification hook fire on every reply?

Because it is registered on Stop. Stop fires after every assistant turn rather than once when the work is done, so a bell there rings on each reply. Move the hook to the Notification event and match on idle_prompt, agent_needs_input and agent_completed. Those are the moments where Claude Code has judged you stepped away or it needs an answer.

Do Claude Code desktop notifications reach my phone?

No. Every preferredNotifChannel value is local to the machine Claude Code is running on, so a banner or a bell only exists in front of the screen you already left. That is the limit of the built-in notification system rather than a bug in it. Pushary sends the same moments to your phone and, when Claude is blocked on a question, holds the call until you answer it from the lock screen.

Fix the bell, then stop needing to be at the desk.

The local bell is free and always will be. When you want the same moments on your phone, with one-tap approvals and a log, that is Pushary.

99.9%Delivered
Hacker NewsFeatured on Hacker News
3-4xvs Email