fix(tmux): keep browser keys from switching a tab onto another session (#669)

Squash of PR #669. Browser terminals could be moved onto another session
by tmux's prefix keys: Ctrl+B then ), (, s or w switched the tab's tmux
client to a different session while the tab kept the original's name.
Codeman's tmux socket now keeps only Ctrl+B Ctrl+B (send-prefix) in its
prefix table, and codeman tui and scripts/tmux-manager.sh get F1 as their
way out instead of Ctrl+B d.

Merge-time fixes by the maintainer: on an empty prefix table the
unbind-key that fails no longer skips binding send-prefix; a key tmux lists
escaped (prefix C-\ shows as C-\\) compares equal, so the reset does not rerun on every create;
and reconcileSessions() reduces the table at boot when the socket has live
sessions, so sessions that survive an upgrade are covered too.

Co-authored-by: christianhaberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
authored and Codeman maintainer committed 2026-10-22 19:23:17 +02:00
1 parent 620e7728ec
commit 6eaaa960ff
14 files changed
+775 -28

No files matched your search

+10
View File
@@ -125,6 +125,7 @@ import {
import { EXEC_TIMEOUT_MS } from './config/exec-timeout.js';
import { ensureDeepSeekStatusShim } from './deepseek-status-shim.js';
import { restrictTmuxPrefixTable } from './tmux-prefix-table.js';
/** How long a cached process snapshot stays usable. */
const PROC_SNAPSHOT_TTL_MS = 2000;
@@ -2491,6 +2492,10 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer {
/* Non-critical */
}
// Browser keystrokes reach the attach client, so tmux's stock prefix table would
// let Ctrl+B ( or s move a tab onto another session. Before the agent starts.
restrictTmuxPrefixTable(this.tmux());
// Per-CLI env: API keys, config blobs, config-sourced vars, status bridges. All of
// it is registry data, so this is one unconditional call rather than a per-mode ladder.
this._configureCliEnv(
@@ -3176,6 +3181,11 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer {
active = new Map();
}
// Sessions that survived an upgrade may sit on a server whose prefix table was never
// reduced (createSession does it for new ones), so cover them at boot too. Only with
// panes listed: on an empty socket `list-keys` spins up a throwaway server instead.
if (active.size > 0) restrictTmuxPrefixTable(this.tmux());
// Check tracked sessions against the live pane list.
for (const [sessionId, session] of this.sessions) {
const pid = active.get(session.muxName);