gatecheck
v0.0.1
Published
Quality gate for git changes — run checks and AI reviews against changed files
Readme
gatecheck
Quality gate for git changes — run deterministic checks and AI-powered reviews against changed files.
In AI-native workflows, agents produce large volumes of code changes. Compound guardrails — type checking, linting, testing — let agents receive automated feedback and self-correct in a tight loop. gatecheck makes this simple: run gatecheck check and it executes your configured checks, scoped to only the files that changed. Run gatecheck review to get AI-powered code reviews on the same changed files.
Designed for AI agent integration. Ships with built-in support for Claude Code hooks and Copilot CLI hooks.
Install
pnpm add -D gatecheckQuick Start
Run the interactive setup to generate a gatecheck.yaml config file:
pnpm gatecheck setupThe setup wizard walks you through:
- Default changed sources — Which changed files to check (default:
untracked,unstaged,staged,branch:main). - Default target groups — Which check groups to run (default:
all). - Check presets — Detects installed dependencies and pre-selects matching presets (prettier, oxfmt, eslint, oxlint, biome, tsc, tsgo, vitest, jest).
- Review preset — Optionally add an AI review (codex or claude).
- Agent hooks — Optionally configure Claude Code Stop hooks or Copilot CLI agentStop hooks.
For non-interactive setup (CI, scripts):
pnpm gatecheck setup --non-interactiveCommands
gatecheck check
Run deterministic checks (lint, typecheck, test, format) against changed files.
# Run all checks with config defaults
pnpm gatecheck check
# Specify changed sources and target groups
pnpm gatecheck check --changed staged --target lint,typecheck
# Preview which checks would run
pnpm gatecheck check --dry-run
# Machine-readable output
pnpm gatecheck check --format jsonOptions:
| Flag | Description |
| ------------------------- | --------------------------------------------------------------------------------- |
| -c, --changed <sources> | Changed sources (comma-separated). See Changed Sources |
| -t, --target <groups> | Target groups (comma-separated or "all") |
| -d, --dry-run | Show which checks would run without executing |
| -f, --format <format> | Output format: text (default), json, claude-code-hooks, copilot-cli-hooks |
gatecheck review
Run AI-powered code reviews against changed files.
# Run all configured reviews
pnpm gatecheck review
# Preview review configuration
pnpm gatecheck review --dry-run
# Review changes since main branch
pnpm gatecheck review --changed branch:mainOptions:
| Flag | Description |
| ------------------------- | ------------------------------------------------------ |
| -c, --changed <sources> | Changed sources (comma-separated) |
| -d, --dry-run | Show review config and matched files without executing |
gatecheck setup
Create or update gatecheck.yaml interactively.
| Flag | Description |
| ------------------- | --------------------------------------------------- |
| --non-interactive | Skip prompts, auto-detect presets from package.json |
Configuration
All configuration lives in gatecheck.yaml at your project root.
defaults:
changed: untracked,unstaged,staged,branch:main
target: all
checks:
- name: typecheck
match: '\.(m|c)?tsx?$'
group: typecheck
command: pnpm exec tsc --noEmit
- name: eslint
match: '\.(m|c)?(j|t)sx?$'
group: lint
command: pnpm exec eslint {{ ctx.CHANGED_FILES }}
reviews:
- name: claude-review
match: '.*'
exclude: '**/*.md'
vars:
prompt: |
Changed files: {{ ctx.CHANGED_FILES }}
You are a professional software architect.
Please review the changes above.
Point out any design issues, bug risks, or improvements.
command: claude --permission-mode 'auto' -p {{ vars.prompt }}
fallbacks:
- codex exec --sandbox 'workspace-write' {{ vars.prompt }}Config Reference
defaults (optional)
| Field | Type | Description |
| --------- | ------ | -------------------------------------------------- |
| changed | string | Default changed sources (comma-separated) |
| target | string | Default target groups (comma-separated or "all") |
checks[]
| Field | Type | Required | Description |
| ------------------------ | ------ | -------- | ------------------------------------------------- |
| name | string | yes | Unique check identifier |
| match | string | yes | Regex pattern matched against relative file paths |
| exclude | string | no | Glob pattern to exclude matched files |
| group | string | yes | Group name for --target filtering |
| command | string | yes | Shell command to execute (supports templates) |
| changedFiles.separator | string | no | Separator between file paths (default: " ") |
| changedFiles.path | string | no | "relative" (default) or "absolute" |
reviews[]
| Field | Type | Required | Description |
| ----------- | -------- | -------- | -------------------------------------------------- |
| name | string | yes | Unique review identifier |
| match | string | yes | Regex pattern matched against relative file paths |
| exclude | string | no | Glob pattern to exclude matched files |
| vars | map | no | Template variables (can reference env, match, ctx) |
| command | string | yes | Primary command to execute |
| fallbacks | string[] | no | Fallback commands tried in order if primary fails |
Template Engine
Commands and vars support {{ scope.KEY }} template syntax.
Scopes
| Scope | Description | Example |
| ------- | -------------------------- | ------------------------- |
| env | Environment variables | {{ env.HOME }} |
| match | Regex named capture groups | {{ match.workspace }} |
| ctx | Runtime context | {{ ctx.CHANGED_FILES }} |
| vars | User-defined variables | {{ vars.prompt }} |
Context Variables
| Variable | Available in | Description |
| ------------------- | --------------- | ----------------------------------------------------------------------------- |
| ctx.CHANGED_FILES | checks, reviews | Space-separated matched file paths. Shell-escaped in checks; plain in reviews |
| ctx.DIFF_SUMMARY | reviews only | Full git diff output for review context |
Shell Escaping
In check commands, {{ ctx.CHANGED_FILES }} contains individually shell-escaped paths (e.g., 'src/file.ts' 'src/other.ts'), safe for direct use as shell arguments.
In review commands, {{ ctx.CHANGED_FILES }} contains plain paths (for human-readable prompts). When {{ vars.* }} values are substituted into review commands, they are automatically shell-escaped with single quotes. This means you should not manually quote {{ vars.prompt }} in your command:
# Correct — vars are auto-escaped
command: claude -p {{ vars.prompt }}
# Wrong — double-quoting breaks the command
command: claude -p '{{ vars.prompt }}'Changed Sources
Values for defaults.changed and the --changed CLI option:
| Value | Description |
| --------------- | ------------------------------------- |
| untracked | New files not yet tracked by git |
| unstaged | Modified but not staged |
| staged | Staged for commit |
| branch:<name> | Changes since branching from <name> |
| sha:<sha> | Changes since a specific commit |
Multiple sources are comma-separated. Changes from all specified sources are combined and deduplicated.
Default (when not specified): unstaged,staged.
Patterns
Named Capture Groups (Monorepo)
Use regex named capture groups to run commands per workspace:
checks:
- name: typecheck
match: '^packages/(?<workspace>[^/]+)/.*\.(m|c)?tsx?$'
group: typecheck
command: pnpm --filter {{ match.workspace }} typecheckIf packages/app/src/index.ts and packages/lib/src/utils.ts are both changed, the check runs once per workspace: typecheck[app] and typecheck[lib].
Exclude Patterns
Use glob patterns to exclude files from matching:
reviews:
- name: review
match: '.*'
exclude: '**/*.{test,spec}.{ts,tsx,js,jsx}'
command: claude -p {{ vars.prompt }}AI Agent Integration
As a guardrail in context
Add a completion check to your CLAUDE.md (or equivalent):
## Completion Criteria
Before completing the task, run and fix any errors:
```sh
pnpm gatecheck check
```Claude Code Hooks
Add a Stop hook to .claude/settings.json — when any check fails, Claude is blocked from stopping:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "pnpm gatecheck check --format claude-code-hooks"
}
]
}
]
}
}Copilot CLI Hooks
Add an agentStop hook to .github/hooks/gatecheck.json:
{
"version": 1,
"hooks": {
"agentStop": [
{
"type": "command",
"bash": "pnpm gatecheck check --format copilot-cli-hooks"
}
]
}
}Both formats output nothing on success (agent stops normally) and { "decision": "block", "reason": "..." } on failure (agent continues fixing).
Output Formats
| Format | Use case |
| ------------------- | -------------------------------------------- |
| text | Human-readable terminal output (default) |
| json | Machine-readable structured output for CI/CD |
| claude-code-hooks | Claude Code Stop hook integration |
| copilot-cli-hooks | Copilot CLI agentStop hook integration |
License
MIT
