v1.0.0  ·  Source-available  ·  Elastic License 2.0

Your team ships
faster than it
can review.

AI-assisted development moved the bottleneck to the pull request queue. CodeCapitan tells you which PRs are safe to approve unattended, and which ones genuinely need a human. The answer is an auditable, rule-by-rule verdict you can still defend a week later.

What teams do now

Nobody is reviewing forty PRs a day.

Assistants made writing code cheap. Reviewing it costs exactly what it always did. So the backlog gets dealt with one of three ways, and you already know which one your team picked. All three place the same bet by default rather than on purpose: that the code is fine.

  1. “We'll get to it this week.”

    Let the queue build

    PRs pile up waiting for someone with the context to spare. Branches drift, conflicts stack, and the review that eventually happens is a scroll to the bottom of a diff whose author has moved on twice since.

    What it costsEverything ships late, and the change nobody could find time to review still gets the least attention of all when it finally goes in.

  2. “LGTM 👍”

    Approve without really reading

    The queue stays clear because approvals get shallower. Forty PRs a day is roughly one every twelve minutes, so the diff gets skimmed for anything obviously alarming and waved through.

    What it costsYou keep the ceremony of review and lose the protection. Every approval on the repo now means nothing, including the ones somebody really did read.

  3. “Turn it off for now, we're blocked.”

    Switch required reviews off

    Branch protection comes off “temporarily” so the team can move. It is the honest version of the rubber stamp: at least nobody is pretending the code was looked at.

    What it costsWhatever lands, lands. And the day something goes wrong there's no record of who agreed to it or on what basis. The audit trail left with the requirement.

  4. “Is this one safe to merge?”

    Scan it before you interrupt anyone

    Point CodeCapitan at a pull request and it answers that question, with reasons, file and line. It tells you whether the PR is safe to approve unattended, or risky enough that a human should really look at it. It isn't a rubber stamp and it isn't a blocker.

    It also doesn't replace anything you already run. Your scanners, your review bots and your CI keep reporting exactly as they do now; CodeCapitan reads what they found, and whether the PR did anything about it.

    What you getThe bet becomes a decision you can show your working for: re-runnable, argue-able, and still defensible a week later to somebody who wasn't there.

Where it fits

It doesn't replace your tools. It reads them.

CodeCapitan answers one question: is this pull request safe to merge without a human? Everything else already in your pipeline is evidence for that answer. Keep all of it. The more signal reaching the PR, the better the call.

Not a SAST or DAST replacement
Semgrep, Snyk, Trivy, GitHub Advanced Security and GitGuardian go looking for vulnerabilities across your whole codebase, on their own schedule and in far more depth than anything reading a single diff could manage. Keep every one of them. CodeCapitan is answering a narrower question about one pull request, which is how much risk merging it adds, and although security problems do surface while it works, catching them is a side effect of that rather than the point of it.
Not a replacement for CodeRabbit or Sourcery
Review bots are there to comment on the code, which is a different job from deciding whether it can go in without you. CodeCapitan reads what they flagged on the pull request, then checks the one thing no review bot can check about itself: whether the author actually did anything about it. A thread quietly marked resolved on a line that was never touched is exactly the sort of thing it counts against the PR.
Not something you run while you work
This isn't a feedback loop. Your editor, your linters and your review bot are already telling you what to fix while you're writing, and CodeCapitan has nothing to add to that conversation. It is for the moment the pull request is finished and the only thing between it and main is somebody's approval. Run one scan then, and either merge on the strength of it or find out that this is a PR genuinely worth interrupting a colleague for.
Not a replacement for your pipeline
Your tests, your linters, the type-check, the coverage gate and whatever scanners you have wired into CI all feed straight into the verdict, so a failing required check makes a pull request dead on arrival while a failing advisory one is reason enough to send it to a human rather than decline it outright. Every check you switch off is a signal CodeCapitan no longer has.

