Re-enter raw mode after piped input ends - #431
Open
anandghegde wants to merge 1 commit into
Open
anandghegde wants to merge 1 commit into
anandghegde wants to merge 1 commit into
Conversation
Programs like node save the terminal state at startup and restore it on exit. When their output is piped into fx, that restore can land after bubbletea has switched the terminal to raw mode, putting it back into canonical/echo mode: keys are echoed at the bottom of the screen and navigation stops working. The producer's output only reaches EOF once it has exited, so put the terminal back into raw mode when fx sees EOF. Fixes antonmedv#415
anandghegde
force-pushed
the
fix-raw-mode-after-piped-input
branch
from
September 15, 2026 16:57
b589884 to
ef62717
Compare
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.
Fixes #415
I could reproduce this on macOS with node 26:
node -e 'process.stdout.write(JSON.stringify({"a":1}))' | fxrenders, but keys get echoed at the bottom and nothing responds. It's a race, which is probably why it works on some machines.Cause: node saves the terminal settings (termios) when it starts and restores them when it exits (
ResetStdioin node). fx starts the TUI before node has exited, so bubbletea puts the terminal in raw mode, and then node's exit puts it back into canonical + echo mode.cat file | fxnever hits this because cat doesn't touch the terminal.The same thing happens with any producer that saves and restores terminal state. For example, this Python script breaks fx every time:
Fix: the producer's stdout only reaches EOF after the process has exited, so after the restore. On
eofMsg, fx now opens/dev/ttyand puts it back into raw mode (term.MakeRaw, the same call bubbletea uses). If the terminal is already raw this does nothing. On exit, bubbletea still restores the original state it saved, so the shell is left normal. If/dev/ttycan't be opened (e.g. on Windows), it's a no-op.Testing: I ran fx inside a pty from a small Python harness. The harness answers fx's OSC 11 and cursor-position queries, checks the tty's
ICANON/ECHOflags 2s after start, then sendsq:node -e ...qignored)qexitsecho '{"a":1}'stty -aafter fx exits showsicanon echo, so the terminal is restored properly.go test ./...passes, andGOOS=windows/GOOS=linuxbuilds succeed.This doesn't address the leaked
^[]11;rgb:...^[[48;1Rseen on Ubuntu. That's when node's exit lands during the startup background-color query.Implemented with Claude Code; I reviewed and tested the change.
🤖 Generated with Claude Code
https://claude.ai/code/session_01MA8JGs7pCoXFL2W6jEJ8sD