Show HN: Commit-quiz – A pre-commit hook that quizzes you on your own diff Developer Cristopheer96 released commit-quiz, a pre-commit hook that generates 4 statements about a staged diff — 2 true and 2 plausible-but-false — and aborts the commit unless the developer correctly identifies the true ones, aimed at code written by AI agents such as Claude Code, Cursor and Codex. The hook sends the staged diff (truncated to 30 KB) only to the AI CLI the developer already uses (claude, codex or gemini), triggers only on commits with 20 or more changed lines, never on merges, rebases or cherry-picks, and is fail-open: if the LLM does not respond or no dialog backend exists, the commit proceeds with a notice. It requires Node ≥ 18, keeps zero telemetry, excludes lockfiles, *.snap and *.svg by default, and cannot yet run fully local, though the provider table in src/providers.js is designed for contributions such as an Ollama-backed CLI. A pre-commit hook that verifies the developer actually read their changes before committing. Useful when AI agents Claude Code, Cursor, Codex… generate the code and the dev just hits "commit" without reviewing. Every AI code-review tool reviews the code. This one quizzes you . npm install -g commit-quiz commit-quiz install in the repo you want guarded 1. On commit, the hook takes the staged diff git diff --cached . 2. It sends it to an AI CLI you already have and generates 4 statements about the diff: 2 true and 2 plausible-but-false wrong file, inverted condition, different value… . 3. The dev marks which ones are true: - In a terminal : interactive prompt, with colors. - From the editor UI VS Code, Cursor — no terminal : native dialogs macOS via osascript , Linux via zenity when installed , including a "generating…" heads-up and a verdict dialog with the real summary when the answer is wrong. 4. On a correct answer the commit goes through. On a wrong one the commit is aborted and the real summary of the diff is shown. The hook is fail-open : if the LLM does not respond, there is no network, or there is no way to ask, the commit goes through with a notice. A gate that gets in the way ends up disabled; this one only gets in the way when it can do its job. What is sent? The staged diff git diff --cached , unified context of 1 line , truncated to 30 KB, plus a fixed instruction prompt. The diff carries the paths of the changed files in its headers, as any diff does. Nothing else: no repo name, no git history, no author identity, no other files. To whom? Only to the AI provider you already use, through its own CLI and under your own account: claude → Anthropic, codex → OpenAI, gemini → Google. The diff goes from your machine to that provider's API, the same path it takes when you use the CLI directly. There is no commit-quiz server, no shared key and no middleman. Which provider is used is yours to pin with git config commit-quiz.cli . When? Only on commits with 20 or more changed lines configurable , and never on merges, rebases or cherry-picks. Everything below the threshold is never sent anywhere. What does commit-quiz keep? Nothing. There is zero telemetry . The optional debug log off by default records timings, the chosen channel and your answers, never the diff. What is excluded by default? Lockfiles pnpm-lock.yaml , package-lock.json , yarn.lock , Gemfile.lock , Podfile.lock , .snap and .svg . How do I keep sensitive paths out? Add git pathspecs, per repo or --global ; the option is repeatable: git config --add commit-quiz.exclude "config/credentials/ " git config --add commit-quiz.exclude " .pem" git config --add commit-quiz.exclude "db/seeds/customers.rb" Excluded files are not sent and do not count toward the line threshold. How do I skip it for one commit? COMMIT QUIZ=0 git commit … or --no-verify , which skips every hook . Can it run fully local? Not yet. Providers are a small table in src/providers.js ; a local CLI for example one backed by Ollama would be a few lines, and contributions are welcome. If sending diffs to your AI provider is not acceptable in your organization, do not install this tool. - Node ≥ 18. - Some AI CLI on the PATH: Claude Code https://claude.com/claude-code claude , OpenAI Codex CLI codex or Gemini CLI gemini . The first one found is used, or the one set via config. - Native dialogs: macOS out of the box; Linux needs zenity . Without a dialog backend, editor-UI commits fail open terminal commits always work . Once per machine: npm install -g commit-quiz once published to npm npm install -g github:Cristopheer96/commit-quiz meanwhile, straight from GitHub Then, once per repo you want guarded: cd /path/to/repo commit-quiz install That appends the hook line to .husky/pre-commit if the repo uses husky, otherwise to .git/hooks/pre-commit . Idempotent. To remove it: commit-quiz uninstall Why once per repo? Git only runs hooks configured in each repository — that is git's design, not the tool's. In husky repos the hook line is versioned, so one teammate commits it and the whole team gets it ; each dev only needs the one-time npm install -g . cd /path/to/repo commit-quiz --range HEAD~1..HEAD --dry-run quiz over the last commit, answers visible commit-quiz --range HEAD~1..HEAD same but interactive commit-quiz --diff-file changes.diff --dry-run Every option reads, in order: environment variable → git config → default . git config can be per repo or --global , and it also reaches hooks launched from editor UIs, where your shell environment does not. | Env var | git config key | Default | What it does | |---|---|---|---| | COMMIT QUIZ=0 | — | — | Skips the quiz for that commit escape hatch | | COMMIT QUIZ MIN LINES | commit-quiz.minlines | 20 | Minimum changed lines to trigger the quiz | | COMMIT QUIZ CLI | commit-quiz.cli | auto | Provider: claude , codex or gemini | | COMMIT QUIZ MODEL | commit-quiz.model | haiku claude only | Model that generates the quiz | | COMMIT QUIZ LANG | commit-quiz.lang | system locale | Quiz and UI language: en or es | | COMMIT QUIZ TIMEOUT MS | commit-quiz.timeoutms | 90000 | LLM call timeout | | COMMIT QUIZ DEBUG=1 | commit-quiz.debug | off | Appends a debug log in the temp dir | | — | commit-quiz.exclude repeatable | lockfiles, .snap , .svg | Extra pathspecs kept out of the quiz | The quiz and all messages are available in English and Spanish adding a language is one new entry in src/i18n.js . It also skips itself on merges, rebases and cherry-picks in progress. Editor-spawned hooks have no visible output. With COMMIT QUIZ DEBUG=1 or git config commit-quiz.debug true every run appends decisions and timings to commit-quiz-debug.log in your temp dir. | | Terminal commits | Editor-UI commits | |---|---|---| | macOS | ✅ | ✅ native dialogs | | Linux | ✅ | ✅ with zenity , fail-open without | | Windows | ✅ expected; untested | fail-open | bin/commit-quiz.mjs thin CLI entry args + top-level flow src/config.js env + git config resolution src/i18n.js all user-facing copy en, es src/diff.js reading the diff out of git src/providers.js AI CLIs claude/codex/gemini + quiz generation src/ui/terminal.js terminal prompt and rendering src/ui/dialogs.js native dialogs osascript / zenity src/install.js hook install/uninstall No dependencies, no build step — plain Node ESM with JSDoc types. Releases are tagged vX.Y.Z and published to npm by the release.yml workflow requires the NPM TOKEN repo secret ; see CHANGELOG.md . - git commit --no-verify skips it, like any hook. The goal is culture, not security. - Each quiz is one LLM call: ~8-15 s and some cost per commit. Hence the line threshold, the cheap default model, and thinking disabled. - Statements are only as good as the diff: huge diffs are truncated to ~30 KB and the quiz may fall short.