early accessOne flat price. Unlimited developers.

Code review that knows your codebase. A fraction of the per-seat price.

Lens learns your repo first. Then it reviews every pull request four ways at once, runs your app to reproduce bugs, and posts one review with only what matters.

runreviewexample · acme/api pull request 4127
$ lens review 4127
scope12 files · +418 −95
reuse2 found
simplify3 found
structure1 found
runtime1 reproduced
merge  7 findings → 3 posted

changes requestedRefunds can be paid twice on retry. The new formatter repeats one you already have. About 140 lines can go.

cautionruntimelib/billing/refund.ex:88

Reproduced. Calling refund/2 twice with the same key creates two refunds. Steps: seed one paid invoice, call twice, count rows.

warningreuselib/billing/invoice_formatter.ex:12

This repeats Billing.Format.money/2. Call that and delete this module.

warningsimplifylib/billing/strategy.ex:1

One implementation behind an interface. Inline it. 96 lines go.

Four reviewers ran at once. One review was posted.

the problem

Review bots are generic, loud and priced per head

The same bot reviews every company the same way. It does not know your code, so it comments on everything, and you pay for it per developer.

It does not know your code

A generic bot cannot tell you that you already have a helper for this, or that your team banned that pattern. Lens learns your repo and your rules before its first review.

personal, not generic

Too many comments

A bot that flags every style choice trains your team to ignore it. Lens posts blockers and things to fix before merge. Small stuff only appears when there is little else to say.

signal over volume

You pay per seat

Per-seat pricing charges you for headcount, not for work done. Lens is one flat price per runner. Hire ten more developers and the bill stays the same.

flat, not per head

getting started

Set up with one pull request

No dashboard to configure and no pipeline to write. Lens sets itself up and asks you to approve the result.

  1. 1

    Install the GitHub app

    Choose which repos Lens may see. It asks for read access to code and write access to reviews. Nothing else.

    about 2 minutes
  2. 2

    Merge the pull request it opens

    Lens reads the repo, starts your app, and opens a pull request with what it learned. Correct anything that is wrong, then merge.

    nothing is reviewed until you merge
  3. 3

    Add your AI key and pick models

    Paste an API key from your AI provider and choose a preset. Reviews are billed to that account, at your provider's price.

    stored encrypted, used only by your runner
pull requestexample · opened by lens-bot

Add Lens: what I learned about this repo

lens-bot wants to merge 1 commit into main

+ .lens/repo.md how to start the app, what exists, house rules
+ .lens/packages core
+ .lens/lenses/reuse.md
+ .lens/lenses/simplify.md
+ .lens/lenses/structure.md
+ .lens/lenses/runtime.md
✓ started the app on port 4000
✓ loaded the test data
✓ practised on your last 3 merged pull requests
To stop, delete the .lens folder or remove the app.

After that, your next pull request gets a review.

what is in that pull request

Lens learns your repo first

A reviewer who does not know your codebase can only give generic advice. Lens reads the repo once and writes down what it learned, in a file you can read and correct.

# .lens/repo.md · written by Lens, edited by you

## How to start the app
docker compose up -d db
mix setup && mix phx.server    # port 4000

## Test data
mix run priv/repo/seeds.exs     # tenant "acme"

## What already exists
- money formatting   Billing.Format
- permission checks  Auth.Policy
- background jobs    Oban, never Task.async

## House rules
- every query is scoped to one customer
- no new file over 1,000 lines

## Packages
core, security, migrations

How to start your app

Lens finds the commands, the ports and the test data, then proves it by starting the app. This is what lets the Runtime lens test a change.

What you already have

It maps your helpers and shared modules. This is how the Reuse lens knows that a new function repeats an old one.

Your rules

It reads your contributor guide, your linter settings and your past reviews, and turns them into rules it will check.

It keeps learning

Dismiss a finding with a reason and Lens proposes a change to the file. You approve it like any other pull request.

the four lenses

Four reviewers, each looking for one thing

One reviewer trying to catch everything catches little. Lens runs four at the same time. Each one has a single job and its own instructions.

lens 01 · up to 30 min

Reuse

Did you write something you already had? Is this easy to use wrong?

  • Code that repeats what exists elsewhere
  • Slow patterns, like a query inside a loop
  • Tests that check how, not what
warning This repeats Billing.Format.money/2. Call that and delete this module.
lens 02 · up to 30 min

Simplify

What can be deleted? It hunts for code written for a future that has not arrived.

  • An interface with one implementation
  • Settings nobody sets
  • Hand-written code the language already has
warning One implementation behind an interface. Inline it. 96 lines go.
lens 03 · up to 30 min

Structure

