Prebuttal
Answer Reviewer 2 before Reviewer 2 exists.
Purpose-built for ML conferences: real NeurIPS / ICLR / ICML / ARR review-form output, three reviewers running in fully independent contexts (optionally cross-model), and a built-in pipeline to measure its scores against real OpenReview ratings.
Prebuttal is a pre-submission stress test for your paper: it sends your submission through three isolated AI reviewers with different temperaments plus an area chair, and hands you a conference-format review report — scores, disagreement, weaknesses with citations to your own tables — before the real Reviewers 1–3 see it. See a synthetic sample: report · share page — or what a deliberately flawed (fictional) paper gets: 1/10 report.
Why not just paste the paper into ChatGPT?
That is the main competitor. It loses, four ways:
| Paste into ChatGPT | Prebuttal |
|---|---|
| One conversation role-playing three reviewers → persona collapse into a single bland compromise opinion | Three reviewers in fully independent contexts (separate calls/processes), genuinely different verdicts + measured disagreement |
| Long papers get skimmed; tables are flattened into prose | Ingestion pipeline: cell-by-cell table extraction (LaTeX tabular parsing, PDF table detection, caption fallback) — reviewers can point at Table 3, column 4 |
| Output is free-form chat text | Real conference review forms: NeurIPS 1–6, ICLR 1–10, ICML 1–10, ARR Soundness/Excitement/Overall — with official scale anchors |
| Scores are vibes | Fixed seeds, recorded backends/models per reviewer, and a calibration script to measure scores against real OpenReview ratings (published results pending) |
Quickstart
pip install prebuttal
prebuttal run paper.pdf --venue iclr
prebuttal run https://arxiv.org/abs/2510.12345 --venue neurips
prebuttal run ./latex-src/ --venue acl
Prefer an isolated install for command-line tools? pipx install prebuttal
or uv tool install prebuttal work the same way (or uvx prebuttal ... to
run without installing). Requires Python 3.11+.
The first run costs zero setup if you already have a subscription CLI or
Ollama — Prebuttal auto-detects the cheapest path at startup and prints what it
chose (prebuttal backends to inspect):
| Backend | Auth | Notes |
|---|---|---|
agent-claude (claude -p) |
your Claude subscription, zero API key | preferred reviewer |
agent-codex (codex exec) |
your Codex subscription, zero API key | gives cross-model reviews together with claude; runs locked down, ignoring ~/.codex/config.toml (see SECURITY.md) |
api-gemini |
GEMINI_API_KEY | free tier — the cheapest "first key" path |
api-openai / api-anthropic |
OPENAI_API_KEY / ANTHROPIC_API_KEY | BYO key |
api-openrouter |
OPENROUTER_API_KEY | one key, hundreds of models — :free ids cost nothing (default is one); prices shown live in prebuttal models |
ollama |
none | local & private — unpublished papers never leave your machine (with the default localhost host) |
relay |
none | file protocol: prompts spool to disk and you, your agent's subagents, or any system write the answers — zero key, explicit only (--backend relay; never picked by auto) |
Unpublished manuscript? The text is sent to the backend's provider, and
what happens to it there is that provider's privacy policy, not ours — see
Privacy & data custody. For local-only review use
ollama or relay.
⚠️ Free tiers are usually paid for with your data. Free API tiers (the Gemini free tier, OpenRouter
:freemodels and their upstream providers) may let the provider log, review or train on what you send. They are fine for published papers and trying the tool out — for an unpublished manuscript, check the provider's current terms, use a paid tier, or stay local.
Useful flags:
prebuttal run paper.pdf --venue neurips --dry-run # cost + plan preview, calls nothing
prebuttal run paper.pdf --venue iclr --json out.json --share # machine output + share page
prebuttal run paper.pdf --seed 42 # reproducible
prebuttal run paper.pdf -y # skip the plan confirmation
In auto mode on a terminal, Prebuttal shows the review plan before calling
anything — press Enter to run, e to re-pick each reviewer's persona, backend
and model via numbered menus, or n to abort. CI and pipes get the plan
printed and proceed automatically; fully-explicit configs never prompt.
prebuttal models lists every backend's actually-available models (live API
scan + installed Ollama models + claude aliases) with the current default
marked — pick one and set model = "..." per reviewer in prebuttal.toml.
Built-in defaults are mid-tier models current at release time and change
between versions — providers retire model ids quickly, so if a default stops
working, upgrade prebuttal or pin a model yourself.
The reviewers
| id | Persona | Behavior |
|---|---|---|
| R1 | senior_kind |
senior, constructive; core contribution + main concerns, grounded |
| R2 | adversarial |
Reviewer 2 in the flesh: motivation, baselines, novelty, overclaiming |
| R3 | detail_obsessive |
reads every table cell; statistics, ablations, reproducibility |
| AC | area_chair |
meta-review, adjudicates disagreement, estimates the final rating |
Every persona enforces the same protocol: cite the evidence (section,
table, number) or the point doesn't count; use the full scale; JSON-only
output. There is also an easter-egg roast persona (persona = "paper_roast")
for when you need the truth fast.
Personas live in prebuttal/personas/ and venue forms in
prebuttal/venues/forms/ — plain text files, PRs
welcome (scale wording drifts every year; keep it current).
Configuration
prebuttal init writes a commented prebuttal.toml. Per-reviewer backends,
models and temperatures:
[default]
venue = "iclr"
seed = 42
[[reviewer]]
id = "R1"
persona = "senior_kind"
backend = "agent-claude" # claude -p, subscription auth
temperature = 0.4
[[reviewer]]
id = "R2"
persona = "adversarial"
backend = "agent-codex" # codex exec, subscription auth
model = "gpt-5.1" # optional: forwarded as --model (agent CLIs too)
temperature = 0.7
[[reviewer]]
id = "R3"
persona = "detail_obsessive"
backend = "api-gemini" # free tier; default model gemini-3.5-flash-lite
temperature = 0.5
[ac]
persona = "area_chair"
backend = "agent-claude"
Calibration (honesty, not prophecy)
Scores are meaningless unless measured. The calibration pipeline runs Prebuttal on papers that already have real OpenReview reviews and plots predicted vs true mean ratings:
The script lives in the repository (it is not part of the pip package), so run it from a clone:
git clone https://github.com/GuoYuKai-SaMuEl/prebuttal && cd prebuttal
pip install -e ".[calibration]"
python scripts/calibration/calibrate.py \
--venue-id ICLR.cc/2024/Conference --venue iclr -n 20 --out-dir calib_out
Output: scatter plot + MAE + correlation. No calibration results are published yet — until they are, treat every score as uncalibrated. Once published, the claim they support is narrow and deliberate: this tool was measured — unlike role-play prompts. It is not a claim that it predicts your score; real reviewers disagree with each other by more than this tool's error. Disagreement (σ) is reported with every aggregate for exactly that reason.
Run history & revision diffing
Every run is archived automatically (best-effort, never blocks a review) under
~/.prebuttal/ — reports, JSON, and the resolved config (backends, models,
seeds) for exact reproduction:
prebuttal runs # list archived runs
prebuttal show <run-id-prefix> # re-read a report (--json for the data)
prebuttal diff <old> <new> # ratings A→B + weakness movement
diff is the revision loop: fix what the reviewers flagged, re-run with the
same --seed, and see which weaknesses went away, persisted, or appeared.
Basic usage is unchanged — archiving is silent, --no-save opts out.
Skill package
skills/prebuttal/SKILL.md teaches any agent to
drive the CLI and interpret the JSON — including relay mode (the reviewers are
the agent's own subagents) and the runs/diff revision loop. The skill file
is explicit about the one rule that matters: the agent must run the CLI,
never role-play the reviewers itself.
When the CLI detects it is running inside a coding agent (currently Claude
Code and Gemini CLI), prebuttal run and prebuttal backends print a one-line
hint pointing at relay mode. An agent environment that should always use its
own subagents can pin it once with PREBUTTAL_BACKEND=relay. Relay is never
chosen automatically: the CLI has to run in the background while the agent
answers the requests, or both sides wait on each other.
Install it into your agent's skills directory — for Claude Code:
mkdir -p ~/.claude/skills/prebuttal && curl -fsSL -o ~/.claude/skills/prebuttal/SKILL.md \
https://raw.githubusercontent.com/GuoYuKai-SaMuEl/prebuttal/main/skills/prebuttal/SKILL.md
# or, from a clone: cp -r skills/prebuttal ~/.claude/skills/
Other agents (ZCode, Codex, …): copy or symlink skills/prebuttal/ wherever
your agent discovers skills (see its docs), or reference the file from your
AGENTS.md / system prompt.
Reference
Environment variables
API keys — two ways, pick either:
prebuttal key set gemini # quick setup: hidden prompt, stored for next time
# or the classic way: set GEMINI_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY yourself
Stored keys live in ~/.prebuttal/keys.env (user-only permissions, like
~/.aws/credentials); real environment variables always take precedence, so
CI setups are unaffected. prebuttal key status shows what's set (masked),
prebuttal key unset <name> removes one.
| Variable | Purpose |
|---|---|
OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY (or GOOGLE_API_KEY) / OPENROUTER_API_KEY |
enable the matching API backend |
OPENAI_BASE_URL |
point api-openai at an OpenAI-compatible proxy |
PREBUTTAL_OPENAI_MODEL / PREBUTTAL_ANTHROPIC_MODEL / PREBUTTAL_GEMINI_MODEL / PREBUTTAL_OPENROUTER_MODEL |
override each backend's default model |
PREBUTTAL_OLLAMA_HOST (or OLLAMA_HOST) |
Ollama base URL (default http://localhost:11434) |
PREBUTTAL_BACKEND |
force one backend for every reviewer + the AC (e.g. relay); --backend still wins, prebuttal.toml loses |
PREBUTTAL_HOME |
run-history and key storage location (default ~/.prebuttal) |
API keys are only read from the environment or keys.env — never written to
reports, JSON, or share pages.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 2 | bad usage / config error / paper not found / unknown run id |
| 3 | no review backend available |
| 4 | partial failure (some reviewers or the AC failed; report still written) |
| 5 | every reviewer failed |
| 130 | interrupted (Ctrl+C) |
Comparison
What Prebuttal provides, next to the common alternatives (by category — check any specific tool's own docs for what it supports):
| Approach | Form | Venue forms | Calibration | Cross-model | Tables in-pipeline |
|---|---|---|---|---|---|
| Prebuttal | CLI + skill | NeurIPS / ICLR / ICML / ARR (editable plain text) | OpenReview script (scatter + MAE; results pending) | claude × codex × API × ollama | cell-by-cell |
| generic "review my paper" agent skills / prompts | agent skill | varies | rarely | single model | via the host model |
| multi-agent peer-review research frameworks | research code | study-specific | study-specific | sometimes | rarely |
| paste into a chatbot | chat | ✗ | ✗ | ✗ | ✗ |
How it works
PDF / LaTeX dir / arXiv link
└─ ingestion: sections, cell-accurate tables, figure captions, refs
└─ reviewer pack (budget-aware; tables are never truncated)
├─ R1 senior_kind ──┐ three independent contexts,
├─ R2 adversarial ──┤ parallel fan-out, venue form + JSON schema
├─ R3 detail_obsessive ─┤
└─ AC area chair ◄──┘ meta-review + estimated rating + disagreement
└─ Markdown report · --json · --share page
Orchestration lives in the CLI, not the host agent — the same pipeline runs from a terminal, from inside any coding agent, or in CI.
Roadmap & versioning
Versioning policy while pre-1.0: patch releases (0.1.1, 0.1.2, …) are fixes and small additions; minor releases (0.2, 0.3, …) are substantial new features; 1.0 only once the interface is battle-tested.
Tentative — priorities shift with usage and feedback. Short-term the focus is hardening the core on real papers, not adding features:
- v0.1 (current, pre-release) — core: ingestion pipeline, real venue forms, 3 independent reviewers + AC, every backend (agent CLIs / APIs / Ollama / relay), reports + JSON + share page, calibration script
- Now (v0.1.x) — polish from real-usage findings: table & ingestion edge cases (complex PDF tables), calibration scatter plot + honest per-model calibration notes, provider-reliability UX (free-pool reality, retry transparency), relay UX
- Next (v0.2+) — more venues, community personas, OpenReview submission integration, and a browser-only web quick-scan (GitHub Pages: drag-drop a PDF + your own OpenRouter/Gemini key — no server, we stay a non-custodian); then the rebuttal workbench (reviews → point-by-point response letter) and "CI for papers" (GitHub Action: \ref/\label checks, citation sanity)
- Eventually — the calibration script becomes a public benchmark / leaderboard: tools depreciate, benchmarks appreciate.
Develop
git clone https://github.com/GuoYuKai-SaMuEl/prebuttal && cd prebuttal
python -m venv .venv && .venv/Scripts/pip install -e ".[dev]" # Windows
.venv/bin/pip install -e ".[dev]" # macOS/Linux
pytest -q
Contributions welcome — the easiest ones are venue forms, personas, and backends; see CONTRIBUTING.md for the three-step guide. Also read CHANGELOG.md, SECURITY.md, and our Code of Conduct.
Honesty & policy
- Prebuttal labels every review with the backend and model that produced it.
- It reports score disagreement, always. High σ is information.
- It is a stress test, not a predictor — the report footer says so, every time.
- Mind conference policies: with NeurIPS 2026 running an official AI-assisted reviewing experiment, the etiquette is clear — AI to prepare your own paper is yours to decide; AI to review others' papers must follow each venue's disclosure rules.
Privacy & data custody
- Your paper's text goes to whatever backend you configure. With API or agent-CLI backends the manuscript is transmitted to that provider — and OpenRouter further routes each request to a third-party upstream provider. What happens to the text there (retention, training use, human review) is governed solely by each provider's terms and privacy policy, not by Prebuttal.
- Prebuttal is an integration layer, not a data custodian. This project operates no models and runs no servers; we never see your paper. For unpublished results, check the backend provider's data-use terms before sending — provider-side handling of your data is the provider's responsibility, not this project's.
- Free tiers deserve extra care: free API tiers (e.g. Gemini's free
tier, OpenRouter
:freemodels) may allow logging or training on inputs; paid tiers usually don't. Read the terms before sending unpublished work. - Local-only is a first-class path:
ollamanever sends text off your machine (as long asPREBUTTAL_OLLAMA_HOST/OLLAMA_HOSTpoint at localhost — a remote Ollama server receives the paper like any API), andrelayleaves who answers entirely to you. - What Prebuttal itself stores stays on your disk: run history (pack
text, raw outputs, resolved config) under
~/.prebuttal/runs/and keys in~/.prebuttal/keys.env(user-only). No telemetry. Note reports and share pages contain excerpts of your paper — sharing them publishes those excerpts.
License & trademarks
Prebuttal is an independent project, not affiliated with or endorsed by NeurIPS, ICLR, ICML, ACL/ARR or any model provider. Venue names are used only to describe which review form a report follows; the forms are paraphrased summaries of the public reviewer guidelines.
MIT
Metadata
Release files for prebuttal 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| prebuttal-0.1.0.tar.gz | 291.4 kB | With provenance | Details for prebuttal-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| prebuttal-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for prebuttal-0.1.0-py3-none-any.whl |
Total release size: 377.5 kB
Release files / prebuttal-0.1.0.tar.gz
| Download URL | prebuttal-0.1.0.tar.gz |
|---|---|
| Size | 291.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e4463082ec704adf2351a344e4aeb6502de7a2ea687b4b5e676fcb591a4579c4
|
|
BLAKE2b-256 checksum How to use checksums |
4b0c454b88a585c48615268ba00ea43c73ac658645613eb2133c0934052007af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logRelease files / prebuttal-0.1.0-py3-none-any.whl
| Download URL | prebuttal-0.1.0-py3-none-any.whl |
|---|---|
| Size | 86.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
faaa3bea73beebe140d9528cc64c5ee8c6124b1e8b8c55f955cdd01773fc957a
|
|
BLAKE2b-256 checksum How to use checksums |
f54a343a29be4a93ded23f08375d35c28842b6db857bac7c2d22ecf83c800953
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logSecurity for prebuttal 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for prebuttal-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.