OpenClaw’s Claude CLI Bridge Has a Permission-Prompt Deadlock, Not a Model Problem

The Claude CLI bug filed against OpenClaw this morning is the kind of failure that gets misdiagnosed as “the model hung” until someone reads the wire protocol. Claude is not the interesting culprit here. The interesting culprit is a bridge that asked Claude CLI to run in live stream-json mode, enabled stdio permission prompting, then apparently ignored the permission message Claude sent back when it wanted to use a native tool.

That sounds small. It is not. Modern coding agents are no longer a single model call wrapped in a chat UI. They are nested runtimes: OpenClaw supervising Claude CLI, Claude CLI supervising native tools, both sides carrying their own permission models, approval modes, tool schemas, and timeout logic. Once you have that stack, a permission prompt is not a UI nicety. It is a distributed-systems message. Drop it, and the session does not fail cleanly. It just sits there until the outer watchdog gets bored.

The issue, #80819, reports exactly that behavior on openclaw 2026.5.3-1 with claude-cli/claude-opus-4-6 and claude-opus-4-7. The live-session backend launches Claude CLI with flags including -p, --output-format stream-json, --input-format stream-json, --verbose, --setting-sources user, --allowedTools mcp__openclaw__*, and --permission-mode default. Claude then asks whether it may use a native tool such as Bash. The message arrives as a control_request with subtype can_use_tool. OpenClaw, according to the report and the automated source review, does not answer with a control_response.

The user-visible symptom is ugly: 180 to 600 seconds of silence, followed by stale-session recovery classifications such as queued_work_without_active_run, classification=stale_session_state, and recovery skipped: active_reply_work. That is not a helpful error. It tells the operator that OpenClaw noticed a corpse; it does not tell them who stopped breathing.

The approval path is now part of the runtime contract

Anthropic’s own Claude Code permission-mode documentation makes the underlying contract explicit. Claude pauses before edits, shell commands, or network requests unless the chosen mode and rules allow them. Modes such as default, acceptEdits, plan, auto, dontAsk, and bypassPermissions are not decorative switches. They define how tool authority moves through the system. Even permissive modes keep protected paths out of automatic approval unless bypass semantics are chosen deliberately.

OpenClaw adds another layer. It has its own MCP tools, exec policy, approval UX, audit surface, and runtime permission model. The reporter’s proposed behavior is the right shape because it does not say “auto-approve Claude native tools so the timeout goes away.” It says map Claude’s native-tool request back to OpenClaw’s effective policy. If OpenClaw is running with full exec access and no ask gate, native Bash can be allowed. Otherwise, deny native Bash, Read, Edit, Write, and similar tools with guidance to use OpenClaw MCP tools instead.

That distinction matters. The security bug would be to fix the reliability bug by creating a bypass. OpenClaw’s value, especially in enterprise or multi-agent setups, is that tool execution can be centralized, logged, mediated, and governed. If Claude CLI gets to run its own native tools under a different permission model just because the bridge wants fewer timeouts, the least-audited layer wins. That is how “integration convenience” turns into policy drift.

The source detail makes the report more credible. ClawSweeper points to src/agents/cli-runner/claude-live-session.ts, where buildClaudeLiveArgs adds stream-json and --permission-prompt-tool stdio, while handleClaudeLiveLine returns for every parsed message whose type is not result. If that reading is correct, OpenClaw is deliberately entering a protocol mode that can produce control messages, then treating those messages as irrelevant because they are not final results. That is not a model-quality problem. That is an incomplete protocol implementation.

Why this matters to operators

For teams running OpenClaw with Claude CLI-backed sessions, the immediate advice is simple: avoid workflows likely to trigger Claude native tools until this path is fixed, or shape prompts and tool exposure so Claude stays on the OpenClaw MCP surface. If you must run this backend, add logging for non-result stream-json records and treat a missing control_response as a first-class error. Do not let it degrade into “idle timeout” because idle timeout is where actionable debugging information goes to die.

For maintainers, the acceptance bar should be higher than “the parser recognizes control_request.” A proper fix needs three proofs. First, a fake can_use_tool regression test that asserts OpenClaw emits the correct control_response. Second, a negative-path test proving native tools are denied unless OpenClaw’s effective policy permits them. Third, one live Claude CLI proof turn that asks for a native tool and completes without waiting for the no-output watchdog. Mocked protocol tests prove the bridge writes JSON. Live proof proves the CLI stops waiting.

There is also a product lesson here. The log vocabulary should name the actual failure boundary. “Claude CLI permission request pending with no response handler” is operationally useful. “stale session state” is not wrong, but it is downstream smoke. Agent platforms need errors that tell operators which layer broke: model stream, permission protocol, tool router, subprocess lifecycle, approval UI, or recovery watchdog.

This is where coding-agent infrastructure is headed. Codex, Claude Code, Gemini CLI, OpenCode, and similar tools are becoming platforms, not just CLIs. When another orchestrator embeds them, it inherits their lifecycle and control-plane semantics. Permission prompts, app-server readiness, subprocess cleanup, stream events, and native tool policy all become part of the host platform’s security boundary.

The correct editorial read is not that Claude integration has a bug. The sharper read is that nested coding agents make permission prompts a distributed protocol. OpenClaw cannot treat Claude CLI’s stream as a token faucet and ignore the control messages. Once the bridge asks for stdio permission prompts, it owns the response path. Otherwise, the agent does not fail closed. It fails confusing.

Sources: OpenClaw issue #80819, Claude Code permission modes, Claude Code headless mode, OpenClaw Claude live-session source