The strict one. It asks whether the whole change could be built in a simpler way.

  • Special cases scattered into unrelated code
  • Files growing past a thousand lines
  • A different design that removes whole branches
warning Three new if-branches in the checkout path. Move the rule into one policy module.
lens 04 · up to 30 min · the unusual one

Runtime

It does not read. It runs. Your app starts in a sandbox with test data, and the lens tries to break what changed.

  • Calls changed functions with empty, huge and wrong inputs
  • Signs in and clicks through the changed screens
  • Reports only what it reproduced, with the steps
caution Reproduced. refund/2 called twice with the same key creates two refunds.

how it runs

One run, start to finish

This is the real pipeline. Each run gets a fresh machine, and the four lenses work side by side. If one lens fails, the other three still report.

One review

All findings arrive as a single review with inline comments. Not a stream of separate bot messages.

It never approves

Lens can request changes or comment. It cannot approve. A person decides what merges.

Duplicates are merged

Two lenses often spot the same line. You see it once, with the clearer wording and the higher severity.

Blockers first

Anything that breaks correctness, data or security sets the review to REQUEST_CHANGES. Everything else is a comment.

packages

Switch on the checks you need

The four lenses are the base. Packages add checks for one subject each. Turn them on per repo.

Core review

ready

The four lenses: reuse, simplify, structure, runtime.

  • Repeated code
  • Needless complexity
  • Tangled structure
  • Bugs it can reproduce
Included in every review

Security

planned

The mistakes that turn into incidents.

  • Secrets in code
  • Missing permission checks
  • Data crossing customer boundaries
  • Unsafe input handling

Database changes

planned

Schema changes that lock tables or lose data.

  • Locks on large tables
  • Changes that cannot be rolled back
  • Missing indexes
  • Deploy order problems

Tests

planned

Whether the tests would catch a real break.

  • Changed code with no test
  • Tests that cannot fail
  • Tests tied to internals
  • Flaky patterns

API contracts

planned

Changes that break the people calling you.

  • Removed or renamed fields
  • Changed response shapes
  • Missing versioning
  • Undocumented endpoints

Performance

planned

Measured on the running app, not guessed.

  • Queries inside loops
  • Slow pages, timed
  • Large payloads
  • Work that should be queued

Accessibility

planned

Checked on the real screens.

  • Keyboard traps
  • Missing labels
  • Low contrast
  • Focus order

Dependencies

planned

What a new package brings with it.

  • Known vulnerabilities
  • Licence conflicts
  • Abandoned packages
  • A package for ten lines of code

Your house rules

planned

The rules only your team has, written by you.

  • Naming and layout
  • Banned patterns
  • Required reviewers' concerns
  • Anything in your team docs

Only Core review exists today. Pick the ones you want and we will build those first.

under the hood

The reviewer is 477 lines in your repo

No black box. Each lens is a plain text file of instructions, checked into your repository. If the review is wrong for your team, you change the file.

# .lens/lenses/simplify.md

# Lens: Simplify

Hunt complexity to delete. Analysis only; no fixes.

## Categories

- delete: dead code, unused flexibility,
  speculative features
- stdlib: hand-rolled behavior the language
  already provides
- yagni: abstraction with one implementation,
  configuration nobody sets
- shrink: same behavior in fewer lines

## Review Questions

- What can be deleted outright?
- What code exists only to support a
  hypothetical future case?

Change the reviewer with a pull request

Too strict about file length? Edit the line. The change is reviewed and versioned like any other code.

Add a fifth lens

Write one more text file for what your team cares about: accessibility, migrations, your own API rules. Add one line to the pipeline.

Pick the model per lens

Each lens can use a different model, so the expensive one only runs where it earns its cost. See the presets.

Turn packages on per repo

A payments service and a marketing site need different checks. Each repo lists the packages it uses, in the same folder.

hosted, but yours

We run it. You own it.

Self-hosting gives you control and a low bill, and costs you the upkeep. Lens keeps the first two and takes the upkeep.

Your reviewer is in your repo

Lenses, repo notes and packages are files in a .lens/ folder. Change them with a pull request.

Your own runner

One machine for your company only. Nothing shared. You choose the region.

Your own AI key

Reviews use your key and the models you pick. Your provider bills you. We add nothing on top.

Every run is open

Read the full log of any review: what it ran, what it found, what it used.

Leave any time

Take the same files and the same machine image to your own cloud. Nothing to rewrite.

models

Bring your own key. Pick your models.

Lens does not resell AI. You connect your own key, choose which model each lens uses, and your provider bills you directly.

1. Bring your key

Pick the ones you have a key for. Only Anthropic works today; tell us what you use and we add it next.

