[FEATURE] Support for Programmatic Input Submission in Interactive Mode

Status Open
Maintainer reply None cached
Activity 8 comments · opened Dec 28, 2025

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Feature Request: Support for Programmatic Input Submission in Interactive Mode

Summary

When using Claude Code in interactive mode within VS Code/Cursor terminals, programmatic input (sent via terminal.sendText() or sendSequence) cannot be submitted. The Enter key character (\r, \n, etc.) creates a newline instead of triggering submission.

Use Case

I'm building a voice-to-code system (speech-to-text → Claude Code) that needs to:

  1. Send transcribed text to an existing Claude Code terminal session
  2. Have it automatically submitted without manual user intervention
  3. Work with terminals running in the background (not necessarily the active terminal)

Problem Description

Claude Code uses the Ink library for terminal UI. Ink's ink-text-input component treats programmatic stdin input differently than physical keyboard input:

  • Physical Enter keypress → triggers onSubmit → prompt is processed
  • Programmatic \r or \n → treated as newline character → prompt is NOT submitted

This appears to be a fundamental limitation of how Ink handles raw mode and TTY detection.

What We Tried

VS Code Extension API approaches:

// Approach 1: terminal.sendText with newline
terminal.sendText(text, true);  // ❌ Creates newline, doesn't submit

// Approach 2: sendSequence with carriage return
vscode.commands.executeCommand('workbench.action.terminal.sendSequence', {
    text: text + '\r'  // ❌ Creates newline, doesn't submit
});

// Approach 3: sendSequence with line feed
vscode.commands.executeCommand('workbench.action.terminal.sendSequence', {
    text: text + '\n'  // ❌ Creates newline, doesn't submit
});

// Approach 4: Hex/Unicode variants
'\x0d', '\x0a', '\u000D', '\u000A'  // ❌ All create newlines

// Approach 5: Text first, then Enter separately with delay
terminal.sendText(text, false);
setTimeout(() => {
    vscode.commands.executeCommand('workbench.action.terminal.sendSequence', {
        text: '\r'
    });
}, 100);  // ❌ Still creates newline

// Approach 6: ESC + Enter (Option+Enter equivalent)
vscode.commands.executeCommand('workbench.action.terminal.sendSequence', {
    text: '\x1b\r'
});  // ❌ Doesn't work

macOS AppleScript approaches:

# Approach 7: AppleScript keystroke
osascript -e 'tell application "System Events" to keystroke return'
# ❌ Doesn't trigger submit

# Approach 8: AppleScript key code
osascript -e 'tell application "System Events" to key code 36'
# ❌ Doesn't trigger submit

Alternative CLI approaches:

# Approach 9: Headless mode (works but different use case)
claude -p "prompt"           # ✅ Works but exits after response
claude -p --continue "prompt" # ✅ Works but exits after response

The headless mode (-p) works for one-shot prompts but:

  • Exits after each response (not interactive)
  • Doesn't show in the same terminal as an active Claude Code session
  • Different workflow than typing into interactive mode

Suggested Solutions

Option 1: Accept programmatic Enter

Add a configuration option or environment variable that makes Claude Code accept programmatic \r/\n as submit triggers, even when stdin is not a "real" TTY.

Option 2: Special submission character/sequence

Define a special escape sequence (e.g., \x1b[SUBMIT] or similar) that triggers submission regardless of input source.

Option 3: Named pipe or socket for input

Provide an alternative input mechanism (like a Unix socket or named pipe) that accepts prompts and submits them to the active session.

Option 4: VS Code extension command

If there's a Claude Code VS Code extension, add a command like claude.submitPrompt(text) that can be invoked programmatically.

Environment

  • macOS Sonoma
  • Cursor IDE (VS Code fork)
  • Claude Code CLI (latest version)
  • Terminal: integrated VS Code terminal

Related Issues

This is likely related to how Ink handles process.stdin.isTTY and raw mode. Similar issues exist in other Ink-based CLI applications.

Impact

This limitation prevents building voice/accessibility tools, automation workflows, and IDE integrations that need to send prompts to Claude Code programmatically.

Thank you for considering this feature request!

Proposed Solution

Proposed Solution:

Ideally, Claude Code would accept stdin input submission from programmatic sources (like VS Code's terminal.sendText() API) the same way it accepts physical keyboard Enter keypresses.

User Experience:

User has Claude Code running in interactive mode in a VS Code/Cursor terminal
An external tool (voice-to-code, automation script, VS Code extension) sends text to the terminal using terminal.sendText("my prompt here", true)
Claude Code receives the text AND the trailing newline, recognizes it as a complete prompt submission, and processes it
The response appears in the same interactive session, maintaining conversation context
Specific Implementation Ideas:

Option A: Add an environment variable like CLAUDE_ACCEPT_STDIN_SUBMIT=true that makes Ink treat \r/\n from stdin as submit triggers
Option B: Add a CLI flag like claude --accept-stdin for interactive mode that enables programmatic input submission
Option C: Provide an IPC mechanism (Unix socket, named pipe) at a known path like /tmp/claude-code-{session-id}.sock that accepts prompts and injects them into the active session
This would enable voice-to-code workflows, accessibility tools, IDE integrations, and automation scripts to interact with Claude Code seamlessly.

Alternative Solutions

_No response_

Priority

Medium - Would be very helpful

Feature Category

CLI commands and flags

Use Case Example

i launch recording of my Speech to text, during the recording i press a keyboard combination like cld shift f13 meaning i want that stt result to be sent to claude code running on terminal 1 in cursor, once i press stop recording and the audio is processed and the text is pasted to clipboard it is detected by my app that polls my clipboard and my key command and sens it to a vscode extension that then sends it to this terminal (so far I have all this working) and it actually SUBMITS it automatically. Meaning the text appears but it is not submitted ie pressing enter)

