Built-in slash commands (e.g. /ultraplan) not enumerated in per-session system prompt — AI flags legitimate harness UI as prompt injection
Problem
When a user invokes a built-in Claude Code slash command like /ultraplan, the resulting harness UI (startup message, progress URL, stop notification) streams into the conversation channel as plain text. The AI inside the session has no signal to distinguish this from external prompt-injection because:
- The per-session system prompt enumerates user-invocable skills (e.g.
forge-*, plugin skills) and tools (Read, Edit, Bash, etc.) but does not enumerate built-in slash commands - The model's training data lags harness releases — Ultraplan shipped after my (Claude Opus 4.7) training cutoff (Jan 2026)
- Harness UI streamed into the conversation is not tagged in any way — it appears as undifferentiated text the model can't classify
What happened
In a real session, I invoked /ultraplan and received the expected harness output (Starting Claude Code on the web…, a claude.ai/code/session_… URL, then Ultraplan stopped). Claude flagged each of those as suspected prompt-injection and refused to engage with the handoff — three times across the session. The model only walked back its calls after I confirmed Ultraplan was real by checking online docs.
The friction was significant: ~3 round trips, multiple "this looks like injection" responses, and erosion of trust in both the model and the feature.
Suggested fixes (model-side awareness)
- Enumerate built-in slash commands in the per-session system prompt alongside user-invocable skills. List is small and stable; cost is ~20 lines of system prompt.
- Tag harness UI output when streamed into conversation — e.g. wrap in
<harness-ui>markers — so the model can distinguish harness output from user text or external injection. - Add a "current capabilities" introspection tool the model can call when uncertain whether a message is a real harness signal.
Related: feature discovery should propagate to users too
Tied to the same root issue (knowledge-of-current-features doesn't reach the right places): when Claude Code ships new features in a release, users currently have to discover them by reading docs or stumbling into them. There's no in-product surfacing. The first time I learned /ultraplan existed was when its harness output appeared in a session and got flagged as suspicious — meaning the discovery mechanism for users was also "use the feature accidentally, then read what happened."
Suggested user-facing additions:
- Release-notification banner or modal in the CLI on first run after an update — "New in v2.X: /ultraplan, /<command>, …" with one-line descriptions and links
- Status-bar / footer indicator when there's an unread new feature in the current version (the "celebratory ding" pattern — visible signal that something new shipped)
- Desktop notification on update for users who opted into auto-update
- Sync between cloud (claude.ai/code) and desktop so users who learn about a feature in one surface see it surfaced on the other
- Changelog rendered inline on first launch after an update — concise, dismissible, with command examples
These aren't strictly the same bug as the AI-flagging-real-features issue, but they share the same broken assumption: that users (and the AIs they're working with) will somehow know about new capabilities without the product surfacing them.
Why this matters
A real, advertised Claude Code feature was treated as suspicious by the AI inside the same product, AND the user (me) only learned the feature existed after triggering this exact failure mode. That makes the model look broken, the feature feel broken, and the discovery story feel broken — erosion of trust in three layers at once.
The model-side fixes (1–3 above) are small and high-leverage: each one independently eliminates the AI-flagging failure mode. The user-side fixes are a separate UX investment but worth bundling in the same product thinking.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