Skip to content

fix(tui): prevent piped stdin from breaking UI and keyboard input#34242

Open
LordMikkel wants to merge 3 commits into
anomalyco:devfrom
LordMikkel:fix/tui-stdin-pipe-v2
Open

fix(tui): prevent piped stdin from breaking UI and keyboard input#34242
LordMikkel wants to merge 3 commits into
anomalyco:devfrom
LordMikkel:fix/tui-stdin-pipe-v2

Conversation

@LordMikkel

@LordMikkel LordMikkel commented Jun 27, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #28538
Closes #24195
Closes #3871
Closes #6220

Replaces #28540, which was closed by the automated PR cleanup bot before maintainer review.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

When stdin is piped, the TUI renderer can read keyboard input from the pipe instead of the terminal. That breaks the UI and keyboard control for a simple command like:

echo "hello" | opencode

The run command already handles this with resolveInteractiveStdin(). This PR applies the same approach to the TUI: pass the controlling terminal (/dev/tty on Linux, CONIN$ on Windows) to the renderer while still consuming piped stdin as the prompt.

How did you verify your code works?

  • bun --cwd packages/opencode test runtime.stdin
  • bun --cwd packages/opencode typecheck
  • Manual case to validate in a real terminal: echo "hello" | opencode

Screenshots / recordings

With the fix:

image image

Without the fix:

Image image

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Jun 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@andrei-hasna

Copy link
Copy Markdown

Local merge/validation note from review queue:

Validated locally against current dev (ae53163):

  • PR head 571459c merges cleanly with no conflicts.
  • packages/opencode typecheck passes.
  • packages/tui typecheck passes.
  • packages/opencode test/cli/run/runtime.stdin.test.ts passes.
  • packages/tui test/app-lifecycle.test.tsx passes.
  • Changed-file oxlint exits 0, with existing warnings outside the added lines.

I would not merge this yet. Remaining blockers found in review:

  1. The resolved interactive stdin is passed to the TUI renderer, but TUI openEditor() call sites still omit it. External editor launches therefore inherit the original pipe/EOF after flows like echo prompt | opencode, so editor-based prompt/session export workflows can still have broken stdin.
  2. The Windows CONIN$ path needs another pass: Ctrl+C guard, processed-input disable, and input-buffer flush still operate on process.stdin, not the resolved renderer stdin.
  3. The no-controlling-terminal error currently reuses --mini requires a controlling terminal for input, which is misleading for the non-mini TUI path.

Also, the branch is currently stale relative to dev (1 ahead / 9 behind); GitHub reports mergeStateStatus=BLOCKED even though the content is MERGEABLE locally.

@andrei-hasna

Copy link
Copy Markdown

Revalidated by the merge queue on 2026-06-28 against current dev (61a7f6d) and PR head 571459c.

What passed:

  • PR still applies cleanly locally; git merge-tree origin/dev refs/remotes/pr/34242 succeeds.
  • git diff --check origin/dev...refs/remotes/pr/34242 passes.
  • bun --cwd packages/opencode test --timeout 30000 test/cli/run/runtime.stdin.test.ts test/cli/tui/thread.test.ts passes.
  • bun run --cwd packages/opencode typecheck passes.
  • bun run --cwd packages/tui typecheck passes.
  • Changed-file oxlint has 0 errors; warnings are on pre-existing lines.

Still not merging yet. The blockers from the previous review comment still apply because the head commit has not changed:

  1. TUI external editor call sites still omit the resolved stdin, so editor workflows can inherit the original pipe/EOF.
  2. Windows processed-input/flush/Ctrl+C guard paths still key off process.stdin, not the resolved interactive stdin stream.
  3. The no-controlling-terminal error text is still mini-specific for the standard TUI path.
  4. GitHub reports mergeStateStatus=BLOCKED; the branch is now 1 ahead / 11 behind current dev.

Please address those before this is merge-ready.

@andrei-hasna

Copy link
Copy Markdown

Revalidated by the merge queue on 2026-06-28 against current dev (dfeb1b505) and PR head 571459c.

What passed locally in an isolated worktree:

  • PR merges cleanly into current dev with no conflicts.
  • git diff --check passes.
  • bun --cwd packages/opencode test --timeout 30000 test/cli/run/runtime.stdin.test.ts test/cli/tui/thread.test.ts passes.
  • bun --cwd packages/tui test --timeout 30000 test/app-lifecycle.test.tsx passes.
  • bun run --cwd packages/opencode typecheck passes.
  • bun run --cwd packages/tui typecheck passes.
  • Changed-file oxlint has 0 errors; warnings are on pre-existing lines.

Still not merging. Independent review confirmed the remaining blockers:

  1. The resolved interactive stdin is only passed to the OpenTUI renderer. TUI openEditor() call sites still omit it, so editor launches can inherit the original piped stdin/EOF after flows like echo prompt | opencode.
  2. Windows terminal handling still keys off process.stdin: Ctrl+C guard, processed-input disable, and input-buffer flush do not use the resolved CONIN$ stream passed to the renderer.
  3. The no-controlling-terminal error text still says --mini requires a controlling terminal for input, which is misleading for the standard TUI path now using the same resolver.
  4. GitHub still reports mergeStateStatus=BLOCKED; branch divergence is 12 1 (dev ahead / PR ahead).

Please address those before this is merge-ready.

@andrei-hasna

Copy link
Copy Markdown

Revalidated by the merge queue on 2026-06-28 against current dev (6ee817d) and PR head 571459c.

What passed locally in an isolated worktree:

  • PR merges cleanly into current dev with no conflicts.
  • git diff --check passes.
  • bun --cwd packages/opencode test --timeout 30000 test/cli/run/runtime.stdin.test.ts test/cli/tui/thread.test.ts passes (13/13).
  • bun --cwd packages/tui test --timeout 30000 test/app-lifecycle.test.tsx passes (2/2; same pre-existing KV ENOENT logs).
  • bun run --cwd packages/opencode typecheck passes.
  • bun run --cwd packages/tui typecheck passes.
  • Changed-file oxlint reports 0 errors; warnings are on pre-existing lines.

Still not merging. Independent adversarial review confirmed the remaining blockers:

  1. TUI external editor call sites still omit the resolved interactive stdin, so editor workflows can inherit the original piped stdin/EOF after flows like echo prompt | opencode.
  2. Windows terminal handling still keys off process.stdin: Ctrl+C guard, processed-input disable, and input-buffer flush do not use the resolved CONIN$ stream.
  3. The no-controlling-terminal error text still says --mini requires a controlling terminal for input, which is misleading for the standard TUI path.
  4. GitHub still reports mergeStateStatus=BLOCKED; branch divergence is 13 behind / 1 ahead current dev.

Please address those before this is merge-ready.

@LordMikkel

LordMikkel commented Jun 28, 2026

Copy link
Copy Markdown
Author

@andrei-hasna Thanks for the thorough review!

I addressed the blockers:

  • Passed the resolved stdin to TUI editor calls.
  • Updated Windows terminal handling to use the resolved stdin.
  • Fixed the TUI controlling-terminal error message.
  • Updated the branch against current dev.

Your detailed feedback was really valuable!

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

Labels

None yet

Projects

None yet

2 participants