block / block/buzz

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

Open
#2,884 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## 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:

```rust
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

```rust
/// 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.