Skip to content

buzz-acp: no way to select Claude Code's auto permission mode — adapter advertises it, PermissionMode omits it #2884

Description

@skyerus

Summary

buzz-acp can't be configured into Claude Code's auto permission mode, because PermissionMode doesn't have an auto variant — even though the adapter on the other end advertises it.

BUZZ_ACP_PERMISSION_MODE=auto fails clap validation at startup, so the value can never reach the adapter.

The adapter already offers it

Speaking ACP directly to claude-agent-acp (0.61.0), session/new returns:

MODE currentValue: default
   - auto | Auto
   - default | Manual
   - acceptEdits | Accept Edits
   - plan | Plan Mode
   - dontAsk | Don't Ask
   - bypassPermissions | Bypass Permissions

auto is first in the list. session/set_config_option with {configId: "mode", value: "auto"} would be accepted today.

PermissionMode (crates/buzz-acp/src/config.rs:123) has five variants and omits it:

Default | AcceptEdits | BypassPermissions | DontAsk | Plan

Why auto specifically matters for this harness

buzz-acp auto-approves every session/request_permission with allow_once (acp.rs:1068, acp.rs:1671). That's the right call — there's no human at a terminal to answer a prompt, and forwarding one would hang the turn.

The consequence is that the modes collapse:

Mode Effect under buzz-acp
default Agent asks, buzz-acp says yes — indistinguishable from bypass
acceptEdits Same
bypassPermissions Skips the flow (the default)
plan No tool execution
dontAsk Rejects anything needing permission

So in practice an operator picks between "no checks at all" and "can't do any work". auto is the missing middle: Claude Code describes it as auto-approving tool calls with background safety checks that verify actions align with the request, so a classifier stays in the loop without a prompt needing an answer. That's exactly the shape a headless, chat-driven harness wants.

This is a gap rather than a disagreement with the trust model in VISION_AGENT.md ("the shell runs at the operator's trust level, like bash itself") — auto doesn't restrict what an operator may do, it adds a review step that doesn't require them to be present.

Worth noting the asymmetry it leaves today: Codex-runtime agents run inside Codex's own Seatbelt sandbox (which config.rs:627-639 has explicit workarounds for), while Claude-runtime agents run with no sandbox and no permission checks.

Proposed fix

Add the variant and its wire string. PR: skyerus/buzz@feat/acp-auto-permission-mode

/// Auto-approve tool calls, with a classifier reviewing each one.
#[value(alias = "auto")]
Auto,
// as_wire_str():
Self::Auto => "auto",

Tests extended to cover the wire string, is_default, and both the kebab-case and camelCase parse paths, matching the existing per-mode coverage. cargo test -p buzz-acp --lib permission_mode passes; cargo fmt --check clean; no new clippy warnings.

Known related issue upstream

agentclientprotocol/claude-agent-acp#607 reports that permissions.defaultMode: "auto" in settings.json has no effect through the adapter. That's a different mechanism from session/set_config_option, which is the path buzz-acp uses and the one the adapter advertises — but worth knowing about when verifying end-to-end behaviour.

Environment

  • Buzz 0.4.25 (desktop), claude-agent-acp 0.61.0, Claude Code 2.1.220, macOS 15.3 arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions