[BUG] Background agent sessions cannot copy to tmux buffer: TMUX is stripped when daemon spawns bg-pty-host
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Background agent sessions (claude bg-pty-host) cannot copy to the tmux paste buffer, even when the whole process chain is running inside tmux. Copy silently falls back to OSC 52. Interactive sessions in the same tmux server work fine and show "copied to tmux buffer".
The cause is that TMUX is removed from the environment when the daemon spawns bg-pty-host, while TMUX_TMPDIR is kept.
Clipboard selection is gated purely on process.env.TMUX:
function Pas(){ if (process.env.TMUX) return "tmux"; if (process.env.STY) return "screen"; return null }
function OYr(){ ... if (process.env.TMUX) return "tmux-buffer"; return "osc52" }
async function Qzg(e){
if (!process.env.TMUX) return false; // <-- gate
await run("tmux", ["load-buffer", "-w", "-"]); // primary
await run("tmux", ["load-buffer", "-"]); // fallback
}
But the underlying capability does not need TMUX. The tmux client resolves the server through TMUX_TMPDIR, which is inherited, so tmux load-buffer succeeds from a background session today. So the gate, not the mechanism, is what blocks it.
Where TMUX is dropped — process chain, with TMUX presence per process:
| process | TMUX | TMUX_TMPDIR |
|---|---|---|
| tmux ... new-session (server) | – | yes |
| -zsh (pane) | yes | yes |
| claude -c (interactive) | yes | yes |
| claude daemon run --origin transient | yes | yes |
| claude bg-pty-host ... | no | yes |
Every ancestor has it; only the last hop loses it, and only that one variable. That looks deliberate — a background job outlives the pane that started it, so pinning a TMUX value that can go stale is reasonable to avoid.
Why a stale value would indeed be worse — confirmed on tmux 3.4, if TMUX points at a dead socket the client tries that path and fails, whereas an absent TMUX falls back to TMUX_TMPDIR and succeeds:
TMUX=<current> tmux load-buffer -w - -> ok
TMUX=/nonexistent/sock,1,0 tmux load-buffer -w - -> error connecting to /nonexistent/sock
(unset) tmux load-buffer -w - -> ok
What Should Happen?
A background agent session running inside tmux should copy to the tmux paste buffer, same as an interactive session in the same tmux server, instead of silently falling back to OSC 52.
Suggested fix: widen the gate rather than propagating TMUX. Qzg() already has two levels of fallback, so attempting load-buffer when either variable is present costs nothing on failure:
if (!process.env.TMUX && !process.env.TMUX_TMPDIR) return false;
That keeps stale-socket safety (an absent TMUX is exactly the case that resolves correctly) and lets background sessions use the paste buffer. OYr()'s predicted-method string would want the same condition so the UI label matches what actually happens.
Error Messages/Logs
# No error is emitted — copy silently falls back to OSC 52.
# Demonstration that the capability is present in a background session:
$ echo $TMUX # empty
$ echo $TMUX_TMPDIR # ~/.tmux_tmp/<host>
$ printf 'x' | tmux load-buffer -w -b test - # exit 0
$ tmux list-buffers | head -1
test: 1 bytes: "x"
Steps to Reproduce
- Start a tmux server with a custom
TMUX_TMPDIRand open a pane. - In that pane, run
claude -c, then start a background agent session so the daemon spawnsclaude bg-pty-host. - In the background session, copy any text (the action that reports "copied to tmux buffer" in an interactive session).
- Observe the copy does not report "copied to tmux buffer" and the content does not appear in
tmux list-buffers; it falls back to OSC 52. - Compare with step 3 performed in the interactive session in the same tmux server — that one works.
Confirming the cause: inspect the environment of the bg-pty-host process (tr '\0' '\n' < /proc/<pid>/environ | grep TMUX). TMUX_TMPDIR is present, TMUX is absent; every ancestor process has both.
Workaround — have the agent write to the buffer explicitly, which works today:
tmux load-buffer -b claude <file>
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.227
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Xterm
Additional Information
TERM=xterm-256colorin the background session,tmux-256colorin the pane- Single tmux server, custom
TMUX_TMPDIR
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