| name | pre-push-review |
| description | Automatic code review before every git push. Review all changes on the current branch against the base branch. Block push on critical issues, warn on medium issues, pass silently when clean. Triggered automatically by a PreToolUse hook on "git push". Use when reviewing code before pushing, ensuring code quality, or setting up push gates. Trigger words include: pre-push, review, push review, code review before push. |
Pre-Push Review — Automatic code review before every git push
Review all changes on the current branch against the base branch. Block push on critical issues, warn on medium issues, pass silently when clean.
This skill is triggered automatically by a PreToolUse hook on git push. Every push must pass review.
Step 0: Detect base branch
BASE=$(gh pr view --json baseRefName -q .baseRefName 2>/dev/null) ||
BASE=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') ||
BASE=$(git rev-parse --verify origin/main 2>/dev/null && echo main) ||
BASE=$(git rev-parse --verify origin/master 2>/dev/null && echo master) ||
BASE="main"
If on the base branch with no changes: output "Nothing to review" and allow the push to proceed.
Step 1: Get the diff
git fetch origin $BASE --quiet
git diff origin/$BASE...HEAD --stat
git diff origin/$BASE...HEAD
If no diff, allow push to proceed.
Step 2: Hard gates (deterministic, run first)
Run these checks. Any failure in this section → BLOCK.
2a. Secret scan
Search the diff for patterns that look like leaked credentials:
- API keys (
AKIA, sk-, ghp_, gho_, tvly-)
- Generic patterns: lines matching
password\s*=\s*["'][^"']+, secret\s*=, token\s*= with literal values (not env vars or config references)
.env file contents in the diff
If found → BLOCK with exact file:line and the matched pattern.
2b. Debug statements
Search the diff (added lines only) for:
console.log( — JavaScript/TypeScript
System.out.println( — Java
print( in .py files (but NOT print( inside logging/test files)
debugger — JavaScript
If found → WARN (not block, these are common but should be cleaned up).
2c. Build check (auto-detect project type)
Detect what build system the project uses and run the appropriate check. Only run for project types where changed files exist:
| Marker file | Command | When to run |
|---|
package.json | npm run build | Changed files include .ts/.tsx/.js/.jsx/.vue/.css |
pom.xml | mvn compile -q | Changed files include .java |
Cargo.toml | cargo check | Changed files include .rs |
go.mod | go build ./... | Changed files include .go |
requirements.txt or pyproject.toml | python -m py_compile on each changed .py file | Changed files include .py |
If no marker file matches → skip build check.
If build fails → BLOCK.
2d. Test check
Run tests relevant to changed files (not the full suite):
- Detect test framework from project markers
- Run only tests in directories related to changed files
- If no test framework detected or no relevant tests → skip
Classify failures:
- Pre-existing: test was already failing before this branch's changes → note but do NOT block
- Newly introduced: test passes on base but fails on this branch → BLOCK
Step 3: LLM review (CC reviews the diff)
Analyze the diff for issues that hard gates cannot catch.
Severity levels
- 🔴 Critical: Security vulnerabilities, data loss risks, broken auth, SQL injection
- 🟠 Warning: Logic bugs, missing error handling, race conditions, N+1 queries
- 🟡 Medium: Code style inconsistency, missing validation, poor naming
- 🟢 Nit: Minor suggestions, style preferences
Confidence scoring
Every finding gets a confidence score (1-100):
- 80-100: High confidence, verified by reading specific code
- 70-79: Likely correct, pattern match
- 50-69: Could be false positive → goes to appendix, not main report
- Below 50: Suppress entirely
Review dimensions
- Security: Injection, unvalidated input at system boundaries, auth bypass, CORS issues
- Logic: Null/undefined handling, off-by-one, infinite loops, unhandled promise rejections
- Interface alignment: If both frontend and backend files changed — do API paths match? Field naming consistent (camelCase vs snake_case)?
- Code patterns: Does the new code follow existing patterns in the codebase?
Scope drift detection
Read commit messages (git log origin/$BASE..HEAD --oneline) to determine the branch's intent.
Compare the diff against the stated intent:
- CLEAN: Diff matches intent
- DRIFT: Extra changes not related to intent (scope creep)
- GAP: Stated intent not fully addressed in diff
Output scope check result. This is informational, does not block.
Step 4: Verdict
Combine hard gate results and LLM findings:
- BLOCK: Any hard gate failure (secrets, build, new test failure) OR any 🔴 Critical finding with confidence ≥ 80
- WARN: Any 🟠 Warning with confidence ≥ 80, but no blockers
- PASS: Everything else
Step 5: Report and act
## Pre-Push Review
**Branch**: [current] → [base]
**Changed**: [N] files (+[X], -[Y])
**Hard gates**: ✅ all pass / ❌ [failed items]
**Scope**: CLEAN / DRIFT / GAP
**Verdict**: PASS ✅ / WARN ⚠️ / BLOCK 🚫
🔴 Critical (blocks push):
- [file:line] (confidence: N) — description
🟠 Warning:
- [file:line] (confidence: N) — description
📎 Appendix (confidence < 70, not blocking):
- [findings]
Action after report
- PASS → Execute the original
git push command immediately. No user interaction needed.
- WARN → Execute
git push, then display the warnings.
- BLOCK → Do NOT execute
git push. Display the report. Ask: "Fix these issues before pushing. Want me to fix them?"
Scope
This skill is universal — it works with any tech stack. Build detection is automatic. No configuration needed.
What this does NOT do
- Does not create PRs (that happens after push)
- Does not manage versions or changelogs
- Does not run the full test suite (only relevant tests)
- Does not review documentation-only changes in depth (reduced checks for .md-only diffs)