Changelog¶
All notable changes to this project are documented here. The format follows Keep a Changelog and the project adheres to Semantic Versioning.
Unreleased¶
0.4.1 - 2026-10-21¶
Changed¶
- The README and the PyPI page lead with what grip does ("a git hook that won't let you
push code you can't explain"), show the whiteboard first, and start with a 30-second
offline try-out: a throwaway repository and
--provider fake, no hook, no API key.
0.4.0 - 2026-10-20¶
Added¶
grip quiz --branchquizzes the branch since it left the default branch, the diff of its pull request, without typing--range main..feat/x.grip ask,grip checkandgrip whiteboardtake it too.grip statusshows where the branch stands against the default branch, and every row says when and how it was quizzed:branch vs origin/main passed 98/100 at 17:52,failed 40/100 at 17:40,not quizzed (4 files).
Changed¶
- A push with nothing new to quiz says why, and when its commits are already on the
remote but the branch never passed a quiz, says to run
grip quiz --branch. - A failed quiz points to
grip last, on the score line and in the final message.
Fixed¶
- Answers in paragraphs keep their line breaks. A paste in the terminal is one answer,
blank lines included, ending at the next empty line, instead of spilling into the next
questions.
grip gradeaccepts raw line breaks inside the JSON strings, which coding agents write when they copy an answer as it is; the/gripskills say to keep them.grip lastindents the lines of a long answer.
0.3.0 - 2026-10-20¶
Added¶
- A retry reuses the questions. Quizzing the same diff again (after a failed quiz, from the
hook,
grip quizorgrip ask) reuses the questions written for it, so only the grading calls the model;grip whiteboardreuses its board the same way, which skips the slowest call. Entries are keyed by the diff, the task context, the difficulty, the provider and the model, live in.git/grip/cache/and expire aftercache_hours(24 by default, 0 turns it off).--freshasks for new questions once.grip submitnever reuses questions. - The hook can use the whiteboard. With
hook_mode = "whiteboard"(orGRIP_HOOK_MODE=whiteboard), the pre-push and pre-commit hooks open the board in the browser and the change is defended there instead of in the terminal. Where no browser can be opened, over SSH or without a display, they fall back to the terminal quiz.
0.2.2 - 2026-10-19¶
Changed¶
- Releases are automatic. Each pull request carries one label,
release:patch,release:minor,release:majororrelease:none; merging a labelled one bumps the version, dates the changelog, tagsmainand publishes to PyPI and GitHub. A check makes sure every pull request has exactly one. grip initasks, in a terminal, which model to use, the pass mark and whether to quiz before pushes, commits or both, with defaults detected on the machine, then says what the chosen provider still needs.--yestakes every default; scripts are not asked.grip installsays which model will write the questions when none is configured.
Fixed¶
- Pushing a new branch said "nothing to quiz" when its commits were also on a branch that
had been deleted upstream (a merged pull request) but not pruned locally: the stale
origin/...ref made them look pushed. grip now asks the remote withgit ls-remotewhenever the local refs say a new branch has nothing to send. - With no provider configured, grip used the Anthropic API even when Claude Code, Codex or
Gemini CLI was installed, and without an API key it crashed with a traceback. The
default provider is now
auto: the first installed coding agent, else Anthropic. A missing Anthropic key is now a clear error that says what to set. grip quiz --range main..feat/xcut branch names to 12 characters in its header (main..feat/kidnap-); only full hashes are shortened now.
Documentation¶
- A shorter README in the usual open-source shape: what grip is, install, quick start, configuration, links. The long-form material moved to the docs site.
- New walkthrough: one real change, from
git committo an accepted push, with the real questions, grades and screenshots. - New inside grip deep dive: the checks before a quiz, diff collection, prompts, structured output per provider, rubric grading, pass memory, the agent flow, the whiteboard's validation, layout and server, and what is stored or sent.
- The docs navigation is regrouped into Get started, Guides, Deep dive, Reference and Project.
0.2.1 - 2026-10-19¶
grip is on PyPI.
Changed¶
- grip is published to PyPI as
grip-hook:pipx install grip-hookoruv tool install grip-hook. Releases publish there through trusted publishing, and the GitHub release carries the same sdist and wheel. - The prebuilt binaries are gone. They bundled the build machine's Python, so the 0.1.0
and 0.2.0 Linux binaries needed glibc 2.38 and failed on Ubuntu 22.04 and older with
GLIBC_2.38 not found.install.shnow installs the package with uv or pipx, and replaces a binary left by an earlier install. - Windows is supported through the same install.
Fixed¶
- Whiteboard layout: a reply arrow (
allow -> handlerafterhandler -> allow) no longer pushes the board into extra columns, a part that only feeds others (tests, a fixture) sits just before what it feeds instead of across the input's arrow, and each column is ordered by what feeds it so fewer arrows cross. - Whiteboard page: long labels and roles end in an ellipsis inside their box (the full text is in the tooltip and the side panel), long arrow labels wrap onto two lines and slide along their arrow when they would cover another label, a box or a pin, and a pin on an arrow sits on the arrow.
- Whiteboard page: two questions pinned to the same box or arrow were drawn on the same spot, so one was hidden and could not be clicked. They now line up side by side.
--unpusheddescribed its range assha..shawith the same commit twice; the base is now resolved to the parent's hash.
0.2.0 - 2026-10-15¶
The whiteboard release.
Added¶
grip whiteboard: the change drawn as a whiteboard (its parts, how they connect, which inputs are untrusted) with five questions pinned to it, defended in the browser. It asks the two whiteboard questions the quiz does not: what a malicious actor could do and why a data structure was chosen. Graded on the same 100-point scale; a pass counts for the push hook.--interviewshows the rubrics to the person asking and records nothing,--exportwrites a shareable page without rubrics. Served on 127.0.0.1 behind a random token, withHost/Originchecks and a hash-based Content-Security-Policy./grip-whiteboardskill for Claude Code, Codex, Gemini CLI, Cursor and friends.- Providers draw boards (
generate_board); thefakeprovider draws one from the changed files or from a scriptedboard.
Changed¶
- grip is now explained around the whiteboard defense: could you explain and defend this change at a whiteboard? The README, the docs homepage and a new whiteboard defense page map grip's five questions to that bar, and say when to leave grip off (prototypes, demos, experiments).
0.1.0 - 2026-10-15¶
The first public release.
Added¶
grip quiz: five questions about your staged, unpushed or ranged diff, graded to a Grip Score out of 100 with a configurable pass mark.grip hook pre-commit/grip hook pre-push: hook entry points, both for native git hooks and for the pre-commit framework (.pre-commit-hooks.yaml).grip install/grip uninstall/grip status/grip config/grip forget.- Providers: Anthropic (default,
claude-opus-5), any OpenAI-compatible API including Ollama, and an offlinefakeprovider for tests and demos. - Configuration through
.grip.toml,[tool.grip]inpyproject.toml,GRIP_*environment variables and command-line flags. - Passed diffs are remembered for a configurable time so you are not quizzed twice.
- Documentation site built with MkDocs Material and published to GitHub Pages.
- A brand identity under
branding/: the grip mark (an 87.5 percent score ring that reads as a G) in ember orange on warm graphite, Archivo wordmark lockups, a social card, and a palette generated in OKLCH bybranding/build.py, which refuses to write colours that fail WCAG 2 or APCA contrast or that collapse under simulated colour-blindness.tests/test_branding.pykeeps the generated files current. - A redesigned docs site: the generated palette and brand type, tabs for each section, a homepage with an install switcher and feature cards, dark code blocks with checked syntax colours, an announcement bar, social preview tags, and a Brand page.
- Feature clips under
docs/assets/features/: one MP4 and GIF per new feature and a stitched "what's new" cut, recorded byscripts/demo/make_features.pyagainst the real CLI with a scripted offline scenario. - Every recording in the brand: the demo, the feature clips, the launch video and the
Product Hunt stills now use the ember and graphite palette, JetBrains Mono in the
terminal, Archivo and Instrument Sans on the title cards, and the mark. Colours come from
branding/tokens.jsonthroughscripts/demo/brandkit.py, so videos and docs cannot drift. - Two more skills:
grip-reviewquizzes a reviewer on a range of commits (or prints the questions for the author with--questions-only),grip-explainturns the developer's answers from the last quiz into a commit message or pull request description.grip lastshows the last graded quiz, with--jsonfor skills to build on. - An evals harness under
evals/: eight fixture diffs with author notes, three answer arms (blank, generic, notes), repeated grading for noise, a committed fake-provider snapshot the tests keep current, and a Markdown summary. A "Honest numbers" docs page says what is measured, what is not, and where grip gets in the way. CITATION.cffand a Cite section in the README;.github/FUNDING.yml. The README opens with a three-tile summary and a before/after comparison, and its Why section cites the METR, GitClear, DORA and Stack Overflow findings on AI-assisted code.grip skipskips the next hook run once,grip skip --hours Npauses hooks for a while,grip resumecancels. Both the git hooks and the Claude Code push gate honour it; a manualgrip quizdoes not.grip statusgained an activity section: last quiz, whether the staged and unpushed diffs have passed, and the skip state.grip statuslineprintsgrip 92/100 passfor editor and Claude Code status lines.grip init: one command that writes a commented.grip.toml(defaulting to an installed coding agent as provider), installs the pre-push hook and writes the agent rule files.--provider,--passing-score,--difficulty,--stage,--no-hook,--no-agents,--force.config.render_templateproduces the file.grip agents: detects the coding agents installed on the machine (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Cline, Copilot, OpenCode) and writes, inside the repository, the rule file each one reads so it runsgrip checkbefore pushing. Marked blocks inAGENTS.md,CLAUDE.mdandGEMINI.md, grip-owned rules files for Cursor, Windsurf and Cline, and the plugin enablement merged into.claude/settings.json.--list,--all,--agent,--dry-runand--remove.-
Keep A Grip, the problem platform:
grip login,grip logout,grip whoami,grip problems,grip solve SLUGandgrip submit. Solve a problem with any assistant, get quizzed on the diff, have the score reported with an API token.Diffgained acontextfield that the prompts pass to the model as data, andGit.worktree_diffdiffs everything since a base commit, uncommitted work included. -
Demo recording (
docs/assets/demo.gif,.webm,.cast) and the script that regenerates it,scripts/demo/make_demo.py. - Scripted mode for the
fakeprovider throughGRIP_FAKE_SCRIPT, plusGRIP_FAKE_DELAYfor artificial latency. -
Providers that reuse a coding agent already installed and signed in, so no API key is needed:
claude-code(aliasclaude),codexandgemini. Each runs the CLI in non-interactive mode with tools disabled, in an empty scratch directory. -
Claude Code plugin, served from this repository as a marketplace (
/plugin marketplace add guilyx/grip):/griprelays the quiz through Claude and aPreToolUsehook blocksgit pushuntil the diff has passed. - The quiz skill lives at
skills/grip/SKILL.mdin the Agent Skills layout, sonpx skills add guilyx/gripinstalls it into any agent that readsSKILL.mdfiles. The plugin is served from the repository root (hooks/hooks.json,skills/). grip ask,grip grade,grip checkandgrip agent-hook: the quiz as non-interactive JSON steps so any coding agent can drive it.-
grip study exportandgrip study status: an anonymised JSON summary of every quiz taken on the machine (scores and per-question focus only, never code, paths, questions, answers or feedback) for study platforms. Graded quizzes are now appended to.git/grip/history.jsonland the repository is recorded in$XDG_DATA_HOME/grip/repos.json. Nothing is uploaded by grip. -
Launch assets under
docs/assets/launch/(Product Hunt image, icon, 1080p launch video) anddocs/assets/demo.mp4, generated byscripts/launch/make_launch.py; a Media page on the docs site.
Changed¶
-
grip initreports agent files as "wrote" or "updated" instead of "written", and the genericAGENTS.mdtarget is labelled "AGENTS.md readers". -
The demo now quizzes a ROS 2 change: a
cmd_velsafety filter gaining a lidar scan watchdog, instead of a payment refund. - Distribution:
install.sh(curl -fsSL .../install.sh | sh) downloads a prebuilt, checksum-verified binary from GitHub Releases into~/.local/bin. The release workflow builds binaries for Linux and macOS (x86_64 and arm64) with PyInstaller; nothing is published to PyPI anymore. modelnow defaults to empty, meaning the provider's own default (claude-opus-5for Anthropic, the CLI's default for coding agents).openaiandollamarequire it.- The score table uses rounded borders, matching the panels.
- The "blocked" message prints the report path relative to the working directory.