Skip to content

bug(claude): trust dialog accept confirms "No, exit" — new default highlight kills the session #705

Closed

Description

@Juliusolsson05

Expected behavior

Creating a Claude agent in a folder Claude Code has not seen before shows the folder-trust prompt (in-app modal and/or TUI dialog). Clicking "trust this folder" accepts the dialog, Claude Code records the trust in its project config, the session proceeds, and the dialog never comes back for that folder.

Actual behavior

Clicking "trust this folder" (or pressing Enter in the pane) terminates the Claude CLI. The pane dies ~300ms after the click, trust is never persisted, and the dialog reappears on every subsequent start in that folder. Every later send into the pane then fails with Cannot deliver prompt: <id> is not a live agent session. From the user's perspective the trust prompt "does nothing" and the agent is unusable.

Root cause

Claude Code changed the trust dialog (observed on 2.1.251). The live dialog is now:

 ❯ No, exit
   Yes, I trust this folder

 Enter to confirm · Esc to cancel

"No, exit" is listed first and is the default-highlighted option. The vendored older source (vendor/claude-code-src/full/components/TrustDialog/TrustDialog.tsx:228-232) shows the previous order — "Yes, I trust this folder" first — confirming upstream flipped both order and default.

Our accept contract everywhere is a bare '\r', written on the explicit assumption that Yes is pre-highlighted:

  • src/providers/claude/renderer/TrustDialogModal.tsx:17 — accept = () => onSend('\r')
  • src/providers/claude/renderer/conditions/views.tsx:56 — dispatches raw pty '\r'
  • packages/claude-code-headless/src/conditions/trustDialog.ts:44 — accept action data: '\r'
  • packages/claude-code-headless/src/parsers/TrustDialogParser.ts:110 — TRUST_DIALOG_ACCEPT_KEYS = '\r' (comment: "Enter confirms the highlighted option (option 1, Yes …) because CC pre-selects it")
  • packages/claude-code-headless/src/ClaudeCodeHeadless.ts:855-856 — legacy accept: write('\r'), reject: write('2\r') (numbered-list assumption; the new dialog has no numbered options at all)

So "accept" now confirms No, exit → gracefulShutdownSync → the CLI exits. Detection (detectTrustDialog) still works because it matches label substrings order-independently — only the resolution keystrokes are wrong.

Evidence

Debug bundle ~/.config/agent-code/debug-bundles/manual/2026-08-30T23-51-06-471-9bd68e14 (project bringdown, build b4d64c1c, CC 2.1.251). Lifecycle journal shows the loop three times in one run (sessions 1cc95cb1, 4ac948fd, 9bd68e14):

23:45:32.048 gate.eval  blocked  conditionKind=claude.trust-dialog resolvable=true
23:45:32.767 input.write origin=renderer writes=1 bytes=1 hadSubmit=true   ← the accept '\r'
23:45:33.112 gate.eval  terminal reason=exited                             ← CLI exited
23:45:34.870 delivery.reject code=not-ready registryHit=false reason=entry-lost-after-owned

trace/screen/latest-tail.txt in the bundle captures the exact new dialog with ❯ No, exit highlighted.

Impact

Any Claude agent in a not-yet-trusted folder is completely unusable: the app's own trust affordance kills the session, and because trust never persists, this repeats on every start. This is the primary cause of the "is not a live agent session" failures reported today.

Fix direction (long-term, layout-independent)

Stop assuming which option is highlighted. The conditions framework already supports custom actions with a headless resolver that can reparse the terminal between writes (AskUserQuestion uses it — resolveConditionAction):

  1. TrustDialogParser additionally extracts the on-screen option order and which row carries the ❯ highlight.
  2. Trust accept becomes a custom-action resolver: observe the highlight; if "Yes, I trust this folder" is highlighted, press Enter; otherwise press the arrow key toward it, re-parse to verify the highlight moved, then Enter; verify the dialog dismissed. Fail closed (structured failure, no blind Enter) if the highlight cannot be determined — a wrong Enter is session-fatal.
  3. Decline uses Esc (Esc to cancel is stated on the dialog and maps to exit in upstream source); retire the stale '2\r'.
  4. Renderer modal dispatches the condition actions instead of synthesizing raw bytes.

This holds regardless of option order, default highlight, or future re-orderings — the resolver acts on what is actually on screen.

Environment

  • Claude Code CLI 2.1.251, macOS, agent-code b4d64c1c (2026-08-30 production build)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions