PreToolUse gate on Claude’s Bash tool. When Claude tries git commit or git push, the hook runs fallow audit --format json --quiet --explain --gate-marker agent. pass and warn are allowed. fail is blocked, and the JSON findings are sent back to Claude on stderr so it can fix the code and retry.
This is Option C: local agent gate in the adoption rollout. Use it together with the shared CI gate from fallow audit, not instead of it. See Adopt Fallow in an existing repo.
Install it in one command
.claude/settings.json and .claude/hooks/fallow-gate.sh. It detects whether your repo also has an AGENTS.md or .codex/ and, if so, adds a managed Codex fallback block to AGENTS.md as well; the block includes the task-to-command matrix from fallow schema and refreshes on upgrade when you re-run the installer. To remove the generated artifacts later, run fallow hooks uninstall --target agent.
Preview first with --dry-run:
Install globally for every repo
Pass--user to install the gate under your home directory instead of per-project. The settings file lands at ~/.claude/settings.json, the hook script at ~/.claude/hooks/fallow-gate.sh, and the emitted handler command uses "$HOME" in place of "$CLAUDE_PROJECT_DIR" so it resolves in every repo Claude Code opens:
Gate semantics
The hook runsfallow audit --format json --quiet --explain --gate-marker agent and blocks the agent’s git commit or git push only when the audit returns verdict: "fail". The --gate-marker agent flag lets local Impact tracking record blocked-then-cleared containment events when it is enabled. Audit defaults to gate=new-only: inherited findings on touched files are reported in attribution and annotated with introduced: false on individual issues, but they do not affect the verdict. Only findings the changeset introduces fail the gate.
This is the adoption-friendly default for legacy codebases: an agent editing a 10-year-old file is not punished for the existing dead exports already there, only for any new ones it adds.
To gate every finding in changed files (the strict mode), set the gate in your project config:
fallow.toml
.claude/hooks/fallow-gate.sh to pass --gate all explicitly. The script is regenerated on every fallow hooks install --target agent run, so prefer the config-file approach for persistence.
Comparison base
The hook runs barefallow audit with no --base, so audit auto-detects the comparison base as the git merge-base (fork point) against the branch’s upstream or the remote default (origin/main). The merge-base is resolved at run time, so a branch freshly cut from origin/main is gated only on the changes it actually introduces.
Two setups want an explicit base. Set FALLOW_AUDIT_BASE (it takes effect because the gate passes no --base):
- Forks. On a fork,
originis your fork and can lag the real upstream. PinFALLOW_AUDIT_BASE=upstream/mainso the gate compares against the true upstream. - A non-default integration branch. If your team merges into
develop(or a release branch) rather thanmain, pinFALLOW_AUDIT_BASE=origin/develop.
fallow-gate.sh is regenerated on every fallow hooks install --target agent run, so an edit to the script does not survive a reinstall.
Version floor
The installed gate enforces a minimum fallow version via theFALLOW_GATE_MIN_VERSION env var (default 2.85.0). The gate passes --gate-marker agent (added in v2.85.0) so local Impact can record blocked-then-cleared events; older binaries reject the flag entirely, which would make every audit fail open. The gate therefore blocks with an upgrade hint when the fallow on PATH is below the floor. This prevents a stale npm-global or ~/.cargo/bin/fallow from masquerading as a working gate.
fallow-gate: blocked by fallow 2.48.1 at /usr/local/bin/fallow, so “which binary ran this?” is answered without re-diagnosis. The header of the installed script also stamps # Installer version: X.Y.Z for forensics when the gate disagrees with your current fallow --version.
Inspect hook state
fallow hooks status shows what is installed on all three surfaces without touching anything: the Git pre-commit hook, the Claude Code gate, and the Codex AGENTS.md managed block. Agents and scripts use the JSON form before proposing setup changes:
user_edited flags a hook file that exists but no longer carries fallow’s generator marker (or a torn managed block), so an agent knows not to overwrite it without asking. script_version and min_version_floor expose the gate script’s installer stamp and version floor, which lets tooling detect a stale gate.
Remove it
.claude/settings.json, deletes the hook script if it still carries the generator marker (use --force to remove user-edited scripts), and strips the managed block from AGENTS.md. Handlers you added outside fallow stay untouched. Pass --user to uninstall the global artifacts at ~/.claude/ instead of the project ones.
The uninstall flow is idempotent: running it a second time prints unchanged / not present and exits 0. Dry-run is supported (fallow hooks uninstall --target agent --dry-run).
fallow hooks install --target agent also recognises and cleans up hook commands that older manual setups emitted (absolute paths, ~/-based paths, Windows drive paths), so re-running it on a pre-existing install upgrades the handler to the canonical form without leaving duplicates.
Related but distinct:
fallow hooks install --target git scaffolds a shell-level Git pre-commit hook in .git/hooks/ that runs fallow on changed files. That is the human enforcement path. This page is the agent enforcement path. The two can be used together: git hooks catch human commits, the agent gate catches agent commits.Manual setup
1. Create .claude/settings.json
2. Create .claude/hooks/fallow-gate.sh
The canonical source of this file lives in the fallow repo at crates/cli/src/setup_hooks/fallow-gate.sh. For a hands-off install, prefer fallow hooks install --target agent; the inline listing below is for environments where you cannot run that command. When copied by hand, omit the # Installer version: line (it is stamped automatically by the installer for forensics).
3. Make the script executable
Runtime errors fail open on purpose. In JSON mode,
fallow audit reports invalid refs, non-Git directories, and config errors as { "error": true, ... } with exit code 2. Letting those cases through prevents a brand-new repo or empty history from getting stuck before the first successful audit.Codex fallback
Codex now has an experimental hooks surface, but the low-friction fallback while it stabilizes is stillAGENTS.md. Add this to your repo root AGENTS.md:
fallow hooks install --target agent maintains this block for you, scoped between <!-- fallow:setup-hooks:start --> and <!-- fallow:setup-hooks:end --> markers so re-running the command is idempotent.
Why this works well with agents
fallow audit --explain gives Claude structured findings with docs links and fix guidance, while Agent Skills teaches the agent how to act on them. The result is a tight feedback loop: Claude tries to commit or push, the gate blocks only real fail-severity issues, Claude reads the JSON envelope, fixes the code, and retries.
Adoption rollout
See Option C: local agent gate next to warn-everywhere and error-plus-baselines.
fallow audit
Reference for verdicts, JSON output, and baselines.
Agent Skills
Teach the agent what to do after the gate blocks.