Blog · September 11, 2026 · 7 min read · by Vilva Athiban P B

Claude Code Notifications in tmux and Over SSH

Claude Code notifications are a solved problem right up until the moment your session stops running on the machine in front of you. Put it inside tmux, or run it over SSH on a beefy remote box, and the tidy little "done" alert quietly stops arriving. The work still finishes. Nobody tells you.

This is not a bug so much as a plumbing problem, and it is worth understanding rather than guessing at. A notification has to travel from the process that finished, through whatever terminal layers you have stacked up, to a notification centre that is capable of drawing a banner on a screen. Each layer in that chain can swallow it.

Why the chain breaks

Claude Code's built-in notifications ultimately depend on the terminal doing something visible. In the simplest case that is an ASCII bell character — \a — written to the terminal, which your terminal emulator turns into a sound, a bounce in the dock, or a system notification depending on its settings.

Insert tmux in the middle and the bell now arrives at tmux, not at your terminal emulator. Tmux has its own opinions about what to do with it, and by default those opinions are conservative: mark the window as having activity, and get on with life. Nothing reaches macOS.

Add SSH on top and you have a second, harder boundary. The process is running on a different computer. There is no notification centre on the other end that you can see, and there is no mechanism by which a remote process can reach across the network and draw on your laptop unless you build one.

Fixing it inside tmux

If Claude Code and your eyeballs are on the same machine and tmux is the only thing in between, this is straightforward. You need tmux to stop absorbing the bell and pass it through.

The relevant settings in your .tmux.conf are the visual and monitoring options. Setting set -g bell-action any makes tmux react to a bell in any window rather than only the current one, and set -g visual-bell off stops it from replacing the audible bell with a status-line flash that you will never notice. Reload with tmux source-file ~/.tmux.conf and test by running printf '\a' inside a pane.

If the bell now reaches your terminal emulator and still does nothing, the problem has moved one layer up: the emulator itself. Most terminals ship with the bell muted or set to "visual only", and each one calls the setting something different. Our guide to Claude Code's preferredNotifChannel setting covers which channel to pick per terminal, and it is worth setting explicitly rather than leaving on auto when tmux is involved — auto-detection gets confused by the extra layer.

Why the bell is a weak signal anyway

Here is the honest trade-off, and it is the reason a lot of people go round this loop twice. Even when you get the bell working perfectly through tmux, it is a poor notification. It fires once, leaves no record, and if you were in another room or had your headphones off, it is simply gone. There is nothing to come back to.

A bell also cannot distinguish between "the task is finished" and "Claude is asking whether it may run this command" — which are very different levels of urgency. If you routinely walk away from long runs, the difference matters, and we have written separately about getting notified when Claude Code is waiting for input.

The hook approach: notify from where the work happens

The more robust pattern is to stop relying on the terminal entirely and use Claude Code's hooks, which let you run an arbitrary command when certain events fire. Instead of emitting a bell and hoping, you run something that actively pushes a message.

On a local machine that can be as simple as calling a notification-sending command. Our guide to Claude Code hooks walks through the event names and the config shape, and the notification scripts post has working examples you can adapt.

The key advantage over the bell is that a hook runs a real program, and a real program can do things a control character cannot: include the project name, distinguish an error from a success, or send the alert somewhere that is not a terminal at all.

The SSH case: accept that the alert has to leave the machine

For remote sessions, there is no clever terminal setting that will save you. The process finished on a server. Your attention is somewhere else entirely. The only workable model is that the remote machine sends a message outward, over the network, to something you are actually looking at.

In practice that means a hook on the remote box that calls a push service, a chat webhook, or an email. People commonly reach for a Slack incoming webhook or a personal push-notification service, because both are a single HTTP request and neither requires anything installed on the receiving end.

Two things to get right. First, keep any tokens out of your shell history and out of the repo — an environment variable read from a file outside the project is the minimum. Second, make the message carry the hostname and the project directory. Once you have more than one remote session running, an alert that just says "done" is close to useless. Our post on getting Claude Code notifications on your phone goes further into the push options.

When to not bother with any of this

There is a case for leaving it alone. If your Claude Code runs typically take thirty seconds, notifications are pure noise — you will be alerted about something you were already watching. The setup only pays for itself when runs are long enough that you genuinely leave, which usually means multi-file refactors, test suites, or background tasks.

Equally, if you are running a single local session in a single terminal window, all of the above is over-engineering. Turn the terminal bell on, keep the window visible, and move on with your day. Complexity here should be proportional to how far away you actually walk.

