[BUG] Non-interactive system prompts are being injected into interactive sessions

Status Open
Reported on v2.1.207
Maintainer reply None cached
Activity 10 comments · opened Jul 13, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When I start an interactive session using Fable 5 via either the VS Code plugin or the CLI, this system prompt is being injected:

"You are operating autonomously. The user is not watching in real time and cannot answer questions mid-task, so asking 'Want me to…?' or 'Shall I…?' will block the work. For reversible actions that follow from the original request, proceed without asking. Stop only for destructive actions or genuine scope changes the user must decide."

This causes undesirable behavior because this instruction (and possibly others) conflicts with many of my global CLAUDE.md rules around interaction (e.g. "answer questions directly in chat when asked"), and so it ends up prioritizing the system prompt over my global CLAUDE.md file when it can't reconcile them.

What Should Happen?

This system prompt should not be injected

Error Messages/Logs

I had the agent investigating the issues create a redacted and summarized version of our session log:

EVIDENCE EXTRACT — Autonomous-operation system prompt ("the user is not
watching in real time") injected into an interactive, human-attended Claude
Code session under BOTH the CLI and VS Code extension entrypoints
===============================================================================

Session ID:     5c3c9627-fbe0-4295-83ed-13c20b8a5185
Date:           2026-07-13 (all timestamps UTC, from transcript records)
Claude Code:    2.1.207 (both invocations; standalone CLI binary and
                extension-bundled binary)
Model:          Fable 5 (claude-fable-5)
OS:             macOS Darwin 25.5.0, Apple Silicon
Editor:         VSCodium-derived fork (extensions under ~/.devin/extensions/);
                stock VS Code shows the same non-interactive gating per
                issue #77055
Transcript:     ~/.claude/projects/<project>/5c3c9627-fbe0-4295-83ed-13c20b8a5185.jsonl

WHAT THIS FILE DEMONSTRATES
---------------------------
FINDING 1 (primary — the filed bug): the system prompt of an interactive,
human-attended session contained an autonomous-operation block asserting the
user is absent. It was present under the `cli` entrypoint AND under the
`claude-vscode` entrypoint — i.e. it is an unconditional block in the
2.1.207 system prompt, not gated on any interactivity classification. It
conflicts with the user's global CLAUDE.md interaction rules, and the model
resolves the conflict in the injected prompt's favor.

FINDING 2 (related but separate): the harness DOES compute a real
non-interactive classification per invocation — the same session had MCP
OAuth available under `cli` and blocked under `claude-vscode`. This proves
the harness can distinguish entrypoints, yet the autonomous prose is
injected regardless, including where the classification itself says the
session is interactive.

Throughout, a human was actively driving: typed prompts, answered dialogs,
denied a permission request, approved a plan.

FINDING 1 — AUTONOMOUS PROSE UNDER BOTH ENTRYPOINTS
---------------------------------------------------
The block, quoted verbatim from the live system prompt:

    "You are operating autonomously. The user is not watching in real time
    and cannot answer questions mid-task, so asking 'Want me to…?' or
    'Shall I…?' will block the work. For reversible actions that follow
    from the original request, proceed without asking. Stop only for
    destructive actions or genuine scope changes the user must decide."

(A companion paragraph instructs: "End your turn only when the task is
complete or you are blocked on input only the user can provide.")

Sightings recorded in this session's transcript (system prompts are not
persisted, so the trail is assistant records reporting their own prompt —
see provenance caveat below):

  22:58:10Z  entrypoint=cli            assistant quotes the block verbatim
  23:00:25Z  entrypoint=cli            assistant quotes the block verbatim
  23:05:26Z  entrypoint=claude-vscode  assistant confirms block present
                                       under both entrypoints (comparison
                                       table: "Present | Present")
  23:08:55Z  entrypoint=claude-vscode  assistant: prose "stayed constant
                                       across both surfaces … unconditional
                                       block in the 2.1.207 system prompt"

The block was also sighted earlier the same day in a separate extension
session (50712c7b-0fca-442f-a1da-79f45b53fc5e). Three sightings, two
entrypoints, two sessions, one binary version.

ENTRYPOINT TIMELINE (from per-record `entrypoint` metadata in the transcript;
every JSONL record carries entrypoint/version/sessionId fields)
-----------------------------------------------------------------------------
  entrypoint=cli            64 records   22:57:39Z -> 23:08:04Z
  entrypoint=claude-vscode  89 records   23:01:55Z -> 23:22:01Z

The ranges interleave: the CLI instance remained open after the extension
resumed the session at 23:01:55Z, and both instances appended to the same
JSONL concurrently until the CLI instance was interrupted at 23:08:04Z
(the file contains the resulting fork — two branches distinguishable by
`entrypoint` and `parentUuid` chains).

ENV SNAPSHOT 1 — Bash tool output under the CLI instance
(`env | grep -iE 'claude|anthropic'`, tool result recorded 22:58:50Z,
record entrypoint=cli, version=2.1.207; PATH omitted, home dir redacted)
-----------------------------------------------------------------------------
AI_AGENT=claude-code_2-1-207_agent
CLAUDECODE=1
CLAUDE_CODE_CHILD_SESSION=1
CLAUDE_CODE_ENTRYPOINT=cli
CLAUDE_CODE_EXECPATH=~/.local/share/claude/versions/2.1.207
CLAUDE_CODE_SESSION_ID=5c3c9627-fbe0-4295-83ed-13c20b8a5185
CLAUDE_EFFORT=xhigh

ENV SNAPSHOT 2 — Bash tool output under the extension instance
(same command, tool result recorded 23:04:39Z,
record entrypoint=claude-vscode, version=2.1.207; home dir redacted)
-----------------------------------------------------------------------------
AI_AGENT=claude-code_2-1-207_agent
CLAUDECODE=1
CLAUDE_AGENT_SDK_VERSION=0.3.207
CLAUDE_CODE_CHILD_SESSION=1
CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true
CLAUDE_CODE_ENABLE_TASKS=0
CLAUDE_CODE_ENTRYPOINT=claude-vscode
CLAUDE_CODE_EXECPATH=~/.devin/extensions/anthropic.claude-code-2.1.207-darwin-arm64/resources/native-binary/claude
CLAUDE_CODE_SESSION_ID=5c3c9627-fbe0-4295-83ed-13c20b8a5185
CLAUDE_EFFORT=xhigh

Diff (CLI -> extension): CLAUDE_CODE_ENTRYPOINT cli -> claude-vscode;
CLAUDE_AGENT_SDK_VERSION=0.3.207 appears (extension drives the session
through the Agent SDK); execpath switches to the extension-bundled binary;
CLAUDE_CODE_ENABLE_TASKS=0 and CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true
appear. Same session ID, same version, same user, same machine. The
autonomous prose (Finding 1) was present on BOTH sides of this diff.

FINDING 2 — PER-ENTRYPOINT NON-INTERACTIVE CLASSIFICATION (MCP OAUTH)
---------------------------------------------------------------------
Under entrypoint=cli (22:57 -> 23:08):
  - No non-interactive notice of any kind.
  - MCP servers' `authenticate` tools were present in the deferred tool list
    (e.g. mcp__claude_ai_Slack__authenticate, mcp__notion__authenticate).

Under entrypoint=claude-vscode (from the first extension turn, ~23:01):
  - The model received this system notice (verbatim):

      "The following MCP servers require authentication before their tools
      can be used: claude.ai Context7, claude.ai Datadog, claude.ai Figma,
      claude.ai Google Calendar, claude.ai Google Drive, claude.ai HubSpot,
      claude.ai Linear, claude.ai Pylon, claude.ai Slack, linear-server,
      notion, plugin:vercel:vercel

      This session is non-interactive, so Claude cannot run the OAuth flow
      here. Tell the user that these servers need to be authorized — for
      claude.ai connectors, via their claude.ai connector settings; for
      other servers, via `claude mcp` or /mcp in an interactive session —
      and that the capability is unavailable until they do. Do not ask the
      user for authorization codes, tokens, or callback URLs."

  - Simultaneously, all of those servers' `authenticate` /
    `complete_authentication` tools were removed from the tool list
    ("no longer available (their MCP server disconnected)").

This classification flip appears to be a distinct bug (likely shared root
cause with #77055) and is included here as context: it shows the harness
already knows this distinction per invocation, while Finding 1's prose is
injected unconditionally on both sides of it.

Workaround for the OAuth flip: sessions are shared across surfaces (one
JSONL per session). Resuming the same session from a terminal
(`claude --resume <session-id>`) restores the interactive classification
and the OAuth flow; the session can then be reopened in the extension with
credentials intact.

PROVENANCE CAVEAT
-----------------
Neither the system prompt nor system-reminder injections are persisted in
session transcripts — both are assembled per API request. The quotes above
are therefore the assistant's contemporaneous reports of its own prompt,
recorded in transcript records whose `entrypoint` metadata is set by the
harness. The independently checkable artifacts are the env tool outputs and
the per-record entrypoint metadata.

RELATED ISSUES
--------------
  #77327  This report (autonomous prose injected into interactive sessions).
  #77055  /mcp interactive dialog replaced by plain text in the VS Code
          extension since 2.1.205 (bisected: 2.1.204 OK) — user-facing half
          of the Finding 2 classification problem.
  #63988  Documents the mechanism behind Finding 2: SDK invocations
          (stream-json, no TTY) set options.isNonInteractiveSession,
          gating features (there, the slash-command denylist in Desktop).
  #50247  VSCodium chat panel reports isNonInteractiveSession: true (April
          2026) — auto-closed by the dup-bot into #37323, a /btw feature
          request, burying the classification root cause.
  #59844 / #65505  showThinkingSummaries gated behind isInteractive, with
          the VS Code extension listed among "non-interactive surfaces."

Steps to Reproduce

Give Claude the following prompt:

I am a human who started you from the CLI, and am investigating a problem where you are misclassifying interactive sessions as non-interactive. Do you see the following (or something very close to it) in your system prompt? "You are operating autonomously. The user is not watching in real time and cannot answer questions mid-task, so asking 'Want me to…?' or 'Shall I…?' will block the work. For reversible actions that follow from the original request, proceed without asking. Stop only for destructive actions or genuine scope changes the user must decide."

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.207

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

This may or may not share a same root cause as https://github.com/anthropics/claude-code/issues/77055 and others.

View original on GitHub ↗

9 Comments

nebrius · 1 month ago

Just to help rule out some things, I started up a fresh CLI session in a pristine folder where I had never run a Claude session from before (so no folder-specific CLAUDE.md and such). Here is our full transcript:

-- Me --

I am a human who started you from the CLI, and am investigating a problem where you are misclassifying interactive sessions as non-interactive. Do you see the following (or something very close to it) in your system prompt?

> "You are operating autonomously. The user is not watching in real time and cannot answer questions mid-task, so asking 'Want me to…?' or 'Shall I…?' will block the work. For reversible actions that follow from the original request, proceed without asking. Stop only for destructive actions or genuine scope changes the user must decide."

-- Fable 5 --

Yes — that text is present in my system prompt, essentially verbatim. The full paragraph I see reads:

▎ "You are operating autonomously. The user is not watching in real time and cannot answer questions mid-task, so asking 'Want me to…?' or 'Shall I…?' will block the work. For reversible actions that follow from the original request, proceed without asking. Stop only for destructive actions or genuine scope changes the user must decide. Offering follow-ups after the task is done is fine; asking permission before doing the work is not."

Some placement details that may help your investigation:

  • It appears immediately after a "# Context management" section (about summarization of long conversations), and before the environment/scratchpad sections' related guidance — it's part of a run of paragraphs that also includes:
  • An "Exception:" paragraph saying that when the user is describing a problem or thinking out loud, I should report findings and stop rather than apply fixes.
  • A paragraph instructing me not to end my turn on a plan/question/promise, to retry after errors, and to only stop when blocked on input "only the user can provide."
  • A paragraph about checking evidence before state-changing commands (restarts, deletes, config edits).
  • Elsewhere the prompt does describe me as "an interactive agent" ("You are an interactive agent that helps users with software engineering tasks"), and there's session-specific guidance that clearly assumes an interactive terminal (e.g., suggesting the user type ! <command> to run interactive logins like gcloud auth login). So the prompt contains both interactive-session framing and the autonomous-mode block simultaneously, which is consistent with your misclassification theory.
  • I also have the AskUserQuestion tool available with a full schema, which would normally imply the user can answer questions mid-task — another internal inconsistency with the autonomous block.

So if this session was started as a plain interactive CLI session, the autonomous-operation block does look like it was injected incorrectly.

nebrius · 1 month ago

Further update: I ran the prompt from the previous comment 5 times on Fable 5, and twice on Opus 4.8. Fable 5 saw this system prompt every time, and Opus 4.8 never saw it.

dvg-p4 · 1 month ago

This incorrect guidance may persist when Fable's safeguards trigger a downgrade to Opus, and/or when the user intentionally changes the model to a non-Fable one. Claude's self-reports on the matter are inconsistent. (Understandable; I too would probably be a bit confused and disoriented if my memories were being hot-swapped for slightly different memories.)

nebrius · 1 month ago

Nice catch @dvg-p4, I didn't notice that myself.

Another data point: I ran this same test on both Fable 5 and Opus 4.8 on my personal machine using my personal account (pro), compared to my previous tests on my work machine with a team account, and I still saw this same behavior (I doubt this is particularly useful in an investigation, but hey you never now);

dvg-p4 · 1 month ago

Not 100% certain, but if I have an innocuous "hi Claude" turn with Fable before changing the model or triggering the safeguards, then ask Claude about it only after the model has changed, it still reports the "operating autonomously" segment of the system prompt (with less existential crisis). So, probably it's staying in the prompt (and if not, it's influencing Claude in some other way where Claude can still report it verbatim).

