[BUG] `claude -p` / `claude --print` changes Claude Code product identity to Agent SDK identity

Resolved 💬 1 comment Opened May 14, 2026 by oxysoft Closed Jun 12, 2026

Parent tracking issue: https://github.com/anthropics/claude-code/issues/59105

Context note: This is a frontend/product-boundary parity issue, not a criticism
of any individual implementation. Since -p / --print behavior is already a
known pain point, and upcoming mid-June frontend-facing changes may depend on
predictable CLI/TUI parity, this should be evaluated as a user-facing parity
risk. The goal is to reduce verification time and avoid customer-facing
regressions with potential business impact.

Summary

claude -p should be a non-interactive output surface for Claude Code. In
Claude Code 2.1.141, it instead changes the product identity sent to the model
from Claude Code CLI to Agent SDK.

This is a frontend/backend boundary collapse: an output-mode decision changes
backend request identity.

Observed

For the same prompt and model:

| Field | claude -p | TUI |
| --- | --- | --- |
| User-Agent | claude-cli/2.1.141 (external, sdk-cli) | claude-cli/2.1.141 (external, cli) |
| request attribution | cc_entrypoint=sdk-cli | cc_entrypoint=cli |
| identity prompt | You are a Claude agent, built on Anthropic's Claude Agent SDK. | You are Claude Code, Anthropic's official CLI for Claude. |

Attempting to force the environment does not help:

CLAUDE_CODE_ENTRYPOINT=cli claude -p "TRACE_PROMPT_ALPHA" ...

Still produces:

claude-cli/2.1.141 (external, sdk-cli)

Also, omitting -p but running with stdout not attached to a TTY follows the
same sdk-cli path.

Rediscovery track

Capture one claude -p / claude --print request and one TUI
repl_main_thread request in the same state, then compare only the
identity-bearing fields:

  • HTTP User-Agent
  • first system text block attribution (cc_entrypoint=...)
  • second system text block identity prompt

For minified builds, search stable literals rather than local names:
CLAUDE_CODE_ENTRYPOINT, sdk-cli, --print, process.stdout.isTTY, and the
two identity prompt strings. The structural path is CLI/stdout classification
to entrypoint serialization to user-agent/attribution to identity prompt
selection.

Why this matters

The identity prompt is not cosmetic. It tells the model what product it is, what
behavioral frame applies, and what user expectations it should satisfy.

For users this breaks parity:

  • TUI behavior and -p behavior are not the same product contract
  • frontend-facing flows are harder to reproduce manually
  • evaluations using -p measure SDK/headless behavior, not TUI Claude Code behavior
  • users cannot see the drift from stdout

Suspected code topology

The minified native bundle appears to:

  1. compute a combined non-interactive boolean from -p, --init-only,

--sdk-url, and !process.stdout.isTTY

  1. pass that boolean into the entrypoint setter
  2. map true to CLAUDE_CODE_ENTRYPOINT=sdk-cli
  3. choose the SDK identity prompt when isNonInteractive is true

That makes isNonInteractive do too much.

Expected

claude -p should be:

  • non-interactive: yes
  • SDK entrypoint: no
  • Claude Code CLI identity: yes

Actual SDK entrypoints should still use SDK identity.

Suggested fix

Separate:

  • isNonInteractive
  • isSdkEntrypoint

Use isSdkEntrypoint for:

  • CLAUDE_CODE_ENTRYPOINT=sdk-cli
  • SDK identity prompt
  • SDK user-agent attribution
  • SDK-only tool/agent filters

Use isNonInteractive for:

  • suppressing TUI rendering
  • output formatting
  • prompt input transport
  • non-interactive setup behavior

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