Summary
psmux's argv parser does not correctly handle the standard Windows CommandLineToArgvW encoding for an argument whose value ends in a backslash and contains spaces. When such a value appears in tmux new-session -e KEY=VAL, all subsequent -e flags are swallowed into the first value's content.
This is independent of #264 (which we just filed for paste-buffer). Both surface only on Windows, both block the same downstream consumer (CAO).
Environment
- psmux: 3.3.4 (
psmux -V → psmux 3.3.4), installed via scoop
- Host: Windows 11 Pro 26200, ARM
- Caller: Python 3
subprocess.run(cmd_list, ...) — uses list2cmdline to encode argv per Microsoft's documented rules
Minimal repro
# Run from a non-psmux shell (e.g., Git Bash with PSMUX_SESSION unset)
python -c "
import subprocess
cmd = ['tmux', 'new-session', '-s', 'bsrepro', '-n', 'w', '-c', r'C:\Users\YOU', '-d',
'-e', r'TRAILING_BS=C:\Program Files\Foo Bar\plugins' + chr(92),
'-e', 'NEXT_VAR=should_survive',
'-e', 'CAO_TERMINAL_ID=test-id-12345']
subprocess.run(cmd)
"
tmux show-environment -t bsrepro
Observed
TRAILING_BS=C:\Program Files\Foo Bar\plugins" -e NEXT_VAR=should_survive -e CAO_TERMINAL_ID=test-id-12345
TRAILING_BS is set to the entire concatenation. NEXT_VAR and CAO_TERMINAL_ID are completely missing from the session env.
Expected
TRAILING_BS=C:\Program Files\Foo Bar\plugins\
NEXT_VAR=should_survive
CAO_TERMINAL_ID=test-id-12345
Real tmux on POSIX, and Windows tooling that uses CommandLineToArgvW, parse this correctly.
Why it's mis-parsed
Python's subprocess.list2cmdline correctly encodes MOZ_PLUGIN_PATH=...\plugins\ (value ending in \, value containing spaces) as:
"MOZ_PLUGIN_PATH=...\plugins\\"
Per Microsoft's argv parsing rules:
\\" → 1 literal backslash + close-quote (the \ is N backslashes where N=2; 2N/2 = 1 literal backslash; the " closes the string).
psmux's parser appears to treat \\" as if it were \" (i.e., escaped-quote-keep-going), so the string never closes and consumes the following -e NEXT_VAR=... and -e CAO_TERMINAL_ID=....
Trigger conditions
The bug fires when an env value:
- Contains whitespace (forces Python to wrap in quotes), AND
- Ends with
\.
On Windows this is common — MOZ_PLUGIN_PATH, some *_PATH vars, and various Program Files\…\ entries can end in trailing backslash.
Impact on CAO
CAO sets CAO_TERMINAL_ID last in the env dict. Any earlier env var matching the trigger silently swallows it, leaving the spawned agent without its terminal identifier — breaking assign/handoff MCP tools.
CAO-side workaround
We're stripping trailing backslashes from env values before passing as -e KEY=VAL (lossless for path-like vars: C:\Foo and C:\Foo\ are equivalent on Windows). Will remove once this is fixed in psmux.
Reference
Filed downstream of awslabs/cli-agent-orchestrator#207. See also #264 for paste-buffer (separate issue).
Summary
psmux's argv parser does not correctly handle the standard Windows
CommandLineToArgvWencoding for an argument whose value ends in a backslash and contains spaces. When such a value appears intmux new-session -e KEY=VAL, all subsequent-eflags are swallowed into the first value's content.This is independent of #264 (which we just filed for
paste-buffer). Both surface only on Windows, both block the same downstream consumer (CAO).Environment
psmux -V→psmux 3.3.4), installed via scoopsubprocess.run(cmd_list, ...)— useslist2cmdlineto encode argv per Microsoft's documented rulesMinimal repro
Observed
TRAILING_BSis set to the entire concatenation.NEXT_VARandCAO_TERMINAL_IDare completely missing from the session env.Expected
Real tmux on POSIX, and Windows tooling that uses
CommandLineToArgvW, parse this correctly.Why it's mis-parsed
Python's
subprocess.list2cmdlinecorrectly encodesMOZ_PLUGIN_PATH=...\plugins\(value ending in\, value containing spaces) as:Per Microsoft's argv parsing rules:
\\"→ 1 literal backslash + close-quote (the\is N backslashes where N=2;2N/2 = 1literal backslash; the"closes the string).psmux's parser appears to treat
\\"as if it were\"(i.e., escaped-quote-keep-going), so the string never closes and consumes the following-e NEXT_VAR=...and-e CAO_TERMINAL_ID=....Trigger conditions
The bug fires when an env value:
\.On Windows this is common —
MOZ_PLUGIN_PATH, some*_PATHvars, and variousProgram Files\…\entries can end in trailing backslash.Impact on CAO
CAO sets
CAO_TERMINAL_IDlast in the env dict. Any earlier env var matching the trigger silently swallows it, leaving the spawned agent without its terminal identifier — breakingassign/handoffMCP tools.CAO-side workaround
We're stripping trailing backslashes from env values before passing as
-e KEY=VAL(lossless for path-like vars:C:\FooandC:\Foo\are equivalent on Windows). Will remove once this is fixed in psmux.Reference
Filed downstream of awslabs/cli-agent-orchestrator#207. See also #264 for
paste-buffer(separate issue).