pre-commit-review is a reusable skill package for reviewing Git diffs before committing, pushing, or opening a pull request. In plain terms: a pre-commit review step you add to your AI coding agent (Codex, Claude Code, Gemini CLI, or Kiro). An AI "skill" is just a set of instructions the agent loads on demand — once installed, your agent runs this review whenever you ask it to check changes before a commit, giving you a structured verdict instead of an ad hoc diff summary.
- English:
README.md - Simplified Chinese:
README.zh-CN.md
Translations should stay functionally aligned. If you update one version, update the others in the same change when possible.
For users — install it and use it:
- What It Catches
- Example Output
- Requirements
- Quick Install
- How to Trigger a Review
- Safety Characteristics
- Limitations
For developers & integrators — adapt or extend it:
- Why This Repository Exists
- Repository Structure
- How It Works Internally
- Other Integration Modes
- Review Output Format
- Contributing
- License
The review looks at your changes and reports bugs, security risks, and missing tests before you commit. For each issue it finds, you get the file and line, why it matters, a concrete fix, and how to verify it.
It reviews whatever diff is most relevant, in this order:
- A diff or patch you pasted in
- Your staged changes
- Your unstaged changes (if nothing is staged)
- Your current branch vs. its base branch
- Raw code you pasted with no diff history (treated as a partial review)
- Nothing available — it asks you to stage changes or paste a diff
It then gives one of three verdicts:
SAFE_TO_COMMIT— nothing blocking; commit nowSAFE_TO_COMMIT_WITH_NOTES— commit now, but address the follow-up notesDO_NOT_COMMIT— a blocking issue was found; fix it first
It focuses on what matters for a commit decision: correctness, security, data-handling, regressions, and — only where it counts — performance on hot paths, queries, loops, or network/IO calls. It never modifies your repository; a read-only helper gathers the Git context.
When you explicitly supply a precomputed SARIF 2.1.0 or normalized JSON report, the skill can also ingest it as snapshot-bound static-analysis evidence. This optional lane maps findings to the authoritative diff and changed lines; it never discovers reports or runs analyzers automatically.
When you additionally authorize an absolute static_analysis_profile/v1 path with its exact SHA256, the Phase 2 runner can execute that hash-pinned external analyzer in a bounded, read-only tracked-file snapshot. It uses no shell, does not search PATH, and emits linked execution provenance plus Phase 1 evidence. See Controlled Static Analysis Execution for the trust boundary.
When you explicitly authorize an absolute orchestration manifest path and the exact SHA256 of those manifest bytes, the Rust orchestrator can preflight an ordered analyzer set and run it serially against one shared snapshot. It records cumulative budgets and honest completed, partial, or failed coverage states while keeping each analyzer's findings independent. This lane is limited to self-contained source-only offline tools; build-coupled analyzers should supply precomputed evidence instead. See Static Analysis Orchestration.
This is a complete default review for an additive schema change. It shows the full structure the skill produces — a header with the verdict, an executive summary, priority findings, commit guidance, a change overview, a risk-summary table, impact scope, and a regression-risk level:
# Pre-Commit Review
**VERDICT:** SAFE_TO_COMMIT_WITH_NOTES
**Conclusion:** Safe to commit the language column migration, but suggest writing unit tests for the new `getLocale` method in this commit.
**Tally:** 0 blockers · 1 non-blocking warning · 1 test-gap · 0 review-limits
**Diff source:** staged diff via helper script (`scripts/collect_diff_context.sh`)
**Review scope:** full review - all hunks in `schema.prisma` and `userRepo.ts` inspected
**Change scale:** 2 files, +24 / -3; no lockfiles or large generated files
**Risk level:** 🟡 Medium - database schema change touches data integrity, but it is an additive column with a default value
**Unreviewed changes:** none
## Executive Summary
This change adds an optional `preferred_locale` column (defaulting to 'en-US') to the `users` table. No blocking issues were found. The main residual risk is the consistency of default fallback logic during retrieval; suggest adding unit tests before committing.
## Priority Findings
1. ⚠️ `src/repo/userRepo.ts:22` - missing unit tests for the new `getLocale` method
- Evidence: diff adds database retrieval logic, but no test changes are present under test directory
- Impact: future changes to fallback logic could bypass regression testing
- Fix: add tests in `userRepo.test.ts` covering both NULL and populated language retrieval
- Verification: run `pnpm test userRepo` to verify success
- Confidence: High
## Commit Guidance
- **Required before commit:** None
- **Suggested before commit:** Add unit tests for `getLocale`
- **Follow-up items:** None
- **Suggested verification:** `pnpm test userRepo` to check query logic
- **Suggested documentation:** Include migration down SQL script in the PR description
## What Changed
- **Modified:** data access - added retrieval logic in `userRepo.getLocale`
- **New:** Prisma schema column `preferred_locale`
- **Deleted:** none
- **Behavioral changes:** query defaults to 'en-US' if preferred_locale is not set
## Risk Summary
| Dimension | Conclusion | Basis |
|---|---|---|
| Correctness | Pass | simple query logic without exceptions |
| Security & Privacy | No obvious risk | no sensitive data exposed |
| Data & Migration | Risky | large tables might encounter migration locks; confirm production PG version ≥11 |
| Performance & Scalability | Pass | single-row index query; no hot path impact |
| Compatibility | No breakage | additive column; backward compatible |
| Observability & Rollback | Sufficient | migration includes automated rollback script |
| Test Coverage | Gaps | database query logic lacks unit tests |
## Impact Scope
- **Direct impact:** `userRepo` and database schema
- **Indirect impact:** none
- **Domain confirmation needed:** none
## Regression Risk
**Level:** 🟡 Medium
**Reason:** database schema migration, mitigated by automated rollback scripts
**Minimal verification loop:** run migration and rollback on stagingFor a blocking issue the verdict is DO_NOT_COMMIT with a 🔒-marked blocker in Priority Findings. For large diffs the skill adds coverage-led sections. See references/examples/ for visual and coverage-led examples.
- A supported AI coding agent runtime that can load skills (Codex, Claude Code, Gemini CLI, or Kiro). The skill package ships no runtime of its own.
gitonPATHfor local diff collection. The review still works without it when you paste a diff or code directly.- The static-analysis product runtime is Rust-only.
collect_static_evidence.sh,run_static_analysis.sh, andorchestrate_static_analysis.share compatibility wrappers overstatic-analysis-cli collect,static-analysis-cli run, andstatic-analysis-cli orchestrate. - Self-contained releases include
static_analysis-<platform>next to the diff helper binary. Source builds may usecollect-diff-context-cli/target/release/static-analysis-cli, andPRE_COMMIT_REVIEW_STATIC_ANALYSIS_BINmay explicitly select an absolute executable. The wrappers never searchPATHfor it. - Python 3 is required only for the optional development schema validator,
scripts/validate_schemas.py, which additionally requires thejsonschemapackage. - Network access is optional. From a source clone,
install.shattempts to download the pinned Gitleaks8.30.1binary and verify both the release archive and extracted executable SHA256. Self-contained release packages already include the verified executable. If download is disabled, unavailable, or fails, installation and review still work without local secret redaction. ImplicitPATHdiscovery is not allowed. - A Unix-compatible shell to run
install.shand the helper. On Windows use Git Bash, MSYS2, or WSL.
From a clone of this repository, install globally for any supported agent:
./install.sh --agent codex
./install.sh --agent claude-code
./install.sh --agent gemini-cli
./install.sh --agent kiro-cliThese commands attempt to provision the pinned current-platform Gitleaks binary during installation. This is an installer action initiated by the user; the Agent review workflow never downloads tools. Provisioning failure is reported as a warning and does not prevent installation or review.
List every supported agent id and its project/global paths:
./install.sh --list-agentsDefaults:
- Global installs use the agent-specific global path shown by
--list-agents - Project installs use the agent-specific project path shown by
--list-agents --dir PATHoverrides both defaultsAGENT_SKILLS_DIRoverrides the global default for all agents- Dedicated overrides are also supported for existing integrations:
CODEX_SKILLS_DIR,CLAUDE_SKILLS_DIR,GEMINI_SKILLS_DIR,KIRO_SKILLS_DIR, andCODEX_HOME - Backward-compatible aliases are supported:
claude,gemini, andkiro
Useful flags:
--copycopies the minimal runtime skill payload into the target directory and is the default mode--linkcreates a symlink to this repository, which is useful for local development--projectinstalls into the agent's project-local skills directory--dir PATHoverrides the target skills directory--forcereplaces an existing non-managed target--dry-runprints what would happen without changing anything--no-downloadskips the optional Gitleaks download; review remains available without secret redaction--doctordiagnoses scanner source, version, bundled SHA256, trusted configuration, and stdin/JSON capability without installing a skill; it exits non-zero when redaction is unavailable but does not imply that review is blocked--doctor-target /absolute/managed-skillruns the read-only artifact doctor for an installed target; it never downloads, repairs, or selects a replacement
Release artifact trust is checked outside the extracted core payload. A release consumer verifies the archive's published .sha256 sidecar before opening it, then verifies the project attestation for the exact archive subject. The attestation must bind junit/pre-commit-review, the expected release workflow, an immutable version tag and commit, the GitHub Actions OIDC issuer, and the pack composition digests. scripts/verify_release_artifacts.sh --fixture <fixture> is the build-only verifier used by CI; an unscoped subject-only attestation is rejected.
Manual workflow_dispatch runs of the core release workflow are build-and-verify only. Core attestations and publication are reachable only from a pushed immutable v* version tag.
Third-party packs use the project-owned immutable release tag and never fall back to latest, nightly, another source, or a remote revocation service. Target-local revocations are sorted and digest-pinned with 16,384-entry and 8 MiB ceilings. An offline core installation cannot learn a revocation published after that core was built, so operators must install a newer reviewed core when the distribution manifest changes.
The rust-analyzer provider is never installed or started by a normal review, Fast Mode, repository index, SQLite cache, or static-analysis workflow. Install it only with an explicit copy-mode request:
./install.sh --agent codex --copy --with-rust-analyzer--no-download --with-rust-analyzer accepts only a previously verified
current-platform pack in the canonical cache; a cache miss fails before the
target replacement commit point. --with-rust-analyzer --link is rejected
before any download or target mutation. A successful installation writes the
profile and registry only under the managed target at
runtime/providers/rust-analyzer.profile.json and
runtime/providers/provider-registry.json; callers pass their absolute paths
and exact SHA256 values explicitly to repository-context-provider-cli run.
The provider never downloads at runtime, searches PATH, invokes rustup or a
package manager, resolves a direct upstream asset, or discovers a global
registry.
Examples:
./install.sh --agent cursor --project
./install.sh --agent windsurf --link --project
./install.sh --agent github-copilot --dry-run
./install.sh kiro --dir .kiro/skillsDepending on your review scenario, you can trigger and guide the AI using these prompt examples in your conversation. Below are the 5 primary scenarios, their purposes, and typical prompts:
- Staged/Unstaged Changes Review (Routine Pre-Commit Check)
- Scenario: Developers modify code locally and want to assess if the changes are safe before running
git commit. - Purpose: Inspect the diff for high-risk issues such as syntax errors, deadlocks, sensitive credential leaks, and missing unit tests.
- Prompts:
- “Help me perform a pre-commit review.”
- “Check my staged changes to see if they are safe to commit.”
- “Review my unstaged changes for potential issues or credential leaks.”
- “Check the current modifications for credential leaks or missing tests.”
- Scenario: Developers modify code locally and want to assess if the changes are safe before running
- Branch vs. Base Merge Review (PR Gateway)
- Scenario: A branch is developed and ready to be merged into a target branch (e.g.,
main,develop) via Pull Request, requiring a review of the cumulative differences. - Purpose: Perform a static code review on branch changes relative to a specific base ref (e.g.
develop) as a pre-merging gate. - Prompts:
- “Please review my current branch changes against the
developbranch (PR review).” - “Review cumulative differences between the current branch and
mainto see if it is safe to merge.” - “Run a branch-level merge review against base branch origin/develop.”
- “Please review my current branch changes against the
- Scenario: A branch is developed and ready to be merged into a target branch (e.g.,
- User-Provided Patch/Diff Review (Text-only Diff)
- Scenario: The agent lacks local Git repository access (e.g., in restricted sandboxes), or you want to review a patch file by copy-pasting the diff text directly.
- Purpose: Evaluate the quality and risks of a pasted patch.
- Prompts:
- “I have a git diff patch, please perform a pre-commit review on it: [paste diff here]”
- “Analyze this patch for regression risks:
[paste diff here]”
- Static Code Review (Single File/No Diff)
- Scenario: You paste raw source code directly without any before/after diff history, requesting an audit.
- Purpose: Run a static pre-commit style audit. Note that the review will be marked as a "partial review" since no historical diff context is present.
- Prompts:
- “I wrote some new code and want a static pre-commit security review: [paste code here]”
- “Review this single file as a pre-commit readiness audit:
[paste code here]”
- Complex/Large Diff Review (Coverage-Led)
- Scenario: Large or highly fragmented changes (e.g., major refactoring or version upgrades) where direct end-to-end diff review is unreliable or truncated.
- Purpose: Automatically split changes into manageable groups using
collect_diff_context.sh, track coverage with a ledger, and synthesize results via a reducer to ensure no modified line goes unreviewed. - Prompts:
- “This branch has a huge diff, please perform a coverage-led review.”
- “Please start a coverage-led pre-commit review, split the changes into groups, and review them step-by-step.”
- “Analyze the large amount of changes on the current branch, generate a Review Plan, and audit them group by group.”
This package is intentionally conservative:
- it avoids pretending to see local changes when no repository is available
- it distinguishes staged and unstaged review scope, and flags when unstaged changes touch files also staged
- it warns about untracked files not present in
git diff - it never reproduces secret values; flagged credentials are shown as a redacted preview with a rotate suggestion
- it treats large or truncated diffs as a reason to split work and retrieve smaller context, not as permission to skip material units
- it reserves partial triage for advisory fallback and blocks commit-readiness when high-risk units are unreviewed
- it supports coverage-led commit-readiness by requiring every manifest unit to be accounted for before claiming full scope
- it keeps long-review reducer state compact and explicit instead of relying on implicit conversation memory
- it treats semantic context queries as bounded read-only hints, not arbitrary shell commands or coverage substitutes
- it accepts static-analysis reports only through explicit paths, binds them to the authoritative fingerprint, and never treats tool output as manifest coverage
- it executes a static analyzer only through an explicitly authorized, hash-pinned profile and external executable, inside a bounded tracked-file snapshot
- This repository does not include the runtime that loads or executes the skill.
- The included installer covers common Codex, Claude Code, and Gemini CLI locations, but some local setups may still require
--diroverrides. - The helper script expects a working
gitexecutable in the environment. - Static-analysis evidence ingestion and controlled execution use the bundled Rust CLI. Python is needed only for the optional
scripts/validate_schemas.pydevelopment validator and itsjsonschemadependency. - Controlled execution is process isolation for a trusted hash-pinned tool, not an operating-system hostile-code or network sandbox.
- On Windows, the helper script and installer require a Unix-compatible environment (such as Git Bash, MSYS2, or WSL) to run correctly.
- The current repository itself may be used outside Git, but local diff collection only works inside a Git repository.
This repository is not an application or framework. It is a small, portable skill package that can be:
- published as a standalone open source repository
- copied into an existing skills collection
- adapted for local agent tooling that needs pre-commit review behavior
.
├── install.sh
├── SKILL.md
├── agents/
│ └── openai.yaml
├── collect-diff-context-cli/
│ ├── Cargo.toml
│ └── src/
├── docs/
│ ├── helper-capabilities.md
│ ├── static-analysis-evidence.md
│ ├── static-analysis-execution.md
│ └── static-analysis-orchestration.md
├── references/
├── scripts/
│ ├── bin/
│ ├── build_all_binaries.sh
│ ├── build_with_docker.sh
│ ├── collect_diff_context.sh
│ ├── collect_diff_context.legacy.sh
│ ├── collect_impact_context.sh
│ ├── collect_static_evidence.sh
│ ├── index_repository_context.sh
│ ├── lib/repository_context_cli.sh
│ ├── lib/static_analysis_cli.sh
│ ├── orchestrate_static_analysis.sh
│ ├── run_static_analysis.sh
│ └── validate_schemas.py
├── tests/
│ ├── lib/
│ ├── collect_diff_context_test.sh
│ ├── full_review_workflow_test.sh
│ ├── helper_shadow_mode_test.sh
│ ├── install_agent_matrix_test.sh
│ ├── install_smoke_test.sh
│ ├── parity_assets_test.sh
│ ├── parity_golden_test.sh
│ ├── repository_context_test.sh
│ ├── repository_index_test.sh
│ ├── repository_index_workflow_test.sh
│ ├── skill_contract_test.sh
│ ├── static_analysis_evidence_test.sh
│ ├── static_analysis_execution_test.sh
│ ├── static_analysis_execution_modes_test.sh
│ └── static_analysis_orchestration_test.sh
└── evals/
├── output/
├── taxonomy/
├── eval_contract_test.sh
├── compare_output_eval_quality.sh
├── compare_output_eval_quality_test.sh
├── readme_surface_test.sh
├── readme_host_entrypoints_test.sh
├── output-eval.json
├── trigger-eval.json
├── output_eval_runner.sh
├── output_eval_runner_test.sh
├── output_eval_codex_runner.sh
├── output_eval_claude_runner.sh
├── output_eval_codex_case.sh
├── output_eval_claude_case.sh
└── output_eval_host_wrappers_test.sh
Loaded on demand by SKILL.md. References are now layered by responsibility:
| Layer | Files | Loaded when | Purpose |
|---|---|---|---|
decision/ |
verdict-rules.md, risk-taxonomy.md, finding-verification.md, static-analysis-evidence.md, static-analysis-execution.md, static-analysis-orchestration.md |
Every routine review, plus finding verification for strong claims, explicit SARIF/JSON evidence, explicitly authorized controlled execution, or an explicitly authorized orchestration manifest | Verdict selection, blocker thresholds, evidence discipline, high-impact claim verification, static-tool reduction, execution authorization, and multi-analyzer coverage honesty |
rendering/ |
output-en.md, output-zh.md, visual-output.md, review-meta.md |
When rendering the response | Per-language review skeletons, optional visual presentation guidance, and machine-readable metadata |
advanced/ |
coverage-led-review.md, visual-review-rules.md, grading-compat.md |
Only for complex workflows | Coverage-led review flow, UI/visual review rules, and grading-sensitive exact phrases |
examples/ |
default-tiny-en.md, default-tiny-zh.md, complex-visual-and-coverage.md |
Optional calibration only | Concrete examples for aligning structure and tone without redefining the rules |
Daily Default/Tiny reviews intentionally avoid loading the examples/ layer unless structure calibration is needed, which keeps routine runs small and stable.
Defines the skill itself:
- when it should be triggered
- how the diff source is resolved
- how large diffs are handled
- what review dimensions must be covered
- the required output template and verdict rules
A read-only helper script that gathers local repository context for the review workflow. It does four jobs:
- Diff source resolution — detects whether the cwd is a Git repository, prefers staged changes, falls back to unstaged or branch-vs-base, and reports diff stats, file lists, status, truncation, high-risk candidates, generated-like/lock files, and top-churn files. Rename, delete, binary, mode-only, and submodule pointer changes are recorded as manifest units.
- A bounded control plane — emits a compact
--control-planeJSON gateway with an authoritative full-scope content fingerprint, per-unit fingerprints, bounded units/groups, work order, and reusable command templates; supports--expect-scope <fingerprint>on follow-up retrieval so stale output fails closed; and disables external diff/textconv drivers so snapshot identity and inspected content stay aligned. - Coverage-led planning + on-demand impact context — emits a Review Manifest/Groups and reducer-friendly structured sections (Review Plan JSON v2, split suggestions, ledgers, work packets, finalization templates). Review Plan v2 points to the fingerprint-bound
impact_context/v1command in the authoritative control plane; structural, text-query, dependency, framework, configuration, and test-selection context is retrieved separately only when needed. - Optional local secret redaction — when a trusted Gitleaks installation is available, scans and redacts each full selected diff before applying its output byte limit, replaces detected match ranges with
[redacted:<rule-id>], rescans the sanitized view, and sanitizes captured wrapper stdout/stderr. This ordering prevents a detected credential crossing the truncation boundary from leaking as an unmatched prefix. If the scanner is disabled, unavailable, times out, or returns no finding, review continues with the original output. If Gitleaks returns a finding but local span mapping or verification fails, the helper reportsstatus: redaction-failedrather than calling the scanner unavailable; this path also continues with the original output and never withholds the review material.
The optional scripts/collect_static_evidence.sh lane accepts explicitly supplied SARIF 2.1.0 or normalized JSON after the control plane is opened. It requires the same scope fingerprint, maps findings to manifest units and added lines, emits reducer-ready dispositions, and revalidates the snapshot before returning. It never runs an analyzer. See docs/static-analysis-evidence.md.
The separate scripts/run_static_analysis.sh lane requires an explicitly supplied absolute profile path and exact profile SHA256. Profiles that trust repository configuration additionally require --allow-repository-configuration. It verifies both profile and external executable bytes, materializes the selected tracked candidate without Git metadata or checkout filters, invokes the fixed arguments directly without a shell, enforces time/output/snapshot limits, and returns static_analysis_execution/v1 linked to the Phase 1 evidence. It never auto-discovers a tool or profile. See docs/static-analysis-execution.md.
The multi-analyzer scripts/orchestrate_static_analysis.sh lane requires an explicitly supplied absolute manifest path and exact manifest SHA256. It preflights every referenced profile and executable before execution, shares one bounded read-only candidate snapshot, runs profiles serially under cumulative budgets, and emits linked static_analysis_orchestration/v1 plus combined static_analysis_evidence/v1. Failed, timed-out, invalidated, and not-run profiles remain visible limitations; findings from separate executions remain independent. It never discovers analyzers or prepares builds/dependencies. See docs/static-analysis-orchestration.md.
The full list of emitted sections (Coverage Ledger Template, Group Review Work Packets, Reducer State Snapshot, etc.) is documented in docs/helper-capabilities.md for integrators building reducer/subagent automation.
The ordinary review entrypoint does not fetch, stage, reset, install, or modify files. Controlled static analysis runs only after the separate profile-path and exact-SHA256 authorization gate, and operates on a temporary candidate snapshot rather than the business repository. During an explicit user-initiated installation, install.sh invokes scripts/fetch_gitleaks.sh when the current-platform binary is not already bundled. The fetcher downloads only repository-pinned upstream assets and verifies pinned SHA256 values for both the archive and extracted executable. Download progress is shown automatically on an interactive terminal; use PRE_COMMIT_REVIEW_FETCH_PROGRESS=always when output is captured, or never to suppress it. --dry-run never downloads, and --no-download skips this optional installer behavior. Run ./install.sh --doctor to diagnose whether local redaction is available.
It does not run, rewrite, or skip tests. test-selection summaries in impact_context/v1 are read-only guidance for choosing focused verification commands and for distinguishing environment failures from code failures. Built-in summaries cover common JVM/Spring/Quarkus/Micronaut, Maven/Gradle integration naming, JUnit tags, Testcontainers, Docker Compose, WireMock/MockServer, pytest markers, Playwright/Cypress/Node e2e, Go build tags, Rust ignored/integration tests, and database/cache/broker/search service configuration. A no-known-env-heavy-marker summary is not proof that a test is isolated; it only means no known heavy-environment marker matched.
The review workflow starts with scripts/collect_diff_context.sh --control-plane. This bounded gateway emits no raw diff and is authoritative only when its collection-start and collection-end fingerprints match. The default report remains plan-first and may omit the global raw diff. PRE_COMMIT_REVIEW_INLINE_DIFF_BYTES (default 60000) controls when that default output inlines the global diff. PRE_COMMIT_REVIEW_MAX_DIFF_BYTES (default 200000) controls truncation for a diff that is actually emitted; use 0 only when printing the full diff is safe.
The default budgets are intentionally conservative even when the selected model advertises a 200K+ context window. CLI hosts can persist or preview large tool stdout before it ever reaches the model, long raw diffs increase latency and multi-turn token cost, and broad diffs can reduce review focus. Treat the defaults as a stable cross-host baseline rather than a model-context maximum.
Advanced gateway budget tuning:
PRE_COMMIT_REVIEW_INLINE_DIFF_BYTES: Default60000. Raise it for private deployments with larger model context windows, for example150000; lower it for smaller models, for example30000.PRE_COMMIT_REVIEW_MAX_DIFF_BYTES: Default200000. Caps any diff that is explicitly emitted through the gateway or follow-up context commands.- Prompt caching and adaptive inline budgets are deployment-specific optimizations. Enable higher inline budgets only after confirming the host does not hide large stdout behind a preview and that latency/cost remain acceptable.
Review group budgets default to 120KB target and 160KB hard limit. Override them with PRE_COMMIT_REVIEW_GROUP_TARGET_BYTES and PRE_COMMIT_REVIEW_GROUP_HARD_BYTES; groups over the hard limit are marked split-required.
The entrypoint wrapper scripts/collect_diff_context.sh supports multiple execution modes for transition and safety:
PRE_COMMIT_REVIEW_HELPER_IMPL: Specifies the helper implementation mode.rust(default): Executes the compiled Rust CLI binary. Collection failures may fall back to the legacy script. Secret-scan failures do not trigger a special fallback or block output; the selected implementation continues without redaction and reports the downgrade.legacyorshell: Forces execution of the legacy Shell script.shadow: Runs both the legacy Shell script and the Rust binary, compares their stdout, warns on mismatches, and returns the legacy script's stdout to ensure safety.
PRE_COMMIT_REVIEW_SHADOW_MODE: If set to1, forces Shadow Mode comparison even whenPRE_COMMIT_REVIEW_HELPER_IMPLis explicitly set tolegacyorshell.PRE_COMMIT_REVIEW_SHADOW_DIFF_LOG: Optional path for writing shadow mismatch diffs. By default, shadow mode does not write diff content to/tmp.PRE_COMMIT_REVIEW_DISABLE_FALLBACK: If set to1, disables the legacy script fallback, strictly propagating Rust CLI process failures.PRE_COMMIT_REVIEW_SECRET_SCAN: Controls optional local redaction:auto(default) uses a verified scanner when available;offskips scanning and continues review unredacted.PRE_COMMIT_REVIEW_GITLEAKS_BIN: Explicit trusted absolute scanner path for development, tests, or controlled offline environments. It must match the pinned version and pass the stdin/JSON capability test. Setting it is an explicit trust decision; otherwise the target-owned artifact (or legacy SHA256-verified bundle) is accepted, andPATHis never searched.PRE_COMMIT_REVIEW_GITLEAKS_CONFIG: Explicit trusted scanner config path for development/tests. Do not point this at configuration from the repository being reviewed.PRE_COMMIT_REVIEW_GITLEAKS_TIMEOUT_MS: Per-process Gitleaks deadline in milliseconds. The default is30000; accepted overrides are50through120000. A timeout kills and reaps the scanner, reportsscanner-timeout, and continues review without redaction.PRE_COMMIT_REVIEW_FETCH_PROGRESS: Controls Gitleaks download progress:auto(default),always, ornever.
Every implementation mode uses the same best-effort stream sanitizer. When scanning succeeds, shadow mismatch logs are based on sanitized stdout/stderr. status: unavailable means the scanner could not run or finish; status: redaction-failed means it returned a finding but the helper could not apply or verify that replacement. Both states continue review without withholding output and explicitly report that redaction was not applied.
Use scripts/collect_diff_context.sh --plan-only or --include-diff never to recover only the structured control plane when a host persisted the original helper output. Use --include-diff always only when you explicitly want the global diff view, still bounded by PRE_COMMIT_REVIEW_MAX_DIFF_BYTES; verify ## Secret Scan before assuming that view was redacted.
Use scripts/collect_diff_context.sh --source <staged|unstaged|branch> --group <group_id> --expect-scope <fingerprint> to retrieve one in-budget review group's diff after opening the control plane. Use --path <path> with the same fingerprint for file-level follow-up when a group needs narrower context or has been split. Rerun --control-plane before the verdict; snapshot drift invalidates the old ledger instead of being merged into a false complete review. split-required groups must be reviewed through bounded replacements instead of as one group.
Use scripts/collect_impact_context.sh --source <staged|unstaged|branch> --expect-scope <fingerprint> --mode fast when structural or cross-file context can materially affect the review. Fast mode parses complete changed Rust files with Tree-sitter and applies bounded text/configuration rules to changed candidate files only. The returned impact_context/v1 must match the authoritative scope fingerprint; partial or unavailable context stays visible and never satisfies manifest coverage.
Fast Mode performs zero persistent writes. It may read a compatible immutable SQLite generation and compose an exact in-memory staged or working-tree overlay; a missing, stale, incompatible, or corrupt generation becomes an explicit cache miss and ordinary changed-file review continues without waiting for a writer.
Deep/index operations write cache only when explicitly invoked. They persist content-addressed, path-independent FileFacts and an immutable heuristic repository graph for the exact candidate. The graph is not compiler-complete: Tree-sitter and the passive Cargo model can resolve supported Rust modules, imports, references, and unique direct calls, but macro expansion, cfg selection, trait/method dispatch, generated targets, external dependencies, and runtime dispatch remain partial or unresolved.
The platform cache defaults are $HOME/Library/Caches/pre-commit-review on macOS, $XDG_CACHE_HOME/pre-commit-review or $HOME/.cache/pre-commit-review on other Unix systems, and %LOCALAPPDATA%\pre-commit-review on Windows. PRE_COMMIT_REVIEW_CACHE_DIR must be an absolute path outside the reviewed worktree and Git common directory. The cache stores derived facts and immutable graph rows, not raw source files; it is repository-sensitive but disposable. index clean is dry-run by default, and --execute is required for deletion.
These POSIX-shell examples use the same explicit limits in both READMEs:
PRE_COMMIT_REVIEW_CACHE_DIR=/absolute/cache \
repository-context-cli index build \
--source staged \
--expect-scope <fingerprint> \
--deadline-ms 30000 \
--max-file-bytes 2097152 \
--max-query-rows 50000 \
--max-graph-depth 2
repository-context-cli index doctor \
--cache-dir /absolute/cache \
--generation <generation-digest>
PRE_COMMIT_REVIEW_CACHE_DIR=/absolute/cache \
repository-context-cli index inspect \
--generation <generation-digest> \
--path src/lib.rs \
--max-rows 100
PRE_COMMIT_REVIEW_CACHE_DIR=/absolute/cache \
repository-context-cli index clean \
--dry-run \
--max-bytes 2147483648 \
--retain-generations 2index build and collect --mode deep are explicit operator actions. They never run Cargo, build scripts, package managers, dependency installation, repository executables, or network discovery. index doctor and index inspect are read-only; index clean --execute mutates only the validated repository cache namespace.
Project-specific risk hints can live in .pre-commit-review/risk-paths and .pre-commit-review/risk-content. Each non-empty, non-comment line is an extended regular expression; matches promote files into high-risk ordering but do not change coverage requirements.
Project-specific text context hints can live in .pre-commit-review/context-queries. Each non-empty, non-comment line is an extended regular expression evaluated by the bounded text adapter over changed candidate files; these matches can guide dependency or caller checks but never satisfy review coverage.
Project-specific test selection hints can live in .pre-commit-review/test-hints. Each non-comment line is a TSV row:
rule_id<TAB>path_regex<TAB>content_regex<TAB>test_kind<TAB>environment_dependency<TAB>confidence<TAB>hint
The impact-context collector emits the first custom hint whose path or content regex matches a changed test file, alongside built-in classification. Built-ins cover popular cross-ecosystem conventions, but project-specific config should still be used for local profiles, naming schemes, proprietary test harnesses, and service-backed suites that are not visible from path/content markers alone.
Human-readable review-planning tables use TSV because paths and commands may contain commas.
Reducer and subagent automation must use authoritative Review Control Plane JSON for scope. Review Plan/Manifest/Ledger sections are report views over that scope; impact_context/v1 is optional evidence with coverage_credit: none. TSV tables are primarily for human scanning. Automation must not reconstruct scope from direct git status or git diff --name-only after the helper has emitted a manifest.
Deterministic shell tests with no model dependency. skill_contract_test.sh pins the cross-document contract between SKILL.md and references/ (forbidden placeholders, required labels, the untranslatable VERDICT field). collect_diff_context_test.sh, control_plane_test.sh, and full_review_workflow_test.sh exercise normal output, authoritative snapshot pinning/drift failure, schemas, and full reduction against temporary real Git repositories. static_analysis_evidence_test.sh, static_analysis_execution_test.sh, static_analysis_execution_modes_test.sh, and static_analysis_orchestration_test.sh cover report ingestion, exact authorization, bounded single/multi-analyzer execution, shared snapshots, cumulative budgets, terminal states, all three candidate snapshot modes, and gitlink omission. parity_golden_test.sh reuses shared parity fixtures plus a dedicated normalizer to compare the retained legacy-vs-Rust report contracts while excluding intentionally migrated context sections. install_smoke_test.sh and install_agent_matrix_test.sh verify the installer across copy/link/dry-run modes and the supported agent matrix. All of them avoid model calls and are safe in CI.
The LLM-backed evaluation harness is now layered by responsibility:
trigger-eval.jsoncovers skill triggering behavioroutput-eval.jsonremains the compatibility umbrella for core output scenariosevals/output/routine-output-eval.json,advanced-output-eval.json,visual-output-eval.json, andlocalization-output-eval.jsonsplit output grading into routine, complex, visual, and localization-specific matricesevals/taxonomy/marker-eval.jsonisolates finding-marker and tally expectations for🔒,❌,⚠️,🧪,👁️,📈, and🧭
Execution entrypoints are layered too:
output_eval_runner.shprepares real local fixtures for any one eval file, can optionally invoke an external model runner, and grades saved responses against expected verdicts and required phrases--eval-fileletsoutput_eval_runner.shtarget one layered output eval JSON such asevals/output/visual-output-eval.json.--skill-dirselects the skill checkout linked into host fixtures, so baseline and current responses can be generated from the same eval cases without changing the harness checkoutrun_layered_output_evals.shruns the layered output eval matrix end-to-end across the routine, advanced, visual, and localization eval filesrun_marker_eval_checks.shvalidates marker-taxonomy coverage and summarizes blocking vs non-blocking case countsoutput_eval_codex_case.shandoutput_eval_claude_case.shrun a single eval case per hostoutput_eval_codex_runner.shandoutput_eval_claude_runner.share host-specific thin wrappers that link this checkout into the fixture's project-local skill directory (.agents/skillsfor Codex,.claude/skillsfor Claude Code) and delegate tooutput_eval_runner.shwith host-appropriate non-interactive commandsoutput_eval_runner_test.shis the deterministic self-test for fixture preparation and grading logiccompare_output_eval_quality.shgrades saved baseline and current responses against the same layered eval cases, emits anoutput-eval-quality-diff/v1JSON report, and fails on regressions or incomplete response sets without invoking a model. Secret-attention cases additionally report non-secret finding recall and fail throughsecret_attention_regressionswhen a credential finding causes authorization, migration, or compatibility recall to fall.compare_output_eval_quality_test.shdeterministically covers regression, improvement, no-regression, and incomplete comparison outcomesoutput_eval_host_wrappers_test.shverifies the wrappers with mock Codex and Claude binaries so host command templates regress without spending model callsrun_helper_gateway_probe.shruns a real-host stage that instruments the bundled helper and selected direct Git commands, then fails if a host inspects Git diff source before attemptingscripts/collect_diff_context.shcheck_persisted_output_contract.shscans host transcripts for persisted helper output and fails if the saved plan/manifest was never recovered before a full-review claimreadme_surface_test.shkeeps the README-facing public surface aligned with the documented contract gates and entrypoint inventoryreadme_host_entrypoints_test.shpins the tieredHost Entrypointssection so the README keeps exposing the host-lane surface byPrimary,Analysis,Stage, andInternal / Repo-wideeval_contract_test.shis the repo-wide gate for trigger evals, layered output evals, marker taxonomy assets, and host-lane contract surfaces
Generate the baseline and current response directories with the same eval files, host, model, and runner settings, then compare them without another model call:
./evals/compare_output_eval_quality.sh \
--baseline-responses /path/to/baseline-responses \
--current-responses /path/to/current-responses \
--report-json /path/to/output-quality-diff.jsonThe advanced-independent-findings-enumeration-en case uses a neutral review prompt and contains one credential plus three independent non-secret findings. For a meaningful stochastic A/B result, run that case 5–10 times per checkout with matched host/model settings and require full current non-secret recall with no per-run decline.
The controlled scanner-off/scanner-on pilot and its limitations are recorded in docs/gitleaks-quality-evaluation.md.
For the host-lane workflow, use these scripts by tier:
Primary:evals/run_host_readiness_pipeline.sh,evals/run_cross_host_readiness.sh- Default entrypoints for end-to-end single-host or cross-host verification
Primary / Real Host Smoke:evals/run_real_host_smoke.sh,.github/workflows/real-host-smoke.yml- Use these when you want one stable entrypoint for real authenticated host smoke runs and artifact collection
Primary / Output Matrix:evals/run_layered_output_evals.sh,evals/run_marker_eval_checks.sh- Use these to run the layered output-eval surface and marker-taxonomy checks without hand-selecting individual eval assets
Analysis:evals/analyze_host_readiness_diff.sh,evals/compare_output_eval_quality.sh- Use these to compare cross-host readiness reports or saved before/after output-eval responses without rerunning stages or invoking a model during comparison
Stage:evals/check_host_availability.sh,evals/run_helper_gateway_probe.sh,evals/check_persisted_output_contract.sh,evals/run_layered_host_evals.sh,evals/host_contract_subset.sh- Use these when debugging or running one host-lane boundary directly
Internal / Repo-wide:evals/eval_contract_test.sh, host*_test.sh,evals/host_failure_taxonomy.sh- Important support surfaces, but not normal user-facing entrypoints
Stage reports:check_host_availability.sh,run_helper_gateway_probe.sh,run_layered_host_evals.sh, andhost_contract_subset.shcan emithost-stage-report/v1Pipeline report:run_host_readiness_pipeline.shemitshost-readiness-report/v1Cross-host and diff reports:run_cross_host_readiness.shemitscross-host-readiness-report/v1, andanalyze_host_readiness_diff.shemitshost-readiness-diff-report/v1
Provides lightweight agent metadata for environments that expose skills through an agent registry.
Installs this skill package into host-specific skills directories for supported AI coding agents. See Quick Install for usage.
This section is for developers who want to understand the resolution logic or extend it. End users can skip to How to Trigger a Review.
The skill resolves review input in this order:
- A diff explicitly provided by the user
- Staged changes in the current repository
- Unstaged changes if nothing is staged
- Current branch compared with a detected base branch
- User-provided code without before/after diff
- If no diff or code is available, the skill asks for staged changes or a provided diff
If the user provides code without a before/after diff, the skill:
- perform a static pre-commit-style review
- labels the review source as user-provided code
- treats the review as partial
- avoids inferring prior behavior unless the user explicitly showed it
When local repository access is available and the user has not explicitly provided review material, the workflow first attempts the helper at scripts/collect_diff_context.sh. Resolve that path relative to the installed pre-commit-review skill package containing SKILL.md, not relative to the user's project root.
The helper is the source of truth for:
- diff source
- review boundaries
- changed file counts
- staged vs. unstaged notes
- untracked file warnings
Only fall back to direct Git inspection when the helper is unavailable at that resolved path, exits non-zero, cannot be executed in the current host, or the user already provided the review material explicitly.
Clone or copy this repository into the place where your agent runtime expects custom skills.
Example layout:
your-skills/
└── pre-commit-review/
├── SKILL.md
├── agents/
├── references/
└── scripts/
Then register or expose the skill according to your agent platform's skill-loading mechanism.
If you already maintain a larger skills repository, copy this directory in as one skill package and preserve the relative paths:
SKILL.mdscripts/collect_diff_context.shscripts/collect_static_evidence.shscripts/run_static_analysis.shreferences/agents/openai.yaml
The helper script is referenced by the skill instructions, so the directory structure should remain intact unless you also update those references.
The expected output is a review that leads with the commit decision and keeps detail minimal:
- a verdict plus a one-line conclusion
- diff source
- review scope
- change scale
- priority findings with concrete fixes
- the minimum risk and test guidance needed to make a commit decision
The default review should answer three questions first:
- can this be committed now
- what must be fixed before commit
- what should be tested next
Only include deeper intent analysis, before/after logic detail, or extra notes when they actually help the commit decision.
Final verdicts mean:
SAFE_TO_COMMIT: reviewed scope looks safe to commit nowSAFE_TO_COMMIT_WITH_NOTES: safe to commit now, but follow-up notes or review limits existDO_NOT_COMMIT: blocking issue found; do not commit as-is
Contributions are welcome. Good focus areas: review heuristics, safety boundaries, the output template, and diff collection robustness across repository states.
See CONTRIBUTING.md for the development setup (shellcheck, the Rust CLI build, and the deterministic test suites) and PR checklist.
Note:
README.mdandREADME.zh-CN.mdare contract files — several tests assert specific phrases appear in them. When editing, keep those exact strings intact or update the assertions together.
This project is licensed under the Apache License 2.0. See LICENSE.