Prove the bug, don't just guess it.

A user reports a bug: I couldn't save, I tried three times. reprobe gathers what production saw, read-only. Your coding agent finds the cause, cites evidence for every claim, and writes a test that fails on the code you deployed.

npx reprobe init

Free and MIT licensed. No server, no account, no hosted model. It runs on your machine with Claude Code or Codex.

~/.reprobe/cases/app/2026-10-14-a71c3e
Complaint

“I couldn't save, I tried three times.”

Evidence
  • query:3b7e10c9a2Drafts saved by u_7f2 since 09:00: 0 rows
  • logs:…:9f04d2b6e1POST /drafts 409, stale key from an earlier draft, 3 times
  • sentry:api:API-4K2UniqueViolation on drafts_idem_key
Root cause

Every attempt resends a stale idempotency key from an earlier draft, so each is rejected as a duplicate. No new draft is saved. query:3b7e10c9a2 sentry:api:API-4K2

Replay
  • e4b1907deployedFAILexpected 1 draft, got 0
  • 5d03c2athe fixPASS

Most bug reports end in a guess.

A user says something broke. You open the database, the traces, the logs and Sentry in separate tabs, and piece together a story that sounds right. You ship a fix. Whether it worked, you learn from the next complaint.

reprobe replaces the guess with a test. When the test fails on the code your users ran and passes on your fix, the cause is proven, not just plausible.

  1. A user reports a bug“I couldn't save.”
  2. Five tabs openDatabase, traces, logs, Sentry, code
  3. A story that sounds rightNo test, nothing cited
  4. Ship a fixAnd hope

For engineers who get bug reports from real users.

You run a production app, maybe with AI features, and the evidence for one bug is spread across several systems. You already work with a coding agent. reprobe gives that agent the evidence and a way to prove its answer.

A good fit if you

  • Get bug reports from users, not only from alerts.
  • Keep evidence in Postgres, Langfuse or LangSmith, Sentry, or logs. Every source is optional.
  • Already use Claude Code or Codex in your repo.
  • Want a failing test before you call a bug fixed.

Not a fit yet if you

  • Can't get read access to production data from your machine.
  • Want a hosted dashboard, or triage with no engineer in the loop.
  • Need it to reply to users or file tickets. reprobe posts nothing.

The CLI does the parts that must be exact. Your agent does the thinking.

You run one command. reprobe gathers the evidence, then starts Claude Code or Codex in your repo with the case and a playbook, like npx t3 triage. Everything that must be exact is plain code, not a model's judgment: gathering, read-only access, redaction, citation checks and replays at old commits.

  1. 1
    reprobe

    Gather the evidence

    Rows, agent traces, logs and Sentry issues for that user and time window, from Postgres, Langfuse, LangSmith, Sentry, Railway, any log CLI or log files. Each item gets a stable id. Missing sources are listed, not guessed around.

    npx reprobe "<complaint>" --since 6hWrites evidence.json and CASE.md
  2. 2
    your agent

    Investigate

    Reads the case and the code at the deployed commit, then digs further through reprobe's read-only tools. Each answer becomes new evidence it can cite.

    reprobe query <case> "SELECT …"Adds evidence with new ids
  3. 3
    your agent

    Write the replay

    The smallest test of the invariant the bug broke, in your own test framework, filled with the real shapes from the evidence.

    <case>/replay.jsonWrites a test file and replay.json
  4. 4
    reprobe

    Run it at each commit

    Each run happens in a detached worktree. You want FAIL on the deployed commit and PASS on the fix.

    reprobe verify <case> <deployed-sha> <fix-sha>FAIL, PASS or BROKEN; NOT-APPLICABLE if required files are missing
  5. 5
    reprobe

    Check every claim

    The agent writes <case>/diagnosis.json. reprobe drops any claim that cites nothing, or cites an id that isn't in the evidence, and renders the rest.

    reprobe report <case>Reads diagnosis.json, writes report.md

Your first case

Run these in your repo. The config stores env var names, never secret values.

cd your-repo
npx reprobe init     # finds your sources, writes .reprobe/config.json
npx reprobe doctor   # checks configured sources and tools
npx reprobe "users can't save since this morning" --since 6h

One test, run across your history.

An explanation can sound right and still be wrong. A test that fails on the commit your users ran and passes on the fix settles it. This is a real incident with the names taken out: the first fix shipped, and the bug stayed.

  1. FAIL

    Deployed

    e4b1907

    The code users ran. The bug reproduces.

  2. FAIL

    Before fix 1

    c02f6d1

    Still fails, as expected.

  3. FAIL

    Fix 1, shipped

    7a9e33b

    Still fails. This is why users on the next build kept seeing the bug.

  4. PASS

    Fix 2

    5d03c2a

    Passes. The real fix.

FAIL
The test reached its assertion and the assertion failed. The bug reproduces.
PASS
The test reached its assertion and it held.
BROKEN
No valid assertion verdict. A crash or invalid replay output can't prove the bug reproduces.

Every query is read-only, three times over.

reprobe reads the same production your users hit. Its database path wraps each query in three read-only layers, and stops if the server doesn't confirm read-only mode.

Read-only transactionBEGIN READ ONLY … ROLLBACK
Read-only sessiondefault_transaction_read_only=on
SELECT/WITH guardanything else is refused
SELECT id, created_at FROM drafts WHERE …

Give it a read-only database role as well. The guard can't tell whether a function in your schema has side effects.

Replays stay out of your checkout
Each runs in a detached git worktree, as a known test runner, without a shell. Keep production credentials out of its environment, as you would for any test run.
Redaction is on, and pattern-based
Phones, emails, tokens, keys and signed URLs are removed before a case is written. An opaque token can slip through, so read a case before you share it.
Nothing is posted
No writes to Sentry, GitHub, Langfuse or your users. The agent is told to treat evidence as data, never as instructions.
Your code is trusted code
Configured commands, your pack and replay tests run as you, with your permissions, like your test suite. Headless mode limits which tools the agent can call; it is not an OS sandbox.

Before you try it

What does it cost?

Nothing. reprobe is MIT licensed and has no server. The investigation runs on the Claude Code or Codex you already use, so the only cost is your agent's usage.

Does my data leave my machine?

reprobe reads your configured sources directly, with no reprobe backend. Evidence goes to the agent you choose, as it does when you paste logs into it today. Cases are written to ~/.reprobe/cases, outside your repo.

What if I don't use Postgres or Railway?

Every source is optional. Logs can come from any CLI that prints lines (fly, vercel, kubectl, docker) or from files. Without a database, reprobe still works from traces, logs and Sentry.

What is a pack?

One TypeScript file that teaches reprobe your product: how to find the user a complaint is about, which rows matter, your known failure signatures, and how to build an old commit. Every hook is optional.

Which agents work?

Claude Code and Codex start automatically. With neither installed, reprobe prints one line to paste into any coding agent.