Multiplexer interoperability: behavior matrix and contract tests - #204
Merged
Merged
Conversation
Research for #175: a behavior matrix for NMSh inside and around tmux and GNU screen, verified on tmux 3.7c and screen 4.00 in isolated sandboxes, with Zellij and TUIOS marked unverified. It covers rendering, resize propagation, job control, fullscreen passthrough, bracketed paste, mouse and key encodings, clipboard, and how multiplexer persistence and NMSh live sessions overlap: a closed pane detaches the live session, and a reattached session keeps the environment it was created in. Baseline coexistence needs no multiplexer detection. Prioritized follow-ups cover a reattach notice for environment changes, Shift+Enter under default tmux settings, Open all from inside a multiplexer, a Zellij pass, and recommended tmux settings. tests/muxInterop.test.ts pins the verified contract with real tmux and screen where installed and skips otherwise, plus host-detection cases for tmux, screen and Zellij environments.
The end-to-end status test typed /resume while 'sleep 30 &' was still finishing and NMSh correctly refused to switch transcripts mid-command. Wait for the command to complete first.
Each row of the multiplexer matrix now states its evidence: automated test, manual observation or expected. The test file is described as coverage for selected tmux/screen paths, not the whole contract. Tests added where they fit the existing harness: closing only the tmux pane (server still running) detaches the live session; NMSh inside GNU screen renders, sees STY, follows a resize and suspends a job; a program on the alternate screen gets the full terminal in passthrough; and the stale-environment test confirms the tmux server is gone. tmux runs with multiplexer variables stripped from the inherited environment, and the screen-inside-NMSh test quits its screen, which detaches rather than exiting when its terminal closes. Corrected: screen 4.00 keeps the window size it started with, so inside NMSh it keeps the composer-reduced height (new follow-up 6); it was wrongly described as corrected by SIGWINCH. vim, fg and less inside screen are marked as manual. Stale TMUX/TERM in a reattached shell is documented as affecting later child commands, while the attaching frontend's host detection uses its own environment.
This was referenced Sep 29, 2026
raiseCatError
added this pull request to stack #210
September 29, 2026 10:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #175
#175 is a research issue: "deliver a concise behavior matrix and prioritized implementation follow-ups … NMSh is not becoming a pane/window multiplexer; the outcome is reliable coexistence." This PR delivers that. No product behavior changes.
Deliverables
docs/architecture/multiplexer-interop.md: a behavior matrix for NMSh inside tmux and GNU screen and for each running inside NMSh, the persistence-overlap analysis, the detection decision, and prioritized follow-ups.tests/muxInterop.test.ts: pins the verified contract with real tmux and screen, skipping when they're not installed, so CI never depends on a multiplexer. Plus environment-only host-detection cases for tmux, screen and Zellij.Verified (tmux 3.7c, GNU screen 4.00, isolated sandboxes)
TERM=tmux-256color,TERM_PROGRAM=tmuxandTMUX;jobswork;lesspasses through and returns;paste-buffer -pstays a paste;lesswith its return all work.TERM=tmux-256color,TERM_PROGRAM=tmuxand a staleTMUX. This is the main interop wrinkle and is documented, not changed.Not verified (physical QA or follow-ups)
mouse on.tmux send-keyscan't produce real extended keys. NMSh decodes both extended encodings, but tmux's default settings likely deliver Enter./copyviapbcopyinside tmux.Detection
Baseline coexistence needs no multiplexer detection; nothing was added. #197's window launcher keeps its current behavior: inside tmux started from Ghostty, it detects Ghostty through the inherited
GHOSTTY_RESOURCES_DIR, so "Open all" opens Ghostty windows outside tmux. That's documented and tested, and follow-up 3 decides whether to change it.Prioritized follow-ups (in the doc)
extended-keys on(P1).Also
/resumebefore a background command's prompt had returned, and failed once under full-suite load. Test-only change.Tests
tests/muxInterop.test.tspassed 4/4 repeatedly, including alongsideliveHardeningandctrlZJobControl, with no tmux, screen or nmshd processes left behind.git diff --checkare clean. The full suite passed 595/595 locally.Review cleanup (bf51095)
STY, follows a resize and suspends a job;vimandfgunder tmux, andlessunder screen, are marked manual. StaleTMUX/TERMis documented as affecting later child commands, while the attaching frontend's host detection uses its own environment.fgthen Ctrl+C step). They'll be fixed in a stacked reliability PR. The rerun is green on Node 22 and 26.