Skip to content

Inspecting a Policy

Three commands, none of which execute anything.

Terminal window
wardcell policy explain -- git push

It lists which fragments were applied and why, then every rule they produced, per platform:

fragments applied (4):
- base
- integrations-core/git (selects_on command: git)
- toolchains/apple-toolchain-core (required by: integrations-core/git)
- workspace
== Linux (29 rules) ==
CATEGORY DETAIL DESCRIPTION FRAGMENT LAYER
fs AllowRead /usr base base
fs AllowRead ~/.gitconfig User gitconfig read by... integrations-core/git selected
net.host host="github.com" allow_h... integrations-core/git selected

The “fragments applied” block answers why a rule is present at all. The net.host rows are the request-level rules inside each allow_http block, and the DESCRIPTION column is the same-line comment from the fragment.

Flag
--os linux|macosrestrict to rules that apply on that platform
--output jsonthe stable, scriptable format
--output prettythe default; a full policy per OS, coloured on a terminal
--output textthe same, never coloured
--profile, --zone, --app-bundleselect as run would

Use --os when a rule works on one platform and not the other — an untagged block appears under both, a tagged one under only one.

Terminal window
wardcell policy render -- git push

Prints the compiled backend profile: SBPL on macOS, the bwrap configuration on Linux. This is verbatim what gets applied.

explain tells you what the policy says; render tells you what the backend was told. When those seem to disagree, render is the ground truth.

Add --os to render for the other platform from either host.

Terminal window
wardcell policy verify
wardcell policy verify --policy-root ./policies --output json

Parses and merges the whole root, checking schema_version and the merge invariants — no unresolved same-layer ties, no base overrides. Suitable for CI. It checks the root alone: no workspace policy is read, because a policy root is shared and the directory a command will run in is not known here.

  1. explain | grep <the thing> — is the rule there at all? If not, the fragment was not selected.
  2. Check the layer. A selected rule can be beaten by a base deny.
  3. Check the OS column. An [macos]-tagged rule does nothing on Linux.
  4. Check for a deny. Deny wins from anywhere; explain names the fragment.
  5. render — if the rule is in explain but not in render, that is a backend bug worth reporting.

explain prints what each grant costs on each platform — which grants are transparent and which need client cooperation. Worth reading before assuming an allow_tcp grant works everywhere. See Platform Support.