Skip to content

fix(cmd): respect SetStdin/SetStdout/SetStderr for tea.Exec compatibility - #522

Open
puneet-chandna wants to merge 2 commits into
charmbracelet:mainfrom
puneet-chandna:main
Open

fix(cmd): respect SetStdin/SetStdout/SetStderr for tea.Exec compatibility#522
puneet-chandna wants to merge 2 commits into
charmbracelet:mainfrom
puneet-chandna:main

Conversation

@puneet-chandna

Copy link
Copy Markdown

This PR fixes issue #506 where Bubble Tea programs running under Wish's bubbletea.Middleware with ssh.AllocatePty() would not properly release the alternate screen when executing child processes via tea.Exec.

Problem

When using tea.Exec with wish.Command, the child process output appeared "stacked" below the TUI instead of replacing it. This happened because wish.Cmd's SetStdin, [SetStdout](cci:1: wish/cmd.go:76:0-79:1), and SetStderr methods were no-ops, causing Bubble Tea's alt screen escape sequences to be written to a different output path than the child process.

Solution

Modified wish.Cmd to properly store and use the I/O handles set by Bubble Tea's exec flow:

  • Added stdin, stdout, stderr fields to [Cmd](cci:2 /wish/cmd.go:31:0-37:1) struct
  • Implemented [SetStdin](cci:1 /wish/cmd.go:71:0-74:1), [SetStdout](cci: wish/cmd.go:76:0-79:1), SetStderr to store values
  • Updated [doRun()](cci: wish/cmd_unix.go:7:0-34:1) to use custom I/O when set, falling back to PTY otherwise

Changes

  • [cmd.go](cci:7: /wish/cmd.go:0:0-0:0) - Added stdio fields and implemented Set* methods
  • [cmd_unix.go](cci:7: wish/cmd_unix.go:0:0-0:0) - Use custom I/O when any handle is set
  • cmd_windows.go - Use custom I/O when ALL handles are set (no ppty.Slave on Windows)
  • [cmd_test.go](cci:7: wish/cmd_test.go:0:0-0:0) - Added [TestCommandSetStdio](cci:1: wish/cmd_test.go:100:0-138:1) to verify the fix

Testing

  • All existing tests pass
  • Added new test [TestCommandSetStdio](cci:1: wish/cmd_test.go:100:0-138:1) that verifies custom I/O handles are used

Before/After

Before: Child process output appears below TUI frame; scrollback shows "stacked" output
After: Child process replaces TUI cleanly; alt screen properly exits/enters around exec

Fixes #506

…lity

Previously, wish.Cmd's Set* methods were no-ops, causing alt screen
escape sequences to be out of sync with child process output when
using tea.Exec with bubbletea.Middleware.

Now wish.Cmd stores and uses custom I/O handles when set by tea.Exec,
ensuring proper sequencing of alt screen commands.

Fixes charmbracelet#506
@puneet-chandna
puneet-chandna requested a review from a team as a code owner December 16, 2025 12:42
@puneet-chandna
puneet-chandna requested review from aymanbagabas and kujtimiihoxha and removed request for a team December 16, 2025 12:42
@codecov

codecov Bot commented Dec 16, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.75%. Comparing base (ee243c6) to head (ee33d17).
⚠️ Report is 264 commits behind head on main.

❗ There is a different number of reports uploaded between BASE (ee243c6) and HEAD (ee33d17). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (ee243c6) HEAD (ee33d17)
2 1
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #522      +/-   ##
==========================================
- Coverage   77.23%   68.75%   -8.49%     
==========================================
  Files          19       22       +3     
  Lines         940      976      +36     
==========================================
- Hits          726      671      -55     
- Misses        160      250      +90     
- Partials       54       55       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aymanbagabas aymanbagabas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, this looks good! Could you look at our x/xpty library and use it to spawn the process instead?

- Use xpty.WaitProcess on Windows for proper ConPTY waiting
- Implement SetStdin/SetStdout/SetStderr to store and use custom I/O
- Require all stdio to be set for custom path (avoids PTY deadlocks)

Fixes charmbracelet#506
@puneet-chandna

Copy link
Copy Markdown
Author

@aymanbagabas Thanks for the suggestion! I’ve updated the implementation to use the x/xpty library for spawning the process. Please let me know if this matches what you had in mind.

@puneet-chandna

Copy link
Copy Markdown
Author

Hi! Just a gentle follow-up on this PR. I’ve addressed the requested changes (switched process spawning to x/xpty) and CI is passing. Whenever you have time, I’d appreciate a re-review. Thanks!

@aymanbagabas
aymanbagabas requested a review from caarlos0 January 13, 2026 22:01

@aymanbagabas aymanbagabas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Could you back port this to the v2-exp branch in a separate PR?

@puneet-chandna

Copy link
Copy Markdown
Author

I’ve opened a backport PR targeting the v2-exp branch with the same changes. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wish Bubble Tea middleware: ExecProcess/PTY can’t replace TUI (alt screen re-enters automatically)

2 participants