github / github/copilot-cli

Interactive TUI ignores all keyboard input written to its PTY (only Ctrl+C responds), breaking automation/orchestration tooling

Ouverte
#4,180 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

area:input-keyboard
Langage dominant
Shell
Étoiles
11.2k
Forks
1.9k
Merge moyen
14 h 16 min
PR mergées (30 j)
6

Description

Describe the bug

When copilot runs its interactive TUI inside a programmatically-driven PTY (agent orchestrators, tmux send-keys, expect, pty.fork()), the TUI ignores every keystroke written to the PTY. Printable characters, /, Tab, arrow keys, Ctrl+L and Enter all produce no reaction: the ❯ composer stays empty and nothing is submitted.

The only key that does work is Ctrl+C, which cleanly tears down the alt-screen and exits — so the process is reading stdin, but the composer's key handling never sees the events.

Typing by hand in a regular terminal works fine. Non-interactive mode (copilot -p "...") also works fine. Only the automated interactive path is broken.

Affected version

GitHub Copilot CLI 1.0.70. (TUI banner reports v1.0.71)

Steps to reproduce the behavior

Minimal, dependency-free repro (Python stdlib only):

repro.py

import os, pty, time, select, fcntl, termios, struct, signal

pid, fd = pty.fork()
if pid == 0:
os.environ["TERM"] = "xterm-256color"
os.execvp("copilot", ["copilot"])

fcntl.ioctl(fd, termios.TIOCSWINSZ, struct.pack("HHHH", 40, 120, 0, 0))

def pump(t):
b = b""; end = time.time() + t
while time.time() < end:
r, _, _ = select.select([fd], [], [], 0.2)
if r:
try: b += os.read(fd, 65536)
except OSError: return b
return b

pump(10) # let the TUI boot

for name, seq in [("text", b"hola prueba"), ("enter", b"\r"),
("slash", b"/"), ("tab", b"\t"),
("arrow", b"\x1b[C"), ("ctrl-l", b"\x0c")]:
os.write(fd, seq)
print(f"{name:8s} -> {len(pump(2))} bytes of output")

os.write(fd, b"\x03") # Ctrl+C
print(f"ctrl-c -> {len(pump(3))} bytes of output")

Output:

text -> 0 bytes of output
enter -> 0 bytes of output
slash -> 0 bytes of output
tab -> 0 bytes of output
arrow -> 0 bytes of output
ctrl-l -> 0 bytes of output
ctrl-c -> 102 bytes of output <-- teardown sequences, process exits

Expected behavior

Bytes written to the PTY should be handled exactly as if typed: printable characters appear in the composer, Enter submits the prompt. This is what every other agent TUI I drive the same way does (Codex, for example, accepts the identical injected input).

Additional context
  • OS: macOS (Darwin 25.5.0), arm64
  • Node: v22.17.1 (installed via nvm), @github/copilot npm install
  • Shell: zsh

Things I ruled out:

  • Not a raw-mode problem. While the TUI is up, the PTY's termios is correctly in raw mode: ICANON=False, ECHO=False, ISIG=False, VMIN=1. Since ISIG is off, the working Ctrl+C must be handled by the application itself — confirming the read loop is alive.
  • Not a capability-negotiation deadlock. Copilot emits a kitty-keyboard query (CSI ? u), a theme query, alt-screen, bracketed paste (?2004h), mouse tracking and focus reporting (?1004h). Answering them (CSI ?0u, CSI ?997;1n, CSI ?62;1;6c) does not unblock input.
  • Not a focus problem. Sending focus-in (CSI I) after ?1004h changes nothing.
  • Not a paste-detection problem. Wrapping input in bracketed paste (ESC[200~…ESC[201~) changes nothing.
  • Not a "typed too fast" problem. Writing one byte at a time with 250 ms between characters changes nothing.
  • Not terminal-emulator specific. Same failure through a real terminal emulator (an Orca-managed pane) as through a bare pty.fork(). In the emulator case the injected string is even rendered appended to the footer line rather than into the ❯ composer, and Enter still submits nothing.
  • Not an injection-tooling problem. The identical injection path drives a plain shell and another agent's TUI correctly.

Debug log (copilot --log-level debug --log-dir ./logs) shows no input-related error at all. The only entries at the moment of the write are:

[INFO] Unregistering foreground session: d13a790d-…
[DEBUG] Broadcasting session lifecycle event: session.background for session d13a790d-…
[INFO] Registering foreground session: d13a790d-…
[DEBUG] Broadcasting session lifecycle event: session.foreground for session d13a790d-…

Impact: this makes the interactive TUI unusable from any agent-orchestration or automation harness. Current workaround is the non-interactive -p/--prompt mode, which loses the multi-turn session.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par exécuter repro.py, sans dépendances, sur le point d’entrée interactif de copilot et comparez les entrées PTY automatisées aux entrées manuelles du terminal. Suivez ensuite la gestion de stdin et des événements clavier du TUI, puis vérifiez que les touches imprimables, Tab, les flèches, Ctrl+L et Enter parviennent au composer, tandis que Ctrl+C quitte toujours proprement.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
node.js, python, shell
Domaine
cli
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Calme
Clarté
Plutôt claire
Accessibilité débutants
38/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.