CutplaneJoin the private beta

Review an AI-generated pull request from your terminal.

GitHub tells you which lines changed. Cutplane tells you which components changed, what else in the system those changes reach, and — for every sentence it prints — the evidence it was computed from.

$ npx cutplane analyzethis branch against the default branch
$ npx cutplane analyze --pr 482a pull request, by number
$ npx cutplane analyze --jsonthe whole report, for another program

Published on npm as cutplane, MIT licensed.

What a report looks like

cutplane zermmi-app  a859dfc1..6e9e3126
base is the merge-base with origin/main

  58 files changed                 7 components changed            9 components reached
   0 routes added/removed         22 schema statements             0 dependencies added

WHAT CHANGED
  src/features/invoicing/ (Invoicing)                                34 files  schema, 8 dependents
    Invoicing changed in 34 files, 3729 lines added or removed.
  …

CHANGE IMPACT — 9 components, 65 files reached
  src/features/invoicing/                                               36 files  1-4 hops   precise
  …
  6 further component(s) reached — ranked lower or held back

When it is uncertain, it shows less

When Cutplane is uncertain, it shows less — not something plausible.

A wrong architecture diagram is considerably worse than an incomplete one. So every list that stops early says how many it left out, every reach it declines to trace says why, and the footer says whether the sentences were written by a model or by templates. There is a section headed “Not stated” whose entire job is to name what the engine computed and chose not to claim.

Every command and flag

cutplane analyze   [--repo <path>] [--base <ref>] [--head <ref>] [--pr <n>]
                   [--full] [--json] [--offline]
                   [--print-llm-payload] [--depth <n>]
cutplane new-files [--repo <path>] [--base <ref>] [--head <ref>] [--pr <n>] [--json]
cutplane doctor    [--repo <path>]
cutplane version
no --base
the merge-base with the default branch, and the report says so
no --head
HEAD
--pr <n>
gh pr view if you have it, then the GitHub REST API with GITHUB_TOKEN, then an error naming both. gh is never required. The base is the merge-base, which is the diff the PR page shows
--full
every count, every claim, every withheld sentence — the short report is the default
--json
the whole report, including the configuration every threshold came from
--offline
make no network call at all — the structural report, and it says so at the top
--no-source
make the calls, and send no file contents with them
--depth <n>
how far the impact walk may travel
doctor
everything the other commands assume, checked and named

Cutplane reads git objects locally and never downloads a diff. If --pr names a commit your clone does not have, it tells you the git fetch that gets it.

The drawn report

The architecture diff, the impact cascades and every claim under the thing it is about are at cutplane.dev, which runs this same engine on a server and gives each run a link you can send. There used to be a --html flag that rendered it into one self-contained file; it was retired once that page existed, because two renderers of one report are two pages that can disagree about the same change. Here, --json is the whole report and the thing to hand another program.

What leaves your machine

Source files are sent. Up to 12 changed files, whole, at most 156 KB in all: the highest-priority changed files of the components this change touched, so the report can say what the change does and not only what it touched. Structural metadata goes with them — paths, symbol names, component names, counts and relationships — and a path can itself name an internal service or a customer.

default
structure, plus the key files above
--no-source
structure only — what every version before 0.2 sent
--offline
nothing

--print-llm-payload prints the exact bytes of both, so none of the above has to be taken on trust.

Two calls are made, and OPENAI_API_KEY is required — from the environment or a .env at the repository root. One phrases the report's sentences and names its components, and sends no source at all. The other reads the key files and writes what the change does, at the top of the report.

Without a key, analyze stops and names the fix. --offline is how you ask for the structural report on purpose — every count, every claim and every citation, and a block at the top saying the report is structure only.

What Cutplane does not claim

  • It is not a linter and not a test runner.

    It says what changed and what that reaches. Whether the change is correct is your job.

  • Dynamic dispatch is invisible to it.

    getattr, DI containers, Django's app registry and duck typing are invisible to any static tool; nothing is claimed about them.

  • Line numbers are valid at one commit.

    Every citation carries the sha it was taken at.

  • The thresholds are tuned against a twelve-unit corpus, not proven.

    They are in --json under config, versioned, so a number that moved is traceable to the run that moved it.

Requirements

Node ≥ 20 and git. TypeScript and Python are parsed; nothing is installed, run or evaluated from the repository being analysed.