How it decides

The wall doesn't care who's climbing.

Every scan runs in isolation against a single snapshot of the pull request, in a fixed order, with the same rules and the same weights every time. It doesn't care who opened the PR, how senior they are, or how much they disagree with the result. And every line of the report names the rule that produced it, that rule's weight, and the file and line it fired on.

11 22 33 44 55
  1. Stage 1

    Deterministic scans

    Secrets, tampered CODEOWNERS, trojan source, size gates, a red pipeline, plus a language pack for whatever the PR happens to touch.

    40+ rules · every PR · $0.00

  2. Stage 2

    Agent checks

    Fourteen groups of checks, each one skipped outright when the PR doesn't touch anything that group cares about.

    14 groups · 73 lenses · 291 sub-checks

  3. Stage 3

    Adjudication

    A council argues every finding: one advocate to suppress it, one to keep it, a judge to rule. False positives are a defect here.

    two advocates · one judge · every finding

  4. Stage 4

    Risk assessment

    Confidentiality, integrity, availability and privacy are each rated, then re-rated against each other into one whole-PR risk band.

    4 dimensions · one risk band

  5. Stage 5

    Verdict and actions

    Every result is scored into one verdict, CODEOWNERS resolves who would have to review it, and the report states exactly what it intends to do.

    one verdict · the right reviewers · a CI exit code

73 lenses  ·  291 sub-checks

What it looks for.

This is what CodeCapitan reads in one diff to work out how risky merging it is. Every lens declares its own sub-checks, so the report tells you which one tripped, not just which lens. Here's a slice of the catalogue.

Adversarial changes

The PR that tries to talk its way past the reviewer.

Most review tools assume the diff is arguing in good faith. This group assumes it isn't. It's the one group that never gets gated away, because the PRs worth catching are exactly the ones that look cheap to skip.

  • Instructions aimed at the reviewerText planted for an AI reviewer to obey, forged sign-offs, wording that tries to redefine the rules
  • Code hidden from reviewEncoded payloads decoded and run, a string assembled and executed, a minified blob passed off as hand-written source
  • New traffic to an outside hostFresh HTTP, socket or DNS calls leaving the service, especially carrying secrets or user data
  • Behaviour on a hidden triggerDestructive or auth-related code that only fires on a certain date, tenant, hostname or magic value
  • A description that doesn't match the diffA security-relevant change the write-up never mentions, or a high-impact edit buried in a large one
  • The guard removed with the thing it guardedA security test deleted alongside the change it covered, an assertion loosened, a snapshot rewritten to bless the new output

Injection & input

SQL built by concatenation, shell and eval with interpolated input, server-side requests to an attacker-controlled host, zip-slip, unescaped template output, regexes that backtrack catastrophically.

Authorization

An authz check quietly removed, a route that went from authenticated to public, an object resolved straight from a client-supplied id with no tenant scope, credentialed CORS reflecting any origin.

Secrets & crypto

Hardcoded keys and connection strings, MD5 and ECB, predictable RNG for tokens, certificate verification switched off, auth headers and card numbers landing in logs.

Correctness

Inverted conditions, off-by-ones, swapped arguments, swallowed exceptions, a lock held across a blocking call, a handle that isn't released on every path.

Change safety

Schema and code shipped in one deploy, a non-nullable column with no backfill, a dropped endpoint, a Terraform change that forces replacement or broadens an IAM trust policy.

Maintainability

Wrappers around a single caller, any-type escape hatches, renames left half-done, and tests that exercise behaviour without asserting anything.

Supply chain

Dependencies from non-canonical sources, install hooks, typo-squats, loosened pins, lockfile integrity mismatches, copyleft arriving without an SPDX id.

Docs & comments

Real customer names, live credentials or personal data in prose, instructions that contradict themselves, and comments that restate the code or narrate the edit instead of the intent.

Language packs

