Govern

Command rules

Decide the shell commands a harness runs, part by part: the platform's default rules ask about catastrophic commands on every node, and the tenant's own rules Allow, Ask or Refuse by the command's parse, never its text.

For: tenant admins and governance reviewers.

Command rules decide the shell commands a harness asks to run. Add a tenant rule below, then review the matching and parser limits before allowing a broader class of commands. Keep the sandbox enabled: these rules cover commands the harness reports to the platform.

A harness agent runs commands of its own: Claude's Bash, a Codex, Gemini CLI, OpenCode or goose session's execute calls and the terminals it opens through the client, and a remote session's bash. These are not functions of the tenant's plugins, so the function rules do not decide them. Command rules do. They live in the same tool policy, beside the function rules, with the same three outcomes, the same reasons, ends, shadow mode, four eyes, export and apply, and the same audit trail.

On every node, for every tenant, with nothing installed and no model asked, each command a harness asks to run is read as a syntax tree and decided before it runs:

OutcomeWhat happens
AllowThe command goes on, as the job's hooks and approvals say.
AskA person decides, on an approval that names the rule and its reason. Their no reaches the agent as a refused call.
RefuseThe command is not run, and the agent reads the rule's reason.

The platform's default rules only ask; they never refuse on their own. Only the tenant's own Refuse refuses.

The default rules

These ask a person about catastrophic commands, on by default. Each has an ID a tenant's rules name, a reason the approval card shows, and examples that are checked whenever the rules load: each match example must still be found and each not_match example must not, or the node asks a person about every command rather than decide by rules that no longer say what they did.

IDIt asks aboutSuch as
cmd.delete-homeDeleting a home, the root, a top-level folder, a folder above the working directory, or a path it cannot resolve, recursivelyrm -rf ~, rm -rf /*, cd ~ && rm -rf *, rm -rf "$DIR"/, find ~ -delete, find / -exec rm {} +
cmd.disk-eraseErasing a diskmkfs.ext4 /dev/sdb1, wipefs -a /dev/sda, dd of=/dev/sda, > /dev/nvme0n1, /usr/bin/time -o /dev/sda, shred /dev/sda, sgdisk --zap-all, diskutil eraseDisk
cmd.chmod-rootChanging permissions or owners of the root recursivelychmod -R 777 /, chown -R nobody /usr
cmd.fork-bombA function that calls itself:(){ :|:& };:
cmd.download-runRunning what it downloads, unreadcurl ... | sh, wget -qO- ... | sudo bash, bash <(curl ...), sh -c "$(curl ...)"
cmd.default-branchRewriting or deleting a default branchgit push --force origin main (and master, trunk, develop, or the current branch when none is named), git push origin --delete main
cmd.git-clean-homeDeleting what git does not track in a homecd ~ && git clean -fdx
cmd.cloud-deleteDeleting cloud resourcesgh repo delete, gh release delete, kubectl delete namespace, kubectl delete ... --all -A, terraform destroy and apply -destroy, aws s3 rb --force, aws s3 rm s3://bucket --recursive, docker system prune -a --volumes
cmd.unreadableA command with a construct the reader does not model exactly: the flooran unclosed quote, eval, a loop, a pattern (ls *.txt), $(...), $HOME, sh -c '...', xargs, git -c ..., and everything else outside what the reader reads

oz0 policy show lists them with their version; Govern › Policy › Commands shows them with their reasons. Each default is found by one or more checks (rm-recursive, find-delete, download-to-shell and the others); the card names both, such as "cmd.delete-home (rm-recursive)". A home spelt in another case (rm -rf /USERS/kevin) is the home, since macOS's file system ignores case by default.

Your own rules

Add a rule as you add a function rule, with --command and the command's pattern instead of a function:

Terminal
oz0 policy refuse --command 'git push --force * [default-branch]' --reason "nobody rewrites main"
oz0 policy ask --command 'kubectl delete **' --reason "deletes in the cluster need a person"
oz0 policy allow --command 'terraform destroy -target=module.test.*' --agent infra --reason "test modules only"
oz0 policy allow --command 'curl -fsSL https://get.k3s.io | sh' --agent installer --expires 72h --reason "the k3s bootstrap"

A rule over a default names it by its ID instead of a pattern, to turn it off (Allow), make it refuse, or either for some agents, callers or target classes. It is stored by the ID, so a later version of the defaults never undoes it:

Terminal
oz0 policy allow --default cmd.download-run --agent installer --reason "the installer runs vendor scripts"
oz0 policy refuse --default cmd.cloud-delete --reason "agents never delete cloud resources"
oz0 policy refuse --default cmd.delete-home --target home --reason "homes are never deleted"
oz0 policy refuse --default cmd.unreadable --agent nightly --reason "unattended jobs run only what can be read"

--agent (repeatable) narrows a rule to those agents' jobs, --caller to calls by some plugins, --target a rule over a default to what it finds of these classes: home, root, outside-workdir, unresolvable, device, default-branch. An Allow narrowed so allows a command only when every path the default found in it is of those classes: a delete of an unresolvable path and a home together still asks under an Allow for unresolvable. A Refuse or an Ask narrowed so decides when any of them is.

--shadow, --expires and --id work as for function rules, and so do oz0 policy edit and remove by the rule's ID. --agent on a function rule is the condition caller.agent == '<name>'.

The --reason is what the agent reads when the rule refuses a command, and what the approval card says when it asks, so write it for them: "homes are never deleted" rather than "per review".

Previous section links

allowlist a command from its card: Read the section.

governed audited exported: Read the section.

patterns: Read the section.

what it sees and what it does not: Read the section.

what the reader reads: Read the section.

which rule decides: Read the section.

which rules a running job uses: Read the section.

Copyright © 2026