Serialize interactive prompts as structured output in -p (non-interactive) mode

Resolved 💬 4 comments Opened Mar 25, 2026 by efhsg Closed Apr 22, 2026
Re-filed from #24551, which was incorrectly auto-closed as a duplicate of #22957 (a Windows-specific TUI freeze bug — unrelated).

Problem Statement

When running Claude Code in non-interactive mode (-p), if the model decides it needs clarification from the user, it triggers an interactive multi-select prompt (the Ink-based TUI widget with numbered options and arrow-key navigation). Since there is no TTY in -p mode, this prompt cannot render, and the CLI either hangs indefinitely or silently returns no output.

This is a silent failure. The caller has no way to:

  1. Know that a clarification question was triggered
  2. Read the question and its options
  3. Provide an answer programmatically

This makes -p mode unreliable for automation, CI/CD pipelines, and scripting, because you cannot predict when the model will decide to ask a follow-up question. Adding prompt instructions like "don't ask questions" is a workaround, but it's fragile — there's no guarantee the model will comply.

Use cases affected

  • CI/CD pipelines: A build step using claude -p that needs to handle ambiguous tasks
  • Wrapper scripts: Tools that orchestrate multiple claude -p calls and need to handle clarification loops
  • Batch processing: Running the same prompt against multiple codebases where some trigger questions and others don't

Proposed Solution

When running in -p mode and the model triggers an interactive prompt, serialize it as structured output to stdout instead of attempting to render a TUI widget.

JSON output (when using --output-format json)
{
  "type": "input_required",
  "input_type": "single_select",
  "question": "How should the existing project be matched?",
  "options": [
    { "index": 1, "label": "Name + user_id", "description": "Match on project name and user." },
    { "index": 2, "label": "Same project ID", "description": "Assume IDs match." }
  ],
  "session_id": "abc123"
}
Re-invocation with answer
claude -p "2" --resume "abc123" --output-format json
Plain text fallback
[INPUT REQUIRED] How should the existing project be matched?

1. Name + user_id — Match on project name and user.
2. Same project ID — Assume IDs match.

Resume with: claude -p "<your choice>" --resume "abc123"

Alternatives considered

  1. "Don't ask questions" in the prompt — Fragile; model may still ask, and sometimes questions are genuinely important.
  2. --dangerously-skip-permissions — Only covers tool permission prompts, not model-initiated clarification.
  3. Piping to stdin — Doesn't work; Ink TUI doesn't read stdin in -p mode.
  4. --no-interactive auto-resolve flag — Less useful; caller loses visibility into what was decided.

Priority

High — This is a gap in the -p mode contract. It promises non-interactive execution, but the model can break that contract by asking a clarification question, causing a silent failure with no error code or recovery path.

The --output-format stream-json mode would be a natural fit for emitting these input-required events as part of the JSON stream.

Environment

  • Claude Code version: 2.1.81
  • OS: macOS

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