Additional Context

_No response_

View original on GitHub ↗

8 Comments

aaronS7 · 7 months ago

@ColinusM I actually stumble upon this when trying to implement something like this in claude code. Still early work in progress, but I (or claude code) got it working by having a tmux session send keys to claude code.
The "tmux send-keys" is what worked for me
https://man7.org/linux/man-pages/man1/tmux.1.html

nbonamy · 7 months ago

@ColinusM did you find a workaround?

@aaronS7 what key did you send exactly? tried some options but none work

aaronS7 · 7 months ago

@nbonamy I was able to have it type in a message and press enter. I didn't do anything super crazy with other special characters

mbailey · 6 months ago

Have you tried VoiceMode (700 ⭐ )? It provides natural two way voice conversations with Claude Code, making screen and keyboard optional.

WTHfloyd · 6 months ago

+1 -- We run a multi-agent bridge system with 8+ Claude Code sessions coordinating via a shared file. tmux-backed sessions get auto-delivery via keystroke injection, but VS Code panel sessions have no programmatic input path. This feature would make panel sessions first-class citizens for inter-agent communication.

hrmtz · 6 months ago

Workaround for tmux send-keys: Escape before Enter

We operate a 10-agent multi-agent system where Claude Code sessions run in tmux panes and communicate via file-based mailboxes. A supervisor daemon (inotifywait) detects inbox file changes and wakes agents by sending short nudge messages (e.g., inbox3) through tmux send-keys.

We hit this exact issue: tmux send-keys ... Enter gets intercepted by Claude Code's autocomplete/prompt suggestions, so the text appears in the input field but is never submitted. The agent never wakes up.

Reliable workaround

After extensive debugging, we found that sending Escape (to dismiss autocomplete) before Enter (to submit) works reliably:

# ❌ Broken — Enter gets swallowed by autocomplete
tmux send-keys -t "$pane" "inbox3" Enter

# ✅ Working — Escape dismisses autocomplete, then Enter submits
tmux send-keys -t "$pane" "inbox3"
sleep 0.3
tmux send-keys -t "$pane" Escape
sleep 0.1
tmux send-keys -t "$pane" Enter

The 0.3s delay between text and Escape is necessary — without it, the Escape sometimes arrives before autocomplete has engaged, and Enter still gets intercepted.

Scale of the problem

In our system, this pattern is used dozens of times per hour across 10 agents for:

  • Wake-up nudges (inbox3)
  • /clear session resets
  • /model sonnet and /model opus model switches

Each of these requires the Escape+Enter workaround. We've wrapped all send-keys operations in shell functions to enforce this pattern, but it adds ~0.4s latency to every programmatic interaction.

Feature request

Any of these would solve our problem:

  1. --no-autocomplete CLI flag — disable autocomplete entirely (ideal for automated/headless-ish sessions)
  2. CLAUDE_CODE_DISABLE_AUTOCOMPLETE=true env var — same, but via environment
  3. Fix the Enter key routing — programmatic Enter from tmux send-keys should be treated as submission, not autocomplete acceptance

The existing CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false setting does not resolve this issue.

Happy to provide more details about our multi-agent architecture if helpful. Thanks for the great tool!

hrmtz · 6 months ago

Additional note: /model and /clear commands also affected

Just to clarify — this issue affects not just regular text input but also Claude Code's built-in slash commands sent via tmux send-keys:

# These all get intercepted by autocomplete:
tmux send-keys -t "$pane" "/clear" Enter       # ❌ /clear never executes
tmux send-keys -t "$pane" "/model sonnet" Enter # ❌ model switch never happens

The same Escape workaround is required:

tmux send-keys -t "$pane" "/clear"
sleep 0.3
tmux send-keys -t "$pane" Escape
sleep 0.1
tmux send-keys -t "$pane" Enter

In our multi-agent system, /clear is used to reset agent sessions when they become unresponsive, and /model switches are used to temporarily upgrade agents to more capable models for complex tasks. Both are critical operations that fail silently without the workaround — the command text sits in the input field looking like it was submitted, but nothing happens.

ivooQ · 5 months ago

There is a workaround from my side, which is pretty similar as hrmtz's.

    terminal.sendText("\x1b[200~" + prompt + "\x1b[201~", false);
    await new Promise((resolve) => setTimeout(resolve, 2000));
    terminal.sendText("", true);
  1. Used the prefix and suffix so the terminal treats the entire block as pasted content and won't interpret special chars like \n as Enter. This issue only appears when you have long (>2k words based on my test) prompt.
  2. The waiting time need to increase when the prompt is very long.
  3. Send empty line to submit the prompt.