Blog · September 14, 2026 · 8 min read
Claude Code Notifications Not Working: A Diagnostic Checklist
You followed a setup guide. You set the config key. You ran a long task, went to make coffee, came back eleven minutes later and Claude Code had been sitting on a permission prompt for nine of them. No sound, no banner, nothing.
Claude Code notifications almost never fail for interesting reasons. There are four places the signal gets dropped, they are strictly ordered, and testing them out of order is why people spend an hour on a five-minute problem. Work down the list and stop at the first thing that is wrong.
The chain, in the order it breaks
A notification has to survive four hops: Claude Code decides to emit one, it picks a channel, your terminal turns that channel into something the OS understands, and the OS decides whether you are allowed to see it. Each hop fails silently, which is what makes this annoying to debug.
- Claude Code is using a channel your terminal cannot serve.
- Your terminal has the relevant feature switched off.
- The OS has not granted your terminal notification permission.
- The notification is firing correctly somewhere you are not looking.
Cause 1: the channel does not match your terminal
This is the big one, and it catches most people. Claude Code only sends a desktop notification natively in a handful of terminals — Ghostty, Kitty and iTerm2. If you are in macOS Terminal.app, VS Code integrated terminal, Windows Terminal, Warp, or basically anything else, the default channel has nothing to talk to and the notification evaporates.
The setting that controls this is preferredNotifChannel, a top-level key in ~/.claude/settings.json. The accepted values are auto, terminal_bell, iterm2, iterm2_with_bell, kitty, ghostty, and notifications_disabled.
The fastest diagnostic in this whole article: force the dumbest possible channel and see whether anything happens at all.
{
"preferredNotifChannel": "terminal_bell"
}Restart Claude Code and run something short. If you now get a bell, the emit side works fine and your problem was the channel. If you get nothing even from the bell, skip to cause 2 — the bell is a terminal feature and yours may have it muted.
Worth checking for a value you did not expect: if someone on your team shared a settings file, or you copied one from a blog post, you may have notifications_disabled sitting in there. It does exactly what it says and gives no indication that it is doing it. The full option breakdown is in our preferredNotifChannel guide.
Cause 2: the terminal is swallowing it
Terminals do not forward alerts by default, and iTerm2 in particular needs two separate things switched on before an escape-sequence alert becomes a Notification Center banner.
In iTerm2, open Settings, then Profiles, then Terminal. Enable Notification Center Alerts. Then, under Filter Alerts, enable Send escape sequence-generated alerts. People routinely find the first one already on and the second one off, which produces precisely the symptom you are debugging: the mechanism looks configured and nothing arrives.
If you set terminal_bell and heard nothing, the bell itself is probably muted. Most terminals have an audible-bell toggle buried in profile settings, and many people turned it off years ago after one too many tab-completion beeps. Turn it back on temporarily while you test, and consider iterm2_with_bell if you want both a banner and a sound.
Cause 3: the OS never granted permission
On macOS, open System Settings, then Notifications, and find your terminal app in the list. The permission has to belong to the terminal — Claude Code runs inside it and does not appear separately.
There is a useful piece of diagnostic information hiding here. If your terminal app is missing from the list entirely, it has never once attempted to post a notification. That is not a permissions problem at all; it means you are still stuck on cause 1 or 2, and fiddling with System Settings will not help. An app only appears in that list after its first attempt.
Also worth ruling out in about ten seconds: Focus modes and Do Not Disturb. A Focus that you set up for deep work and forgot about will suppress exactly the notifications you most wanted during deep work. If you use one routinely, add your terminal to its allowed list rather than turning the Focus off. If you are hitting the specific macOS message about Claude notifications being turned off, we covered that one separately in notifications are turned off for Claude.
Cause 4: it works, but not where you are
The last category is the one that feels like a bug and is not. The notification fired perfectly — into a machine, a session, or a screen that you were not in front of.
- SSH. Claude Code running on a remote box emits its notification on that box. Escape-sequence channels can survive the hop to your local terminal; anything that calls a local OS API cannot.
- tmux and screen. Multiplexers intercept escape sequences by design. Unless tmux is explicitly configured to pass the bell through, it stops there. Our tmux and SSH notifications guide covers the passthrough settings.
- A background or hidden window. Some terminals suppress alerts from the frontmost tab on the theory that you can already see it. If you tested by watching the window, you may have tested the one case that is designed not to notify.
- Detached and background tasks. Long-running background work does not always route through the same notification path as the main loop. Worth knowing if that is where your waiting happens.
A two-minute test that isolates the layer
Rather than changing three things and re-running a twenty-minute task, test the layers directly and from the bottom up:
- Run
printf '\a'in your terminal. If you hear nothing, the bell is muted — that is a terminal setting, and no Claude Code config will fix it. - Check whether your terminal appears in the OS notification list at all. Absent means nothing has ever tried.
- Set
preferredNotifChanneltoterminal_bell, restart Claude Code, and run a task that takes ten seconds. Bell means the emit side is healthy. - Only then switch to your terminal-native channel and retest, with the terminal window in the background.
Four checks, each one eliminating a whole layer. The reason this beats guessing is that every layer fails the same way — silence — so the only way to tell them apart is to test them one at a time.
When the terminal is the wrong place for this
Being honest about the ceiling here: every fix above puts the notification on the machine running Claude Code, in a terminal that has to be configured correctly, on an OS that has to cooperate. That chain works well when you are sitting at that machine with the window behind your browser. It works poorly when Claude Code is on a server, when you are in a meeting in another room, or when you have four sessions running and need to know which one is blocked.
If that is your situation, the terminal is not really the right destination for the signal — a phone notification removes the entire four-layer chain, because nothing about it depends on which terminal emulator you happen to like. If you would rather keep everything local, the notification hook scripts give you full control over what fires and when.
Either way, the goal is the same one: stop paying attention to a terminal that is not doing anything yet.
Keep reading
Claude Code Tips and Tricks: 12 Ways to Use Claude Code Effectively
8 min read
Claude Code Multiple Sessions: How to Run Agents in Parallel Without Losing Track
6 min read
A Claude Code Workflow That Doesn't Involve Watching the Terminal
5 min read
Claude Code Hooks: A Practical Guide to Automating Your Agent Workflow
7 min read
Claude Code Auto Mode: Fewer Permission Prompts Without Living Dangerously
7 min read
Claude Code Subagents: How to Delegate Work to Specialized Agents
7 min read
Claude Code Context Management: Treat the Context Window Like a Budget
6 min read
Per-Subagent Model Selection: Route the Grunt Work Down, Keep the Judgment Up Top
7 min read
Skills and Plugins: How to Teach Claude Code Your Way of Working
7 min read
Claude Code Background Tasks: Run Long Commands Without Blocking Your Session
6 min read
Codex CLI Notifications: How to Get a Ding When Codex Is Done or Needs Input
7 min read
Cursor Notification When Done: Every Way to Get Notified When Cursor Finishes
6 min read
Claude Code Notifications: How to Get Notified When Claude Code Finishes or Needs Your Input
6 min read
Want to Be Notified When Claude Responds? How Claude Notifications Work on Web, Desktop, and Mobile
5 min read
Claude Code Notification Scripts: Copy-Paste Recipes for Every Platform
6 min read
Get a Ding the Moment Codex Needs Your Response
6 min read
Get Notified the Moment Claude Code Is Waiting for Your Input
6 min read
“Notifications Are Turned Off for Claude” — Here Is the Fix
6 min read
Codex Sound When Done: Make Codex CLI Play a Sound When It Finishes
6 min read
terminal-notifier + Claude Code: Native macOS Alerts When Your Agent Finishes
6 min read
Gemini CLI Notifications: How to Get a Sound or Alert When Gemini Finishes
6 min read
Get Claude Code Notifications on Your Phone
6 min read
Claude Code Remote Control, Explained
7 min read
preferredNotifChannel: Claude Code's Built-In Notification Setting
6 min read
Claude Code Notifications in tmux and Over SSH
7 min read
Claude Code Effort Levels: Why Your Setting Keeps Getting Ignored
8 min read
Codex vs Claude Code Notifications: How Each One Tells You It Is Done
8 min read