Skip to content
Agentic Control Plane

Claude Code read our logs and wrote us a security policy

David Crowe David Crowe · · 6 min read
claude-code auto-mode permissions policy engineering
Share X HN LinkedIn

Running Claude Code? See, control, and price every tool call it makes — allow/ask/deny policy, a per-session bill at API rates, and a full audit log, in one command:

curl -sf https://agenticcontrolplane.com/install.sh | bash

Full Claude Code guide →  ·  see your first governed call →  ·  free for individuals

As of August 14, auto mode is the default for Claude Code on Pro, Max, and Team accounts — a classifier now screens tool calls where the permission prompt used to be. Anthropic’s published rationale is blunt and, honestly, correct: in their data, humans at the prompt caught 13.6% of dangerous commands; the classifier catches 89%. Approval fatigue isn’t a UX complaint, it’s a measured security failure.

This week, Claude Code offered to set up auto mode for us. As part of the setup it did something we haven’t seen a harness do before: it read the transcript history on the machine and proposed a security profile derived from how the machine is actually used.

Not a template. A profile, mined from evidence. A trimmed excerpt of what it wrote:

Environment
 · Cloud provider(s): Google Cloud (gcloud used heavily; Firestore API contacted);
   AWS CLI seen once, not established as primary
 · Trusted internal domains: agenticcontrolplane.com, api.agenticcontrolplane.com,
   cloud.agenticcontrolplane.com, calafia.ai (frequently contacted hosts in this
   project's transcripts)
 · Sensitive data locations: .env / .env.example / .env.production files found
   across many sibling checkouts — treat any .env* file and gcloud secrets as
   credential material
 · Sensitive remote targets: any namespace, host, or container whose name carries
   `prod` or `production` as a whole word or name segment

Extra soft blocks
 · Bash(gcloud secrets:*) — scope to secret material reads/writes, given
   secrets-manager marker found in sibling configs

It noticed which cloud we actually use and which one appeared once. It found the .env files in sibling checkouts and classified them as credential material. It flagged gcloud secrets for a soft block because it saw a secrets-manager marker in a neighboring repo. It even scoped its own claims down where the evidence was thin — “not corroborated by usage in this repo.”

This is the right idea, and we should know: deriving policy from observed behavior instead of a blank config file is exactly how our own recommendation engine works — watch what the agent actually does, then propose the rule a human confirms. The harness doing this natively, on-device, at setup time, is the control layer becoming table stakes. Good.

So this post does two things: documents how auto mode actually works, because the mechanics are load-bearing and easy to get wrong — and is honest about what a classifier in the harness does and doesn’t give you.

The mechanics, precisely

Auto mode is a classifier as a second gate. A secondary model reviews tool calls instead of prompting you. The documented order of evaluation is:

  1. PreToolUse hooks fire — on every tool call, regardless of permission configuration.
  2. Permission rules (permissions.allow / permissions.deny) evaluate.
  3. The auto-mode classifier runs last, deciding whether the call proceeds without a prompt.

For actions that must never run regardless of user intent or classifier configuration, permissions.deny in managed settings blocks before the classifier is ever consulted.

The settings surface lives under autoMode.*:

  • autoMode.environment — the trust profile, in prose. The classifier reads it as natural language to decide what “external” means: which repos, domains, and buckets are inside the boundary, and where sensitive data lives.
  • autoMode.allow — carve-outs from soft blocks.
  • autoMode.soft_deny — destructive actions user intent can override (force pushes, production deploys).
  • autoMode.hard_deny — boundaries nothing can override, exfiltration rules being the canonical case.
  • autoMode.classifyAllShell — route every shell command through the classifier (v2.1.193+).

Scope is deliberately restricted. The classifier reads autoMode only from user scope (~/.claude/settings.json) and managed settings — never from project-scoped files. A repository you cloned cannot grant itself trust by shipping a .claude/settings.json. That’s a real prompt-injection defense, and other harnesses should copy it.

And it knows when to give up. After 3 consecutive blocks (or 20 total in a session) the classifier falls back to prompting you — a sensible pressure valve. Orgs that don’t want the mode at all can remove it with permissions.disableAutoMode in managed settings.

Hooks are unaffected. This is the fact practitioners most need: PreToolUse fires on every call, and a hook deny — exit code 2, or a JSON permissionDecision: "deny" — blocks the call even when an allow rule says yes. There is no allow path that skips hooks. Auto mode changes how often a human gets prompted; it does not change what an interception layer on the call path can see or stop. If you run our hook, every call is still checked, logged, and deniable, auto mode or not. The two compose — the classifier makes attended sessions quieter, the hook keeps the call path governed.

One caveat worth knowing: a timed-out hook doesn’t block — the call continues through the normal permission flow. Don’t count on a stalled gate.

What a classifier in the harness doesn’t give you

We’ve now spent several days working under auto mode, and the gaps are as instructive as the feature.

Denials carry no reason. When the classifier blocks a call, recent versions show the fixed text Blocked by classifier. Not which rule, not what the classifier inferred, not what to change. In one working session we hit denials from three different layers — a hook, a server policy, and the classifier — and the classifier’s were the only ones we couldn’t explain afterwards. A deny the operator can’t explain is a deny that gets worked around rather than understood.

The decisions leave no queryable record. Classifier verdicts appear in the session transcript and a “Recently denied” tab, and that’s where they live. There’s no ledger you can query next week to answer what did the classifier allow across our machines, and why? For one developer on one laptop that’s an inconvenience. Across a team it means your effective policy is whatever each machine’s classifier decided, with no record and no way to reconcile.

It’s per-user, per-machine by design. The same scope restriction that defends against repo injection also means there is no workspace-level policy. Two engineers on the same codebase can be running different trust profiles, generated from different histories, drifting independently. Nothing aggregates them, nothing diffs them, nothing tells you they disagree.

It’s probabilistic where it matters most. The environment profile is prose read by a model, not rules evaluated by an engine. That’s what makes it flexible — and it means the boundary moves with the classifier’s judgment on the day. The docs are appropriately careful here: hard boundaries belong in permissions.deny, not in classifier prose. We’d extend that: anything you’d need to prove afterwards — for an incident, an audit, a customer — belongs in a layer that produces a decision record, deterministically, per call.

And the tamper question is open. Settings hot-reload mid-session, including permissions and hooks. The docs don’t state whether the agent itself is prevented from editing ~/.claude/settings.json — the file the classifier trusts. We’ve written before about why an agent must never be able to modify its own controls; until this is documented, assume the guarantee doesn’t exist and enforce it from a layer the agent doesn’t hold the pen on.

The composition that works

None of the gaps above are reasons not to turn auto mode on. They’re the shape of the line between a better attended experience and control you can stand behind later.

Auto mode is squarely an attended-session feature — it exists to reduce prompts while you’re in the chair, and by all early signs it does. The empty-chair test still applies to everything it doesn’t cover: the unattended tiers, the fleet view, the independent record, the deny that comes with a reason attached.

Run both. Let the classifier make your sessions quieter. Keep a deterministic layer on the call path — one that fires on every call, writes a decision record the agent didn’t author, and enforces the same policy on every machine in the workspace. The harness asking “should this run?” per call is the thesis winning. Where the answer has to hold up afterwards, control the tool call itself.

Share X HN LinkedIn
Get the next data drop
What agents actually cost, new tool-surface captures, and the occasional incident post-mortem — sent when we publish something worth your inbox, not on a schedule. Unsubscribe anytime.
Share: Twitter LinkedIn
Related posts

← back to blog