Gated on what the PR actually touches: Doctrine N+1s and missing migrations, floating promises and React hook deps, goroutine leaks, bare excepts, root Docker users, unguarded GraphQL resolvers.

Guarantees

Why the verdict can't be gamed.

A review tool is only worth running if it can't be talked out of its own answer. These seven properties are enforced by the engine itself and guarded by tests, not by anyone remembering to be careful.

The verdict is never the model's text

Rules emit findings. The verdict is computed from each rule's status and its declared severity, never from anything the model wrote. An adversarial prompt can't approve itself by asking the model to type "approved".

Config comes from the default branch only

.codecapitan.yml is read from the repo's default branch, never from the PR's head or base ref. A pull request can't weaken the policy that's judging it, and nobody can smuggle a permissive config in on a side branch.

Every rule judges the same snapshot

One fetch pulls the PR, its diff, checks, review threads and CODEOWNERS before a single rule runs. Nothing re-reads GitHub mid-scan, so two rules can never disagree about what the PR contained.

Findings can only point at lines the PR added

Prompts are told to stay inside the lines the PR added. The engine then post-filters every finding against the added-line set regardless. The backstop is the filter, not the prompt.

Every finding names a line

A finding carries the file, the line, the rule that raised it and that rule's weight. The report is the audit trail: hand it to someone who wasn't there and they can check the call themselves, or argue with it.

False positives are argued down, not shipped

Nothing reaches the report without surviving the council: advocate for suppressing, advocate for keeping, judge to rule. Noise is a defect, because the first tool anyone stops reading is the one that cries wolf.

The deterministic tier never short-circuits

Every rule runs even after a red. You get every reason a PR was declined in one report, the way a CI run gives you every failing job, not just the first one.

How your team uses it

Watch the scan stream in.

One instance runs for the whole team, so nobody installs anything and nobody has another tool to keep up with. When a pull request is finished and the only thing left between it and main is somebody's approval, comment /codecapitan review on it and wait for the reply, or open the dashboard and watch the scan happen.

In the dashboard the results stream back live, every check ticking from waiting to running to a result as the scan works, so a long one stays readable while it is still going and a failure points straight at the thing that tripped.

Come back green and Approve PR leaves a real review on GitHub, behind a second factor. Nothing merges on its own. CodeCapitan is read-only by design and never merges a pull request.

Authorization security
  • authz check removed or bypassedwaiting
  • route made public gating sensitive datawaiting
  • token stored outside auth boundarywaiting
  • signature / JWT / TLS verification disabledwaiting
scanning…

Self-hosting

Deploy it once for the team.

One deployment serves everybody, and it is yours: your infrastructure, your GitHub token, your policy in the repo. The whole test suite runs keyless against fixtures, so you can satisfy yourself it does what it says before it ever touches a real pull request.

Set up
cp .env.example .env
make dev

make invoke
→ {"statusCode": 200, "body": "ok"}
Turn it on for a repo
# .codecapitan.yml, on the default branch
version: 1
enabled: true
amber_threshold: 5

triggers:
  # the prefix a comment has to start with
  on_comment: ["/codecapitan"]

gates:
  required_checks: ["build", "tests"]
Add a rule of your own
# the same file, further down
custom_rules:
  - id: no-active-record-in-controllers
    severity: amber
    weight: 4
    type: prompt
    paths_include: ["app/Controllers/**"]
    prompt: "Flag Active Record calls inside
      controller methods."

Yours to run

Source-available under Elastic License 2.0.

Use it, copy it, modify it, self-host it. That includes commercial use inside your own organisation. You may not offer CodeCapitan to third parties as a hosted or managed service, and you may not alter, remove or obscure the licensing and copyright notices.

  • Not a merge bot. The CLI is read-only and never merges.
  • Not a webhook listener. The webhook ingress is parked; scans are driven by you.
  • Not a replacement for the tools it reads. It's the layer above them.