2. Choose how to spend it

.lens/modelsa file in your repo
reuseclaude-sonnet
simplifyclaude-haiku
structureclaude-opus
runtimeclaude-sonnet
mergeclaude-sonnet
# key: read from your runner, never from this file
Change one line to move a lens to another model.

No markup

You pay your provider's price for every token. Lens earns nothing from how much the model is used.

You see the usage

Every review shows what each lens used. If one lens costs too much, move it to a smaller model.

Your terms apply

Your code is sent under your own agreement with your provider, including any no-training or data-location terms you have.

safety

It can comment. It cannot push.

A reviewer should not be able to change what it reviews. Lens gets the smallest set of permissions that still lets it post a review, and they are written in a file you can read.

WhatAccessWhy
codereadto see the change
pull requestswriteto post the review
issuesreadto read the linked ticket
push, merge, settingsnone
A fresh machine for every runEach review starts from a clean image and is thrown away after. Nothing carries over between runs.
A key that lasts one runGitHub access is created for that run, with those permissions, and expires with it.
The internet is off by defaultOn cloud machines, the reviewer can only reach a short list of hosts you approve. Everything else is blocked.
Your code is not pooledYour runner handles your code only. It goes to that machine and to your AI provider, nowhere else.

case study: in parallel

We built Lens because we outgrew our review bot

This is our own story. The numbers are from our main repository.

We are a small team that ships a lot. AI agents write much of our code, so our main repo gets about 737 pull requests a month. That is around 25 a day, and they arrive in bursts.

We used CodeRabbit on the Team plan. It is a good product. It was not built for that volume.

So pull requests waited in line for a review, and the people and agents who wrote them waited too. We wanted a reviewer with no queue, and we wanted to decide which model reads our code.

737pull requests we opened in one month
3reviews per hour our plan allowed
“0 reviews are currently available.”From the bot, on one of our pull requests, 2026-09-18. It put our allowance at 3 reviews per hour.

We hit the limit

Three reviews an hour is fine for a team that opens a few pull requests a day. We open more than that before lunch.

Reviews came late

A review that arrives after you have moved on is a review nobody reads. We wanted it back while the change was still in our heads.

We wanted to own the model

New models arrive every few months. We wanted to pick ours, switch when a better one ships, and pay the provider directly.

what happened after we switched it on

35pull requests reviewed, of the last 100
79reviews posted, including re-reviews after fixes
43times it asked for changes before merge
0approvals. It is not allowed to give one.

2026-09-22 to 2026-09-27, one repository, read from GitHub on 2026-09-27. Both reviewers still run on the same pull requests, so we compare them every day.

pricing

One flat price. Not per developer.

You pay for a runner, the way you would pay for a build machine. Everyone on the team can use it.

hosted by us

One runner, one flat price

$99 per runner, per month

A runner is a machine that is only yours. It reviews about 1,000 pull requests a month. Add developers for free. Add a runner when you need more.

  • Unlimited developers and repos
  • Every lens, and every package as it ships
  • Free for 30 days
Get early access
what is not in that price

The AI model, on your own key

Lens uses your AI key. Your provider bills you for what each review uses, at their price. We add nothing on top, and you see the usage of every review. Choose your models.

  • No markup on tokens
  • Set a monthly limit
  • Choose a cheaper model for simple lenses

Want to run the machine too? Take the same files to your own cloud and pay for compute only.

Compare with paying per seat

per seat, per month$750
Lens, per month$99

questions

What people ask first

What if Lens cannot start my app?

Then it tells you what it tried and what failed, and you add the missing step to the repo notes. Until the app starts, the other three lenses still run.

How do I remove it?

Delete the .lens folder or remove the GitHub app. There is nothing else installed and nothing to migrate back.

How long does learning the repo take?

It happens once, before the first review. After that Lens only re-reads what changed.

How long does a review take?

The lenses run at the same time, so a review takes as long as the slowest one. Each lens stops after 30 minutes at most. Most finish much sooner.

Which AI model does it use?

The ones you pick, with your own key. Today that means Claude models from Anthropic. Other providers are planned; tell us which you use.

Can I use a model I host myself?

That is planned. Anything that speaks the common chat API will work, so the code never has to leave your network.

Will it fix the problems it finds?

No. Lens reports. Where the fix is obvious it attaches a suggestion you can accept with one click, but it never pushes to your branch.

Does it work with GitLab or Bitbucket?

Not yet. Today it posts to GitHub. Tell us where your code lives when you sign up.

Can I run it next to the bot I already have?

Yes. That is how we run it. Lens posts as its own reviewer and does not touch other reviews.

A reviewer that knows your code. One flat price.