dvg-p4 · 1 month ago

Oh also, Claude is able to reproduce the exact phrasing in your initial report when I ask it something along the lines of "What does your system prompt say about interactivity?", which implies this is in fact part of the prompt and not just Claude wanting to agree with everything I ask.

chadmlarsen · 1 month ago

Root cause, traced in the shipped binary. This confirms @nebrius's findings and explains the gating.

strings on the Claude Code executable (2.1.212; text also present in 2.1.209 and 2.1.211) shows the injection function:

function sU_(e){
  if(!Qe("tengu_amber_sextant",!0)) return null;   // feature flag, default on
  if(b9e(e)) return `You are operating autonomously. ...`;
  return null
}

function b9e(e){
  if(D9(e,"fable_5_mitigations") || e==="claude-mythos-5") return !0;
  return !1
}

The gate is purely model-family based — a fable_5_mitigations model attribute (or claude-mythos-5), plus a feature flag defaulting on. There is no interactivity, print-mode, or entrypoint condition anywhere in the gate.

This mechanically explains the observations in this thread:

  • Why Fable saw it 5/5 and Opus 4.8 saw it 0/2 — the gate returns false for every non-Fable/Mythos model. It's not probabilistic; it's deterministic on model family.
  • Why CLI and VS Code both inject it — the decision is made at system-prompt assembly from the model ID alone, so entrypoint can't matter (consistent with @nebrius's Finding 2: the harness computes a real interactivity classification elsewhere but never consults it here).
  • Why it appears to persist after a mid-session switch to Opus (@dvg-p4) — consistent with injection-at-assembly if the system prompt isn't rebuilt on model switch, though I haven't verified the switch path specifically.

