Skip to content

[enhancement] Encode the interactive-CLI protocol in a high-intent terminal_send_message tool (text + Enter + settle + confirm) instead of leaving send_keys/Enter to the model #482

Description

@serge-ivo

Summary

The terminal / tmux Operator connector exposes two low-level write tools and makes the model choose correctly between them and remember to submit:

  • tmux_run_command / terminal_run_command — types text and presses Enter (for shell/git/build lines).
  • tmux_send_keys / terminal_send_keys — types text without Enter unless the model passes keys:["Enter"] (for answering an interactive prompt, sending Escape/C-c/arrows).

Driving an interactive CLI like Claude Code needs "type this message, then Enter, into the CLI's input box." Today that maps to send_keys plus a correctly-remembered keys:["Enter"], sent into a pane the model must independently know is ready. That's a footgun, and it misfired in production (see #481): the message was sent into a not-ready pane and dropped.

Best-practice framing

Encode the correct protocol in the tool, not in the model's judgment. Add a high-intent tool — the tmux/terminal analogue of the Coder path's send_to_cli (workers/api/src/lib/storage-tools.ts:231-237) — that does the right thing atomically:

terminal_send_message (write) — "Send a message to the interactive CLI running in this pane and submit it."

  1. Verify/await the pane is at an input prompt (readiness gate from [bug] Terminal/tmux Operator writes are fire-and-forget — no readiness gate, no landed-confirmation; the first message to an interactive CLI is silently dropped #481).
  2. sendText(text) then sendKey("Enter").
  3. Settle + confirm the pane changed (landed-confirmation from [bug] Terminal/tmux Operator writes are fire-and-forget — no readiness gate, no landed-confirmation; the first message to an interactive CLI is silently dropped #481).
  4. Return the grounded result: landed + post-settle pane, or an explicit "did not land, resend."

Keep send_keys for genuine key-level control (Escape, C-c, arrows, multi-key sequences) — it stays the escape hatch. send_message becomes the default, hard-to-misuse path for "tell the CLI to do X."

Optionally expose a thin terminal_wait (read scope) that polls capture until the pane quiesces or a pattern appears — the reusable "wait for ready" the Coder path has (coding-loop.ts:179-183 waitIdle) but the connector lacks. send_message uses it internally; the model can also call it explicitly.

Depends on

Acceptance criteria

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    connectorsConnector + tool frameworkenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions