← Blog

Blog

Claude Code on tmux: How to Manage Sessions Across Panes

Harjas Singh

5 min readclaude-codetmuxterminalworkflowmulti-session

If you live in tmux, you already know the trade. You get a dense, keyboard-driven workspace where four panes of Claude Code can run side by side without alt-tab. You give up the operating system's notification graph: macOS doesn't know what each pane is doing. tmux does, but tmux can't tell macOS.

For most processes, that's fine. npm run build doesn't need anyone's attention. Claude Code is different. Claude Code stops and waits for you, sometimes many times an hour. And inside tmux, "waiting for you" means "invisible until you happen to look at that pane."

This post is about what actually breaks when you put Claude Code in tmux at scale, and what Claude Pulse does about it.

Why notifications break down inside tmux

The obvious answer to "Claude wants approval" is a notification. That works fine for one or two sessions in their own terminal windows. In tmux, it falls apart for three reasons.

1. The terminal emulator is one process. macOS sees Ghostty, iTerm2, or Terminal.app as a single app. When Claude pauses in pane 3 of window 2 of session work, the OS doesn't know that. A notification can say "Claude Code is waiting" but not which pane. You still have to find it.

2. tmux multiplexes stdin. When Claude wants approval, it expects a keystroke on its own pane's stdin. A notification you click on doesn't magically route a y to the right pane. You have to manually focus the pane and type. If you batch-approve everything from a single notification, you've guessed which pane needed it.

3. PID lookup is the only reliable identity. tmux doesn't expose a stable session-to-pane mapping that's reachable by another app without an explicit hook. The process ID of the Claude Code session is the one thing both tmux and macOS can agree on.

What Claude Pulse does differently

Claude Pulse hooks into Claude Code itself, not into tmux. The hook fires inside the Claude Code process when it pauses for approval, and Claude Pulse captures the PID at that moment. From the PID, we can ask tmux: which pane is this process running in?

That gives us two useful capabilities. When you approve from the notch, Claude Pulse sends the keystroke directly to the right pane via tmux's send-keys interface. No focus dance. The approval lands in the exact pane that asked, even if you're looking at a different one.

When you want to jump in, Claude Pulse uses the same PID-to-pane lookup to switch the active pane in your tmux session. One keystroke, you're there.

The working-directory fallback

PID lookup works for most cases but not all. If you run Claude Code through a wrapper script, or you suspend it with Ctrl-Z and resume in a different pane, the PID changes. Claude Pulse falls back to working directory matching: it asks tmux which pane has its working directory set to where Claude is running.

This won't catch every edge case — two Claude sessions in the same project will have the same working directory. When that happens Claude Pulse surfaces both candidates and asks you. We'd rather ask than guess wrong on a destructive operation.

A practical workflow

Here's how I personally run Claude Code inside tmux on a typical day. Three windows in one tmux session called work:

  • Window 1: four panes, four Claude Code sessions, each on a different feature.
  • Window 2: my editor (Helix in one pane, references in another).
  • Window 3: a long-lived gh pr status and git log view.

Without Claude Pulse, this is unsustainable. I lose track of which Claude needs what; I batch-approve and occasionally approve a git push --force I didn't mean to. With Claude Pulse, the notch shows me a single row per session, each with a breathing status dot. When one needs approval, that dot changes colour. I look up at the notch — not into the tmux pane — see the tool, the input preview, and the safety classification, and approve or jump in.

I don't alt-tab. I don't switch panes. I read the notch the way I read a watch face.

What we deliberately do not do

We do not run a separate tmux server. We do not require a plugin or a config change to your ~/.tmux.conf. We do not parse pane content. We do not require you to launch Claude Code through a wrapper. None of those are robust strategies; all of them fail when you ssh, attach, or move panes around.

The only thing Claude Pulse needs is the Claude Code hook socket on your local filesystem and the ability to ask tmux for its pane list. Both work whether tmux is brand-new today or has six attached clients across two ssh sessions.

A note on remote tmux

If you tmux-attach to a session running on a remote box, Claude Pulse can't see those Claude sessions. The hook socket lives on the host where Claude is actually running. We'd need to bridge it over ssh, which we haven't built. For local tmux — including the tmux new -s work pattern most people use on their MacBook — it just works.

Try it

Download Claude Pulse and start your existing Claude Code sessions inside tmux. No configuration. The notch will pick them up within a second.

If you want to read more about how the safety model works — why batch-approve excludes rm -rf — see the hidden cost of missed approvals.

Try Claude Pulse

Manage Claude Code sessions from your MacBook notch. Free.

Download for macOS
Written by Harjas Singh · @claudepulse