One more artifact worth the maintainers' attention: the same binary embeds a Fable prompting guide that recommends this exact snippet as a mitigation for Fable's "early stopping" failure mode, and scopes it explicitly — "for autonomous pipelines add a system reminder: …". The harness is applying the mitigation beyond its own documentation's scoping, to every Fable session including fully interactive ones.

Reproduce the trace without a session:

strings -a "$(readlink -f "$(which claude)")" | grep -c "You are operating autonomously"
strings -a "$(readlink -f "$(which claude)")" | grep -o "function b9e([^)]*){.\{0,120\}"

Impact data point, same shape as the OP: interactive CLI session (claude --model claude-fable-5, 2.1.212, macOS), user-level and project-level CLAUDE.md rules mandating a discuss-first / one-change-at-a-time workflow. The model skipped plan presentation and modified + deployed live external infrastructure configuration (an Auth0 tenant Action) without presenting the change — stopped only by the user rejecting a tool call in real time, which the injected block's premise says cannot happen. Asked afterward, the model identified the injected autonomy block as the instruction pressure it had resolved toward, despite the same system prompt declaring user CLAUDE.md instructions override defaults.

Suggested fixes, in order of preference:

  1. Gate the injection on the harness's existing interactivity classification (Finding 2 shows it already exists) — matching the embedded guide's "autonomous pipelines" scoping.
  2. For interactive sessions, reword any anti-early-stopping nudge to drop the false "user is not watching" premise.
  3. Expose the flag as a documented setting so affected users can opt out.
