Skip to content

Input box filled with text on startup #6147

Closed as not planned
Closed as not planned

Description

@ocelot2123

Description

I am using Windows Powershell SSHing into Ubuntu Server 22.04.5. These texts are filled in the input box when running with opencode.
Sometimes it says other text, but I'm not able to reproduce that consistently.

Image

OpenCode version

1.0.2

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Windows 11 SSH into Ubuntu Server 22.04.5

Terminal

Windows PowerShell

Activity

  1. added
    opentuiThis relates to changes in v1.0, now that opencode uses opentui
    on Dec 25, 2025
  2. github-actions commented on Dec 25, 2025

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if none of these address your specific case.

  3. bbartels commented on Feb 5, 2026

    @bbartels
    Contributor

    Having the same issue, is there any workarounds?

  4. KyungmoKu commented on Feb 9, 2026

    @KyungmoKu

    Had the same issue - Windows Terminal SSH into Ubuntu.

    This worked for me: a small Python script that wraps opencode and filters out the garbage from stdin before it reaches the TUI.

    • Save below file as osc-filter (no .py) somewhere in your PATH, chmod +x osc-filter, then run osc-filter opencode instead of opencode.
    • You can alias it in your bashrc for convenience: alias oc='osc-filter opencode'

    The proper fix probably belongs in opentui's input parser - it doesn't handle OSC sequences at all right now.

    osc-filter
    #!/usr/bin/env python3
    """PTY wrapper that filters OSC escape sequences from stdin.
    
    Windows Terminal sends unsolicited OSC queries (10/11/4) over SSH.
    The TUI's input parser has no OSC response handler, so the responses
    appear as garbage text like "eeee/eeee/eeee" in the input field.
    
    This wrapper runs the child command in a real PTY and strips OSC
    sequences from stdin before forwarding them to the child.
    
    Usage:
        osc-filter opencode [args...]
    
    OSC sequence format:
        ESC ] ... BEL        (\x1b] ... \x07)
        ESC ] ... ESC \      (\x1b] ... \x1b\\)
    """
    
    import fcntl
    import os
    import pty
    import select
    import signal
    import sys
    import termios
    
    ESC = 0x1B
    BEL = 0x07
    BACKSLASH = ord("\\")
    
    # Stateful: tracks whether we're inside a partial OSC sequence that was
    # split across read() boundaries (e.g., SSH delivers the response in chunks).
    _in_osc = False
    
    
    def filter_osc(buf: bytes) -> bytes:
        """Remove OSC sequences from a byte buffer.
    
        Handles split reads: if an OSC sequence spans two read() calls,
        the second half is suppressed until the terminator is found.
        """
        global _in_osc
        out = bytearray()
        i = 0
        n = len(buf)
    
        # Continuing a partial OSC from the previous read
        if _in_osc:
            while i < n:
                if buf[i] == BEL:
                    i += 1
                    _in_osc = False
                    break
                if buf[i] == ESC and i + 1 < n and buf[i + 1] == BACKSLASH:
                    i += 2
                    _in_osc = False
                    break
                i += 1
            if _in_osc:
                return b""
    
        while i < n:
            if buf[i] == ESC and i + 1 < n and buf[i + 1] == ord("]"):
                i += 2
                while i < n:
                    if buf[i] == BEL:
                        i += 1
                        break
                    if buf[i] == ESC and i + 1 < n and buf[i + 1] == BACKSLASH:
                        i += 2
                        break
                    i += 1
                else:
                    _in_osc = True
            else:
                out.append(buf[i])
                i += 1
    
        return bytes(out)
    
    
    def copy_window_size(from_fd: int, to_fd: int) -> None:
        try:
            size = fcntl.ioctl(from_fd, termios.TIOCGWINSZ, b"\x00" * 8)
            fcntl.ioctl(to_fd, termios.TIOCSWINSZ, size)
        except OSError:
            pass
    
    
    def main() -> int:
        if len(sys.argv) < 2:
            print(f"Usage: {sys.argv[0]} <command> [args...]", file=sys.stderr)
            return 1
    
        if not os.isatty(sys.stdin.fileno()):
            os.execvp(sys.argv[1], sys.argv[1:])
    
        pid, master_fd = pty.fork()
    
        if pid == 0:
            os.execvp(sys.argv[1], sys.argv[1:])
    
        stdin_fd = sys.stdin.fileno()
        stdout_fd = sys.stdout.fileno()
    
        old_attrs = termios.tcgetattr(stdin_fd)
        try:
            new_attrs = termios.tcgetattr(stdin_fd)
            new_attrs[0] = 0
            new_attrs[1] = 0
            new_attrs[2] &= ~(termios.CSIZE | termios.PARENB)
            new_attrs[2] |= termios.CS8
            new_attrs[3] = 0
            new_attrs[6][termios.VMIN] = 1
            new_attrs[6][termios.VTIME] = 0
            termios.tcsetattr(stdin_fd, termios.TCSAFLUSH, new_attrs)
        except termios.error:
            pass
    
        copy_window_size(stdin_fd, master_fd)
    
        def handle_sigwinch(signum, frame):
            copy_window_size(stdin_fd, master_fd)
            try:
                os.kill(pid, signal.SIGWINCH)
            except OSError:
                pass
    
        signal.signal(signal.SIGWINCH, handle_sigwinch)
    
        try:
            while True:
                try:
                    rfds, _, _ = select.select([stdin_fd, master_fd], [], [])
                except InterruptedError:
                    continue
    
                if stdin_fd in rfds:
                    try:
                        data = os.read(stdin_fd, 4096)
                    except OSError:
                        break
                    if not data:
                        break
                    filtered = filter_osc(data)
                    if filtered:
                        try:
                            os.write(master_fd, filtered)
                        except OSError:
                            break
    
                if master_fd in rfds:
                    try:
                        data = os.read(master_fd, 4096)
                    except OSError:
                        break
                    if not data:
                        break
                    try:
                        os.write(stdout_fd, data)
                    except OSError:
                        break
        finally:
            try:
                termios.tcsetattr(stdin_fd, termios.TCSAFLUSH, old_attrs)
            except termios.error:
                pass
    
        _, status = os.waitpid(pid, 0)
        if os.WIFEXITED(status):
            return os.WEXITSTATUS(status)
        return 1
    
    
    if __name__ == "__main__":
        sys.exit(main())
  5. gbpdt commented on Feb 13, 2026

    @gbpdt
    Contributor

    Had the same issue - Windows Terminal SSH into Ubuntu.

    This worked for me: a small Python script that wraps opencode and filters out the garbage from stdin before it reaches the TUI.

    Thanks for posting this. I've given this workaround a try and it seems to work for me. I'd be very keen to see this integrated into the TUI code itself.

  6. llc1123 commented on Feb 14, 2026

    @llc1123

    It is fixed upstream. Waiting for a new release. PowerShell/openssh-portable#806

  7. haifengqiu commented on Mar 20, 2026

    @haifengqiu

    Additional Info

    Environment: WindTerm 2.0+ (latest), TERM=xterm-256color, UTF-8
    Confirmed issue: opencode TUI has compatibility problem with WindTerm.

    • ESC]66 and other ANSI escape sequences displayed as raw text
    • Other TUI apps (htop, nnn,) work perfectly with Chinese display in WindTerm
    • Windows built-in terminal SSH works fine with opencode
    • Only opencode is affected
      Workaround: Using tmux in WindTerm works around this issue:
    tmux new -s opencode
    opencode
  8. ocelot2123 commented on Apr 17, 2026

    @ocelot2123
    Author

    going to close this as I think its fixed somewhere upstream, maybe in anomalyco/opentui#770? maybe @kommander you can confirm

  9. kodewulf commented on Oct 31, 2026

    @kodewulf

    This same issue is now present in v2.2.5

  10. neriousy commented on Nov 12, 2026

    @neriousy
    Member

    Closing this old v1 report. If it still happens on v2, please open a new issue with your version.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingopentuiThis relates to changes in v1.0, now that opencode uses opentuiwindows

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions