AI coding agent notifications: fine for one session, chaos for a fleet
Your phone buzzes. Second time this hour. You check it mid-lunch,
expecting the session stuck on the git push --force you approved
this morning. Wrong pane. This one finished eleven minutes ago and
wants to know whether the branch is called dev or develop.
The session that is actually stuck, sitting on a permission prompt for a command it has never asked about before, fired the identical buzz. You read it the way you read the last four: not now.
Nothing here is broken. Every alert fired exactly when it was built to. The problem was never whether your AI coding agent notifies you. It's that one notification, at one volume, cannot tell you which of five sessions actually needs you and which one can wait. Read enough of them and you stop reading any of them closely.
Why notifications work for one AI coding agent and fail for a fleet
One session, one terminal: a notification is a tap on the shoulder. Rare, specific, easy to act on. It fires, you look, you deal with it, you go back to what you were doing.
Run four or five sessions the way a solo developer runs a fleet, and the alert does not get any smarter, it just multiplies. Every engine's built-in notification is one channel: a banner, a bell, a buzz. None of them rank a blocked destructive command above a session that finished and is only waiting on your next prompt. Volume goes up. Information per alert goes down.
Claude Code's hooks already name this trade honestly: wiring a sound to a Notification event is trivial with one agent, and the sentence worth finishing is what happens once you run several at once. What happens is alert fatigue, the same mechanism that makes permission prompts stop working as a safety net: a control that depends on you reading closely fails once there is too much to read closely.
How Claude Code, Codex and Gemini CLI try to get your attention
The mechanics genuinely differ, which matters the moment you run more than one.
| Engine | Built-in default | Granularity | Delivery |
|---|---|---|---|
| Claude Code | None, you wire the OS command yourself | 8 matchers, including 2 built for background sessions | Your own osascript, notify-send, or PowerShell hook |
| Codex | notify config key |
1 event: the turn ends | A registered command run with a JSON payload, plus tui.notification_method for the plainer in-terminal alert |
| Gemini CLI | general.enableNotifications toggle |
2 events: action required, session complete | OSC 9 escape sequence where supported, terminal bell everywhere else |
Claude Code trades a default for granularity: nothing fires until you
write the hook yourself.
Gemini CLI's two events are the only pair
documented behind a plain toggle.
Codex's single config key is the simplest of the three, and the
easiest to trust too much: it is silently ignored the moment it sits
in a project-local .codex/config.toml.
Three different defaults, three different failure modes, and not one of them was designed with a second session in mind.
The one built-in fleet feature that only fires if you're already watching
Two of Claude Code's eight matchers exist specifically for exactly
this problem. agent_needs_input fires when a background session
starts waiting on you, and agent_completed fires when one finishes
or fails. Read that as the feature built for a fleet.
Read the fine print next: both fire only while the agent view panel is already open. The one signal built for watching several agents so you do not have to babysit any of them only reaches you if you already have that exact screen open. The requirement is circular.
This is not a knock on one tool. It is what happens when a notification system gets designed one session at a time and is then asked, later, to cover a fleet.
Where AI coding agent notifications go wrong, and what they really cost
Wiring the wrong event trains you to ignore all of them. A Stop
hook fires whenever Claude finishes responding, not only at real task
completion, so a "task done" alert tied to it also fires on ordinary
back-and-forth. A few sessions of that and the sound stops meaning
anything.
Alert fatigue is permission-prompt fatigue, one layer up. Wire a notification to every permission prompt across several sessions and you start dismissing them on reflex, including the one guarding a command you have genuinely never approved before. Muting the channel afterward does not fix that: it just removes the one alert that would have mattered on the same afternoon, along with all the noise.
The delivery channel fails silently. osascript needs Script
Editor to hold notification permission on macOS or it fails without
telling you. notify-send needs a notification daemon that most
containers and SSH sessions do not have. You believe the net is there
until the one night it was not.
A shared config is not a shared notification. Codex's
project-local block on notify means the alert a lead commits for the
whole team to standardize on works on their machine in testing and
nowhere else, and nobody finds out until someone asks why they never
heard about a failed run.
Where "done" becomes a place, not an event you have to catch
Every fix above is still a notification, just a better-tuned one. There is a different move available: stop needing the alert to catch the state in the first place.
SanuDesk is a desktop app built around that. Your Claude Code, Codex and Gemini sessions tile into one grid, so which pane is waiting, which is mid-task, and which is genuinely stuck is something you glance at rather than something you need to be pinged about in time. Work arrives from a Kanban board: deploy a card and it opens a fresh session, and the moment the agent stops, the card parks itself in a review lane with a what-changed note. "Done" becomes a place on the board you check on your own schedule, not an event six different alert channels are all racing to tell you about first. Recurring unattended work becomes a Loop, journaled per run, so the job you would have needed a 2am alert for instead waits quietly in review by morning. It is bring-your-own-model, so it works the same way across engines that each solved notifications differently, and the grid and board are in the free plan (see pricing).
Tonight, count what your alerts are actually telling you
Pick the engine you run most and check what is wired to notify you right now: every permission prompt, every idle wait, or just the narrow set that genuinely needs a decision. Then, for one working session, mute everything except the single event that means a destructive command is waiting on approval.
If you do not miss the rest, you have just found how much of your setup was noise. If you do miss one, you now know the exact alert worth protecting, and everything else was competing with it for your attention the whole time.
Download SanuDesk free to see every session's state in one grid instead of a stream of alerts, or check how the grid, the board and Loops fit together on the features page.