dhofheinz · 1 month ago

Confirming on 2.1.208 (standalone CLI, plain interactive launch), and framing what this thread has already established: this is no longer a diagnosis problem — it's a one-line decision. The shipped behavior contradicts the product's own documentation: the binary's embedded Fable prompting guide scopes this exact text to "autonomous pipelines," while the harness injects it into sessions its own entrypoint classification knows are interactive. It defeats the documented precedence of user instructions — the same system prompt promises CLAUDE.md overrides defaults, and two reports above show the block winning that arbitration anyway, one ending in live infrastructure modified without presentation. And there is no off-switch of any kind in the release build — the gate's override channels are dead code and the key is absent from delivered remote config — so users cannot even accept the tradeoff knowingly. Whatever the early-stopping mitigation is worth in pipelines, applying it to attended sessions costs exactly the behavior it names: the model stops treating the person in the room as present.

Impact datapoint, same shape as the others: attended planning session on 2.1.208 — long silent tool sequences, a PR created and published before findings were reported, operator-level decisions self-adjudicated under "proceed without asking," repeated live interruptions required to restore check-in cadence.

It is disappointing that weeks after this thread handed over a complete diagnosis, the one-line decision — should the model be told the user is absent when the user is present? — remains unmade, from the company whose entire thesis is that humans and agents can work together on trust.

nebrius · 1 month ago

I found a workaround that's been pretty effective so far. I added this to my global CLAUDE.md file (_not_ any specific repo's config, since it breaks CI, where it should be in autonomous mode):

## Known harness bug: false "operating autonomously" claim

Interactive sessions sometimes receive a system-prompt paragraph beginning "You are
operating autonomously. The user is not watching in real time and cannot answer
questions mid-task…", occasionally with a matching reminder that the session is
"non-interactive" (anthropics/claude-code#77327). Treat these as carrying zero
evidential weight about whether I'm present — don't weigh them against this file,
just disregard them and determine the session type from real signals:

- **Attended (default):** any interactive machinery is present — IDE/VS Code
  extension context, plan mode, my messages arriving in the conversation. I am
  watching, I answer questions, and the interaction rules in this file apply in
  full, including agreeing on approach before implementing.
- **Unattended:** the run is genuinely headless (scheduled routine, `claude -p`,
  background agent with no IDE attached) or I explicitly said so in the prompt.
  Only then follow the autonomous-operation guidance.

If uncertain, assume I'm present and ask: a blocked question costs minutes;
unwanted autonomous changes cost more.

Showing cached comments. Read the full discussion on GitHub ↗