Anchorwatch

Rules reference

block denies the tool call before it runs. warn lets it run but tells Claude why to be careful. Override any rule in .anchorwatch.json.

Bash commands

Rule Default Triggers Claude is told to
rm-recursive-dangerous block rm -r/-rf whose target is /, ~, $HOME, ., .., *, a system directory (/usr, /etc, /var, /Users, …), the project root, or .git List what would be deleted, then delete specific paths
rm-recursive warn any other recursive delete (rm -rf node_modules) Confirm the path is inside the project and intended
git-force-push-protected block git push --force/-f/--force-with-lease where the target branch (explicit refspec or current branch) is protected Use a feature branch and a PR; the user runs it if history truly must change
git-force-push warn force push to any other branch Prefer --force-with-lease; confirm if the branch is shared
git-push-delete warn git push --delete, --mirror, :branch Confirm ref deletion
git-destructive block reset --hard, clean -f/-d/-x, checkout -- ., restore ., stash drop/clear, branch -D, filter-branch, filter-repo Stash or commit first; ask
sql-destructive block DROP TABLE/DATABASE/SCHEMA, TRUNCATE, DELETE FROM x with no WHERE — in any CLI Write a migration or a scoped statement and confirm
pipe-to-shell block curl … | sh, wget … | bash, incl. | sudo bash Download to a file, inspect, then run
disk-destroy block mkfs, dd if=, fdisk, parted, shred, diskutil erase, > /dev/sdX
perm-broad block chmod 777/a+rwx, chown -R … / Use minimal permissions
env-read block cat/head/tail/less/bat on .env, .env.* (not .env.example/.sample/.template/.dist) grep -oE '^[A-Za-z_][A-Za-z0-9_]*' .env to list names; ask the user for a value
env-dump warn bare env, printenv, set, export -p (piping into grep/rg/awk is fine) Grep for the variable you need
publish warn npm/pnpm/yarn/bun publish, cargo publish, gem push, twine upload, gh release create, docker push, fly deploy, vercel --prod, terraform apply/destroy, pulumi up, kubectl delete/apply, helm install/upgrade, cloud CLI deletes, supabase db reset/push, prisma migrate reset Only if the user asked for exactly this; otherwise confirm
sudo warn any sudo Make sure a system change is expected
kill-broad warn kill -9 -1, killall, pkill -f Target the specific PID
system-config warn appending to ~/.zshrc/.bashrc/.profile, writing /etc/hosts, crontab changes Get approval for persistent system changes

Commands are split on ;, &&, || and | and each segment is checked, so cd /tmp && rm -rf /var/lib is still caught. sudo prefixes are seen through.

File operations (Edit, Write, MultiEdit, NotebookEdit)

Rule Default Triggers
secret-files block .env* (except example/sample/template/dist/schema), *.pem, *.key, *.p12, *.pfx, *.jks, id_rsa/id_ed25519/…, credentials*, secrets.*, .netrc, .npmrc, .pypirc, .git-credentials, *service-account*.json, anything under ~/.ssh, ~/.aws, ~/.config/gh, ~/.kube, ~/.gnupg, ~/.docker/config.json
git-internals block any path inside .git/ (hooks excepted)
lockfiles warn package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lock*, Cargo.lock, poetry.lock, uv.lock, go.sum, Gemfile.lock, composer.lock, Pipfile.lock, flake.lock
self-config warn .claude/settings.json, .claude/settings.local.json, ~/.claude.json, .mcp.json, plugin manifests, .anchorwatch.json, .quality-gates.json
infra-files warn .github/workflows/*, Dockerfile, fly.toml, vercel.json, netlify.toml, serverless.yml, *.tf
outside-project warn a write outside the working directory (temp dirs and ~/.claude excluded)

Read

Rule Default Triggers
secret-read block Read tool on the same secret-bearing files as secret-files

After a write (PostToolUse)

Rule Default Triggers
secret-scan warn the written content contains an AWS key (AKIA…), GitHub token (ghp_, github_pat_), Stripe live key, Anthropic or OpenAI key, Slack token, Google API key, SendGrid or Twilio key, a PRIVATE KEY block, a database URL with an embedded password, a JWT, or a hard-coded literal assigned to a name like password/secret/token/api_key (env lookups and obvious placeholders are ignored). Markdown and .env.example are skipped.

When it fires, Claude is told which pattern matched and roughly where, and instructed to move the value to an environment variable and to tell you to rotate the credential if it's real.