A quick diagnostic order

When notifications stop arriving and you do not know which layer ate them, test from the inside out rather than changing five settings at once. Run printf '\a' in the pane to check the bell leaves the shell. Detach tmux and run the same thing in a plain terminal to see whether tmux is the culprit. Then check the emulator settings. Only after that should you suspect Claude Code's own configuration — in the large majority of cases the alert was generated fine and something downstream declined to show it.

And if the answer turns out to be "the process is on another continent", stop debugging the terminal. No amount of tmux configuration fixes physics; you need the message to travel.

Where to go next

If you run several sessions at once, the notification problem compounds quickly and the identifying detail in each alert becomes the whole game — our piece on running multiple Claude Code sessions covers keeping them straight. And for the general case, the full Claude Code notifications guide is the place to start.

Keep reading

Desk Exercises for Programmers: 15 Moves to Do While Your AI Agent Codes

7 min read

Exercise While Coding: Turn Claude Code Wait Time Into Micro-Workouts

7 min read

Claude Code Notch Notifications on Mac: See When Claude Is Done Without Watching the Terminal

7 min read

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 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

Claude Code Notifications Not Working: A Diagnostic Checklist

10 min read

Claude Code Notifications Inside Your Editor's Terminal

7 min read

CLAUDE_CODE_DISABLE_BACKGROUND_TASKS Explained

7 min read

CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP Explained

8 min read

Cursor Alerts Explained: Every Alert Cursor Raises, and How to Control Them

7 min read

Claude Code Environment Variables: The Groups That Actually Matter

10 min read

Claude Code Notifications on WSL and Windows

9 min read

Claude Code Checkpoints and /rewind

8 min read

Claude Remote Control: How It Works, Turning It Off, and Auto Mode

7 min read

Claude Code /loop: Poll a Deploy, Babysit a PR, and Get Told When It's Done

8 min read

Setting Up NotchFit With OpenAI Codex CLI: Hooks, $notchfit-plan, and the Daily Flow

7 min read

Claude Mods Explained: What the New Plugin Layer Can Do, and How to Turn On 'You Should Know'

9 min read

NotchFit vs Mac Break Reminder Apps: A Clock or a Signal From Your Coding Agent?

8 min read

Claude Code Headless Mode: Running claude -p in Scripts and CI, and the Three Signals That It Finished

10 min read

Building a Movement Habit at a Desk: Use the Agent Run as the Cue, One Set as the Unit, and Streaks Carefully

8 min read

Claude Code MCP Servers Explained: Adding Servers, Choosing a Scope, Handling Secrets, and Why Long Tool Calls Go to the Background

10 min read

/notchfit:plan Explained: How Claude Code or Codex Writes a Weekly Workout Plan the Notch Can Actually Run

8 min read

Claude Code Spinner Verbs Explained: What “Pondering” and “Brewing” Mean, How to Change Them, and Why You Should Stop Watching the Spinner

7 min read

Why NotchFit's Done and Permission Alerts Wait Until Your Set Ends, When That Costs You, and How to Turn the Workout Off

7 min read

How to Resume a Claude Code Session: --continue vs --resume, Naming Sessions, the Session Picker, Branching, and What Comes Back

9 min read

NotchFit on a Mac Without a Notch: How Pill Mode Works on Mac mini, iMac, Mac Studio and a MacBook With the Lid Closed

6 min read

How to Run a Claude Code Session in the Background: /background, claude --bg, Agent View, and Getting Back to It

9 min read

What a Notch App Can See: NotchFit's Local-First Design, What the Claude Code and Codex Hooks Send, and What Stays on Your Mac

7 min read

Why Codex CLI Asks for Permission Every Time, and How to Tune the Sandbox and Approval Policy Without Going Full Access

8 min read

What to Do While Claude Code or Codex Works: A Simple Protocol for the Two-to-Twenty-Minute Gap in Every Agent Run

7 min read

Is It Possible to Get a Notification When Claude Code or Codex Hits a Reset? Yes for Claude Code: the quota_auto_resume Hooks, Explained

8 min read

What a MacBook Notch App Can Actually Do: The Five Kinds of Notch Utility, Their Trade-offs, and Where NotchFit Fits

7 min read

How to Make MCP Servers Not Take Up as Much Context in Claude Code: Tool Search, alwaysLoad, Scopes and Output Caps

8 min read

The notchfit Command Line: Drive Your Workout, Read Status as JSON, Validate Plans and Test the Notch Without Leaving the Terminal

7 min read