[BUG] `claude -p` / `claude --print` changes Claude Code product identity to Agent SDK identity
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 TUIrepl_main_thread request in the same state, then compare only the
identity-bearing fields:
- HTTP
User-Agent - first
systemtext block attribution (cc_entrypoint=...) - second
systemtext 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
-pbehavior are not the same product contract - frontend-facing flows are harder to reproduce manually
- evaluations using
-pmeasure SDK/headless behavior, not TUI Claude Code behavior - users cannot see the drift from stdout
Suspected code topology
The minified native bundle appears to:
- compute a combined non-interactive boolean from
-p,--init-only,
--sdk-url, and !process.stdout.isTTY
- pass that boolean into the entrypoint setter
- map true to
CLAUDE_CODE_ENTRYPOINT=sdk-cli - choose the SDK identity prompt when
isNonInteractiveis 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:
isNonInteractiveisSdkEntrypoint
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
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