Deterministic PR review for the AI era
The first line of defense against AI slop.
Agents write code faster — and cheaper — than anyone can review it. Generating a new function is now easier than understanding and refactoring the old one, so codebases only grow. Code has never been so cheap to write and so expensive to own: every line added is maintenance someone pays for later.
Talooner reads every pull request against the policy in your repo — rules.tln — and approves, blocks or routes it to the right person or team. Rules decide; a model is consulted only where a rule asks.
100%
Reproducible — same commit, same rules, same verdict
0 prompts
Rules decide. A model answers only when a rule asks
GitHub + GitLab
Check runs, sticky comments, approvals and routing
Integrations
Works with what you already use
Your forge, your CI, your model — Talooner is one more step, not a new stack.
Forges
CI
Models
The problem
Your agent wrote 2,000 lines before lunch.
Who's going to read them?
A pull request now costs a few cents to write — and still hours of someone else's time to check. Review is the bottleneck, and the place slop slips through. A human skims 3 of 47 files and types LGTM. An LLM reviewer writes a confident paragraph that changes every time you ask. Neither is a policy.
- Tests written for show. expect(true).to eq(true) turns CI green and proves nothing. Talooner has a rule for it.
- Quietly removed guards. A missing authorize! hides inside a 2,000-line diff. Talooner has a rule for it.
- Hallucinated dependencies. A gem or package nobody vetted — or that doesn't exist yet. Talooner has a rule for it.
- Code that contradicts its docs. The guide says “scoped to the entity”. The diff grants admin. Talooner has a rule for it.
- AI approving AI. The model that wrote the diff signs off on it. That's self-approval with extra steps. Talooner has a rule for it.
“Humans have to look at every single line that's being changed and remember to comment. And with the rate of pull requests that are coming in, it just becomes impossible.”
By the numbers
Code ships faster than anyone reads it.
90%
of PRs over 1,000 lines merge with zero review[2]
No approval, no change request, not a single comment. Up from 83% a year earlier — the bigger the diff, the less anyone reads it.
no reviewreviewed
+98%
PRs merged on teams with high AI adoption[4]
+91%
time spent in PR review[4]
+154%
average PR size[4]
An LLM approving its own code isn't a review. Even a team of one needs rules.
Solo or not, the agent that wrote the diff — or another prompt to the same model — will happily sign off on it. It reads the same context, shares the same blind spots, and answers differently every run. That's how slop gets an approval. You don't ask a linter for its opinion: you write the rule once and it holds on every commit. Decisions deserve the same.
- rubocop / eslint→ stylechecked on every commit
- tsc / sorbet→ typeschecked on every commit
- rules.tln→ decisionswho must approve, what blocks a merge
Someone else's time
Slop costs cents to write. Someone else pays to read it.
Generated pull requests and vulnerability reports look solid and sound confident — and describe bugs that aren't there. Producing one takes a couple of minutes. Disproving it takes hours of a real person's time, often a maintainer working unpaid on evenings and weekends[2].
In January 2026 curl, which half the internet depends on, shut down its bug bounty after a flood of AI-generated reports[1]. The same thing happens inside companies: one person generates a 2,000-line PR, and their teammates pay for it with their own time.
- of curl's bug bounty
- 6 years
- of curl's bug bounty
- paid to researchers
- $86,000
- paid to researchers
- real vulnerabilities fixed
- 78
- real vulnerabilities fixed
curl's bug bounty, ended because of AI slop. Sources: [1] The Register · [2] Habr
We support open source
Free for open-source projects. Unlimited rules.
Let rules triage the queue before a maintainer spends an evening on it: route big fork PRs, bounce PRs with no description, and keep the model off untrusted forks entirely.
rule "Large fork PRs wait for a maintainer" {
for records where type == "pr"
and attr "pr.is_fork" == true
and attr "pr.lines_changed" > 500
requires "review.maintainer"
do comment "pr" "Big fork PR: link an issue first."
}
rule "No description, no review" {
for records where type == "pr"
and attr "pr.is_fork" == true
and attr "pr.has_description" == false
block "merge"
do block "pr.merge"
do comment "pr" "Add a description and how you tested it."
}How it works
Rules decide the verdict. Not a model.
Four steps on every pull request, with one optional probabilistic hop that a rule has to ask for.
- 01
Extract facts
A short-lived runner reads the PR: changed files, size, author, owners, CI status, new dependencies.
pr.lines_changed = 2431 pr.new_dependencies = 1 pr.tests_passing = true
- 02
Evaluate rules
The tln engine runs your repo's rules.tln. Deterministic — most PRs never touch a model.
touches_auth_secrets ✓ small_change ✗
- 03
Ask a model — only if a rule asks
A typed question, a typed answer with calibrated confidence. It re-enters the engine as a fact, not prose.
llm.risk = "high" llm.risk_confidence = 0.93
- 04
Act on the forge
One check run, one sticky comment, approvals, blocks, assignees and review requests. Then it exits.
require security_team block pr.merge
Why not an AI review skill — or a second model?
Asking Claude to review Codex's PR, or adding a review skill to your agent, still leaves the decision with a model. Talooner keeps models where they're useful — answering one narrow, typed question a rule asks — and leaves the verdict to rules.
A skill is a prompt, not a gate
It's advice the agent may follow, skip or reinterpret. Nothing guarantees it ran, and nothing stops the merge when it's ignored.
A second model is a second opinion
Cross-model review swaps one guess for two. Models share training data and blind spots — and when they disagree, who decides?
Neither knows your organization
Who owns app/policies/, that migrations need a DBA, that SSO changes need security — that's policy, not something a model infers from a diff.
You can't test or audit a vibe
A prompt has no tln test, no reproducible verdict, no “blocked because rule X matched facts Y”. Just a fresh paragraph every push.
Policy as code
Security, ownership and sanity — written down once.
A few rules from a starter policy for a Rails monolith. Each one matches PR facts, declares a verdict and the actions to take. Versioned, diffable, reviewable — and tested.
- approve auto-approve when safe
- block request changes / block merge
- require route to a team
- nudge comment only
define "touches_auth_secrets" {
attr "pr.changed_files" contains "sso.rb"
or attr "pr.changed_files" contains "access_token"
or attr "pr.changed_files" contains "config/credentials"
or attr "pr.changed_files" contains ".env"
}
rule "Auth secrets & tokens need security" {
for records where type == "pr" and is "touches_auth_secrets"
requires "review.security_team"
do require "review.security_team"
do assign "pr" "@acme/security"
do comment "pr" "Touches SSO/token/secret config — security review required."
priority HIGH
}Anything touching SSO config, access tokens or credentials is routed to security — automatically.
talooner[bot]
commented on PR #482
Security review required
Touches SSO/token/secret config — security review required.
- Requested review from @acme/security
- Assigned @acme/security
- Merge waits for security approval
Observability
Know exactly what your policy is doing.
Every verdict, action and model call is a talooner_* Prometheus metric, with a Grafana dashboard in the box. Watch the auto-approval rate climb as you tune the rules.
Auto-approval rate
59.4%
▲ 4.2 pts vs prev 7d
Routed to a human
21.2%
▼ 1.1 pts vs prev 7d
Evaluation p50
0.34s
p99 2.8s · no model call
PRs evaluated
2,730
7-day total · 390/day
Verdict mix over time
sum by (verdict) rate(talooner_pr_evaluations_total)
- approve
- comment only
- require
- block
LLM reviews by result
increase(talooner_llm_reviews_total) · 7d
- cache_hit1,184
- match431
- mismatch176
- unclear58
- error9
Most model calls are cache hits — a re-run at the same commit is free and byte-identical.
Top repositories
topk(6, sum by (repo) increase(talooner_pr_evaluations_total))
| Repository | PRs | approve / block / other | Auto |
|---|---|---|---|
| acme/payments-api | 612 | 64% | |
| acme/web-app | 548 | 66% | |
| acme/infra | 381 | 52% | |
| acme/mobile | 237 | 69% | |
| acme/auth | 141 | 41% | |
| acme/docs | 118 | 88% |
Action mix
increase(talooner_pr_actions_total) · 7d
- comment1,240
- approve1,013
- assign486
- block274
- require192
The same dashboard, for your Grafana
Each pipeline job pushes its metrics to your Prometheus — one variable, TALOONER_METRICS_PUSH_URL.
Your data
Self-hosted: Talooner doesn't store any of your data.
Talooner runs on infrastructure you self-host, so your code, diffs and review history never leave infrastructure you control. The facts rules need live there and expire on the retention you set — we never see them.
Your platform, your servers
Run it as one step in your own pipeline, or on the orchestration platform you self-host — OpenTalon, OpenClaw, Hermes and more. Your code never touches our servers.
The runner keeps nothing
The CI job is a container that exits. Its forge token is minted per run, scoped to one repo, and dies with the job.
Your keys, your models
LLM credentials live only on your cluster and every token is billed to you. The runner never sees a model key.
One license check a day
The plugin confirms its license is still active — the key, a nonce and its version. Never code, repositories or PR data.
Try it free
Put a rulebook between your agents and production.
Get a license key in a minute — no call, no card. It works right away for 10 days while we look at your application, then we extend it. Open-source projects stay free.
- One onboard command drafts your first rules.tln with tests — from your terminal or your coding agent
- Advisory first: comments only until you choose to enforce
- GitHub or GitLab, cloud or self-hosted
- Metrics dashboard from day one
