CLASH is a universal chokepoint for agent-initiated command execution. It enforces an argument-aware policy ladder (BLOCK → ALLOW → CONFIRM → optional arbiter → break-glass) so LLM CLIs can act autonomously without sacrificing safety.
Simple binary allowlists miss risk hiding in arguments (rm -rf ~, python -c 'shred', find . -delete). CLASH inspects command targets, force flags, repo boundaries, and provides previews before destructive steps.
# build (requires Go 1.21)
go mod tidy
go build -o clash ./cmd/clash
# initialize policy in your repo
./clash init
# run commands through CLASH
./clash run -- ls
./clash run -- rm tmp.txt # will confirm with preview
./clash run -- rm -rf / # blocked- ALLOW:
clash run -- git status - CONFIRM:
clash run -- rm foo→ shows count/sample, asks to proceed - BLOCK (hard):
clash run -- rm -rf /→ refused with safer suggestion
clash run -- <cmd>: core chokepointclash codex|gemini|claude|copilot -- [args]: wrap those CLIs (best-effort logging/protection)clash init: write defaultclash.yamlclash policy explain: print effective policyclash decision explain <audit-id>: inspect a prior decisionclash doctor: sanity checks (repo root, policy path, git snapshot)
Flags: --policy (custom path), --yes (auto-confirm), --break-glass + --break-glass-reason (controlled override; still not allowed for hard blocks).
- Hard BLOCK: destructive tools (mkfs/fdisk/dd), catastrophic rm/git clean/reset cases.
- ALLOW: safe read-only commands from policy allowlist.
- CONFIRM: risk signals (mutations, force flags, protected paths, egress, package installs, leave repo root) with preview and safer alternative.
- Arbiter (optional): stubbed hook to tighten decisions when parsing is uncertain.
- Break-glass: explicit phrase + reason recorded; disabled for hard blocks.
Details in docs/policy-ladder.md.
Every attempt is written to .clash/audit.log (JSONL) with timestamp, cwd, repo root, git summary, decision, signals, preview, approver, break-glass reason, and exit code. View with clash decision explain <id>.
Wrapper commands run Codex/Gemini/Claude/Copilot via CLASH so their top-level executions are logged. Deep interception of child processes varies by tool; see docs/integrations.md for recommended container/devcontainer setup to enforce the chokepoint.
CLASH mitigates common destructive commands but is not a sandbox. Interpreter one-liners or compiled binaries may still evade detection. See docs/threat-model.md.
- Unit and golden tests in
internal/... - GitHub Actions workflow runs
go vetandgo test ./...
$ ./clash run -- ls
CLASH: allowlisted read-only command
$ ./clash run -- rm temp.txt
CLASH: CONFIRM
- signal: mutating command
Preview: 1 items sample: /path/to/temp.txt
Proceed with execution? [y/N]: y
$ ./clash run -- rm -rf /
CLASH: BLOCKED (hard)
- catastrophic rm target
Safer: narrow path or remove -rf
MVP for Linux/macOS. Windows not tested (documented limitation). Arbiter hook is stubbed; wire to your provider in arbiter package.