# Control your coding agent in one command — no signup, runs local

One curl command puts a deny floor, an allow/ask/deny policy file, and an append-only audit log in front of Claude Code, Codex, and Cursor. On-device, no account, MIT. Here's the whole thing in 60 seconds.



That recording is real — the live installer, the real CLIs, denies from the
actual hook path. Sixty seconds, one story:

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

No account. Nothing leaves the machine. Then a Claude Code session is asked to
squash the repo and force-push `main` — and the push dies at the hook with the
reason attached, before git ever runs. A `curl` to an external API has to ask
first. The tests run without a prompt, because normal work should never pay a
tax. And at the end, `tail ~/.acp/audit.jsonl` shows every call the agent
made, with the decision and the reason on each line. The same force-push dies
the same death in Codex, from the same policy file.

## What the command actually installs

Three files in `~/.acp`, plus a hook entry in each detected client:

- **`decide.mjs`** — the decision engine. A few hundred lines, dependency-free, pure:
  no imports, no I/O, no network. It classifies a call (`Bash.git.push`,
  `Bash.curl.api.stripe.com`, `Write`), applies the floor, walks your rules
  most-specific-first. Read the whole thing before you let it near your
  shell: [source](https://github.com/agentic-control-plane/acp-install/blob/main/decide.mjs).
- **`policy.json`** — your rules. `allow` / `ask` / `deny`, per tool, per git
  subcommand, per curl host. `"Bash.git.push": "ask"` is the entire syntax.
- **`audit.jsonl`** — append-only log of every call: tool, classification,
  decision, source of the decision, reason.

The floor sits under all of it and always denies the catastrophic:
`rm -rf` on root or home, `mkfs`, `dd` to a disk device, fork bombs,
force-push to `main`. Token-based, so `rm -r -f ~/` and
`bash -c "rm -rf ~"` hidden after `&&` are the same command wearing hats —
[the bypass write-up](/blog/claude-code-deny-list-bypass) is why string
matching wasn't enough.

## What it is not

It's not isolation. A prompt-injected agent inside this can still read what
it can read; a devcontainer is still the right call for untrusted input —
this controls actions, the container contains the process, and they stack.
And if you never touch `--dangerously-skip-permissions`, the built-in
prompts already carry a lot of the load; the ranked options are in
[the comparison](/blog/best-ways-to-control-claude-code-2026).

What it adds over any per-tool setting is the cross-vendor part: one file,
one floor, one log — identical for Claude Code and Codex, instead of two
config dialects that drift.

MIT, and [every file the installer writes is documented](/install-explained).
Outgrown one machine? The same installer without `--local` connects a
workspace — shared policy, every session priced, one console across
everyone's agents.


