fallow guard answers “what am I allowed to do in this file” rather than “what is wrong with this file”: it names the file’s boundary zone, which zones it may import from, which calls are forbidden there, and every rule-pack policy in scope with the token that suppresses it.
It reads configuration and runs no analysis, so it is fast enough to call on every edit and it works on files that do not exist yet.
guard is the pre-edit question. For violations that already exist in the code, run fallow dead-code or fallow audit, which report boundary-violation and policy-violation findings.Output
Files that do not exist yet
A path is classified by matching it against the zone patterns, not by reading it, soguard answers for a file you are about to create:
"exists": false and every rule field populated as usual.
Paths outside every zone
A path matching no configured zone comes back with"zone": null and an empty rule set. That is a normal answer rather than an error, because unzoned files are unrestricted for import rules.
zones applies everywhere, so it still appears here.
When boundaries.coverage.requireAllFiles is on and the path is not covered by an allowUnmatched glob, the JSON has "coverage_required": true: an analysis run will report that file as a boundary-coverage-violation for belonging to no zone. The human output does not surface this, and the note it prints covers import rules only, so read coverage_required from the JSON on projects that enable coverage.
Options
guard inherits the analysis flags shown in --help, but they do not apply: it runs no analysis, so scoping, baseline, and severity-gate flags have no effect. Passing any format other than human or json exits 2 with guard supports --format json or human.
Exit codes
guard reports no findings, so it never exits 1.
JSON output
$ fallow guard src/ui/App.ts --format json --pretty
allowed_zones always contains the file’s own zone, because same-zone imports are never restricted. unrestricted is true when no import rule constrains the file, either because boundaries are unconfigured or because the path sits outside every zone. policy_rules contains only the rules in scope for that file: a rule declaring zones appears for files in those zones and nowhere else, and the array is empty when rules.policy-violation is off.
Suppression tokens
Every policy rule reports the exact token that silences it, so the comment can be copied straight out of the output:policy-violation:<pack>/<rule-id>. Rule ids are unique within a pack, so the pair identifies one rule everywhere it appears.
For agents
Callguard on the files you are about to touch, at the point where you still have a choice about what to write. An agent that reads the constraints first can pick an allowed import; one that runs an analysis afterwards can only react to the violation it already committed.
guard MCP tool, described in the MCP integration guide.