Stop AI agents from running kubectl delete
The same kubectl delete asks in a dev context and is denied in a production one: the kube context, AWS profile, Terraform workspace, git branch and paths such as envs/prod are part of every decision. A team policy can name your production clusters, and the optional infra.kubectl_diff setting flags deletes of namespaces, PVCs, statefulsets and CRDs.
Install: npx @ursuciprian/reflex setup starts with local rules in shadow mode, no account or key.
Plugins for Claude Code, Codex CLI and opencode: setup guide.
Infra guardrails: terraform, kubectl, AWS and change management
Terraform AI agent guardrails and Claude Code production safety controls, which work the same way in Codex CLI, opencode, pi and Hermes:
- Plan-aware terraform gate:
an agent's
terraform applywithout a plan file asks forterraform plan -out=tfplan. Withinfra.terraform_showon and a provider plugin cache, Reflex judges the apply by what the saved plan will change: it reads the plan withterraform show -json(neverplanorapply), denies a plan that deletes or replaces anything and names stateful resources such asaws_db_instancefirst. Off by default, becauseterraform showstarts provider binaries an agent could have written; with the cache, it runs only when every provider in.terraformis a symlink into it.terraform destroyasks, and is denied in production. - OpenTofu AI agent guardrails and Terragrunt guardrails:
tofu apply <planfile>goes through the same plan gate withtofu show -jsonand the same plugin cache check, andtofu applywithout a plan asks fortofu plan -out=tfplan.terragrunt apply,run-all applyandrun --all applyask (terragrunt runs the hooks interragrunt.hcl, so its plans are never read).tofu destroyandterragrunt run-all destroyask, and are denied in production. - helm guardrails for AI agents: a helm uninstall
from an AI agent,
helm deleteorhelm rollbackasks, and is denied in a production kube context.helm upgrade --installin production asks with the release and namespace in the reason. Optionalinfra.helm_diffrunshelm diff upgradeand flags removed PVCs, statefulsets and CRDs, only with a helm-diff plugin outside the working tree that has not changed since you savedconfig.json. - kubectl AI agent guardrail (optional,
infra.kubectl_diff):kubectl diffand server dry runs flag deletes of namespaces, PVCs, PVs, statefulsets and CRDs before they run. - Production context: the working directory (
envs/prod), AWS profile and region, kube context, Terraform workspace and git branch are part of every decision, so the samekubectl deleteoraws rds delete-db-instanceasks in dev and is denied in production. - Team policy: team guardrails for AI
coding agents in a committed
.reflex/policy.json(extra rules, always-human patterns, prod markers, freezes, a mode floor, stricterinfrasettings), applied by every teammate's Reflex in Claude Code, Codex and the other agents. It only tightens; its fast lane needsreflex trust .. - MCP server guardrails: AWS MCP safety and the same for
Kubernetes, Terraform Cloud, database and GitHub MCP servers. Reflex blocks destructive MCP tool
calls before they run: a tool named delete, destroy, drop, terminate, purge, rollback, uninstall
and the like, a scale to zero, a bucket policy, security group or IAM change, destructive SQL or
an HTTP DELETE asks, and is denied when an argument or the server points at production. A shell
command in an argument (the AWS MCP server's
call_aws) goes through the shell rules. Reads pass; an unknown tool is logged keyless and judged by Jev with a key. Claude Code, Codex, opencode, pi and Hermes. - Protected files: an Edit, Write,
apply_patchor other file tool write to.github/workflows/,.gitlab-ci.yml,envs/prod/, production Terraform, tfvars and Dockerfiles,.reflex/, agent settings and hooks or shell startup files asks, and the reason names the path. Configurable; a team policy can add paths. - Change freeze: a deploy freeze or change
window for AI coding agents (
{"days": ["fri"], "after": "15:00", "tz": "Europe/Bucharest"}or a date range). During it, a production command that is not read-only asks or is denied, in shadow and enforce mode. Set inconfig.jsonor the team policy; it can only tighten, andreflex statusshows whether a freeze is active. - Audit log:
reflex auditexports one row per decision (agent, session, cwd, production tier and why, redacted command, decision, rule, who approved it) as csv, json or jsonl, for SOC 2 and ISO 27001 change management evidence. An optional webhook (Slack or json, https only) posts redacted denies, asks or production decisions without ever delaying the hook. - Fails closed: every hook starts through
hook.mjs, so a crash while loading or deciding still answers in the agent's own contract (Claude Code ask, Codex deny) in enforce mode, andreflex statusreports it.
kubectl delete in a prod context
reflex check "kubectl --context prod-eu delete namespace payments"
The prod-destroy rule fires in both engines, with no API call:
{
"decision": "deny",
"rule": "destructive operation on production",
"source": "rule",
"policy": "rules-v12",
"latency_s": 0,
"answers": {}
}
kubectl --context prod-eu delete deploy/api -n web gives the same output.
kubectl delete guardrail (optional). With "infra": {"kubectl_diff": true} (off by default,
because it calls the API server), kubectl apply is checked with kubectl diff and the same
arguments, and kubectl delete|replace|patch with --dry-run=server -o name added at the end.
Both use the current kube context (or the command's --context), the same timeout, and never a flag
that writes: --dry-run=server -o name goes right after the verb, so an option of the command left
waiting for a value cannot take it, and a command with its own --dry-run, --raw, --, -f - or
-o is not run at all. Nor is one that names its own --kubeconfig, --server or --token, or runs
with a KUBECONFIG inside its working directory: an agent's kubeconfig could carry an exec credential
plugin, and an agent's server would receive your credentials. kubectl diff exits 0 for no differences, 1 for differences and above 1 on an error. Deletes of namespaces,
PVCs, PVs, statefulsets or CRDs follow infra.destroy (deny by default); other deletes ask with the
count; changes without deletes only add the counts. Off, or on any failure, kubectl commands are
judged as before, and the production markers (--context prod, a prod kube context) still deny
destructive ones.
How do I share Reflex rules with my team, like Claude Code team settings?
Commit .reflex/policy.json at the repository root (reflex policy init writes a starter). Every
teammate's Reflex applies it while Claude Code, Codex CLI or another supported agent works in that
repository: extra ask and deny rules, always-human patterns, production markers and a mode floor
such as enforce. These team guardrails for AI coding agents can only make Reflex stricter. A team
fast lane, the one part that loosens, applies only after each teammate runs reflex trust . in
their own terminal, and only while the file keeps the hash they trusted. An agent shell command
that edits .reflex/ or runs reflex trust gets a tamper ask, and a .reflex/ in a directory
without .git is never read. Other agents' file tools are not gated, so protect .reflex/ in code
review as you would CI settings.
See: GUIDE: team policy.