Yieldpoint

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.

DoorCatchesMisses
Per-edit hookAn edit before it landsAnything not written through Claude Code's file-edit tools
Stop gateEverything the hook could not see, including edits made through the shellWork that never ends a turn
Pre-commitEvery provider, because all of their work arrives at a commitNothing 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

CodeMeaning
0Checked, and nothing was weakened.
1Findings. Something was taken away.
2The tool itself failed.
3Nothing 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 }.