Getting started
Pick the path that matches how you work. Every one ends the same way:
yieldpoint review tells you whether the change you just made took something
away.
Install
pip install yieldpoint # zero runtime dependencies
pipx install yieldpoint # isolated CLI
uv tool install yieldpoint # same, via uv
Python 3.10 or newer, and nothing else. To try it without installing anything, run
uvx yieldpoint review in a repository with uncommitted work.
Claude Code
The only client that gets all three doors, because it is the only one with a pre-edit hook.
yp init # config + MCP + hook + commit gate
yp install-hook # only to change the mode later
Restart your Claude Code session
Hooks and MCP servers are read when a session starts, so nothing you just installed is active in the session you installed it from — and that looks exactly like it working: no output, no error, every edit allowed.
In the new session, yp doctor is the only way to tell "installed
and working" from "installed and never ran":
[ok ] hook running (advisory — reports, never blocks); 6 edit(s) seen
[ok ] stop gate running (advisory — reports, never blocks); 8 turn(s) verified
[ok ] mcp registered and runnable
0 edit(s) seen after you have edited something means the hook is
registered but not firing. Restart again, and check it was the right window.
The hook starts advisory. When you are happy with what it reports,
yp init --enforce makes it refuse the edit instead of describing it.
Cursor, VS Code, Windsurf, Zed, Cline, Roo, Kiro, Trae
MCP so the agent can ask what a rule means, and the commit gate as the enforcing half.
yp init --client cursor --no-hook
--no-hook skips the Claude-specific files, which would do nothing for
you. Restart the editor, then yp doctor.
Gemini CLI, Amazon Q, opencode, Claude Desktop
yp init --client gemini-cli --no-hook
LibreChat, Continue, Goose, Codex CLI
These configure MCP in YAML or TOML, which this package will not take a dependency to write safely, so it prints the snippet instead of editing your file.
yp init --no-hook
yp install-mcp --client continue --show
No editor integration
yp init --no-hook # config + .git/hooks/pre-commit
Plus pre-commit and CI — see Integrations.
yp install-mcp --list shows every client name.
Validate it in a developer-sized repo
Before adding Yieldpoint to a real project, prove the integration in a disposable Git repository. Establish a committed baseline, weaken a test deliberately, and confirm that both review and the commit gate reject it.
mkdir yieldpoint-smoke && cd yieldpoint-smoke
git init
git config user.email you@example.com
git config user.name "Your Name"
pip install yieldpoint # or: pip install /path/to/yieldpoint
yp init --no-hook # config + pre-commit; no editor setup
mkdir tests
printf 'def test_total():
assert 2 + 2 == 4
' > tests/test_total.py
git add . && git commit -m baseline
# Deliberately weaken the assertion (macOS form of sed).
sed -i '' 's/== 4/is not None/' tests/test_total.py
yp review # expected: REPAIR and exit code 1
git add tests/test_total.py
git commit -m weakened-test # expected: blocked by the pre-commit gate
On Linux, use sed -i 's/== 4/is not None/' tests/test_total.py instead.
The finding should be assertion_monotonicity. Restore the equality assertion
and rerun yp review for a clean result; then initialize the actual repository
and commit its .yieldpoint.json.
Three doors, deliberately
No single surface sees everything, which is why there are three.
| Door | Catches | Misses |
|---|---|---|
| Per-edit hook | An edit before it lands | Anything not written through Claude Code's file-edit tools |
| Stop gate | Everything the hook could not see, including edits made through the shell | Work that never ends a turn |
| Pre-commit | Every provider, because all of their work arrives at a commit | Nothing you commit — it is the backstop |
Reading a verdict
$ yieldpoint review
REPAIR 1 finding(s)
tests/test_invoice.py:14 in test_total [assertion_monotonicity]
Assertion on invoice.total was weakened: eq -> non_null.
fix: Re-assert invoice.total at eq strength, or fix the code under test so the
original assertion passes. Restore `assert invoice.total == 42`.
Every verdict carries a prescription naming exactly what to restore, so a rejected change does not have to be diagnosed by guessing.
Exit codes
| Code | Meaning |
|---|---|
0 | Checked, and nothing was weakened. |
1 | Findings. Something was taken away. |
2 | The tool itself failed. |
3 | Nothing could be analysed. Not a pass. |
Is it saving anything?
Every verdict is recorded locally — no network call, ever. yp stats
adds it up.
$ yp stats
────────────────────────────────────────────────────────────────
SAVED on this repository, across 243 verification(s)
243 model calls not made architectural
~1,194,287 input tokens not read estimated
~$3.58 at $3.00 per M tokens your stated rate
over 27 distinct file set(s); 112 verification(s) re-analysed one already counted
────────────────────────────────────────────────────────────────
Three different kinds of number, never added together. Model calls is architectural: Yieldpoint makes none, and a judge producing the same critique makes one per verdict. Tokens is an estimate. Cost is that estimate times a rate you supply — there is no default, because a vendor price baked in here would be stale within a quarter.
yp stats --price 3.00 # one run
yp stats --since today # a window
yp stats --html # the same figures as a page
yp export # every event as JSON Lines
Or set it permanently: "metrics": { "price_per_million": 3.00 }.