Skip to main content

sober

tests PyPI python deps

How often did your coding agent actually verify what it claimed?

sober audit on the author's 94 sessions

sober reads the session logs that Claude Code and Codex already keep on your machine, finds every sentence where the agent said tests pass / check passed / fixed / built / rendered / pushed, and checks whether a matching command really ran after its last code edit — and what that command's output said.

$ pip install sober-cli && sober audit

Verification rate: 88.1%   (119 verified / 135 decided claims)
Sessions: 93   Claims about this turn's work: 170

  verified         119   a matching check ran after the last code edit and its output agrees
  unverified        16   the agent edited code, then claimed success without running a check
  contradicted       0   the check it ran says otherwise
  could not check   35   evidence is off-transcript (subagents, background, piped exit codes, remote runs)

By agent / model:
  claude-code claude-opus-5-5     86%  (131 decided, 29 could not check)

Those are the author's own numbers, from 93 real sessions. A team that hand-labelled 357 "tests pass" claims from 150 Claude Code sessions found 80 with no run backing them; most were stale: tests passed, the agent edited again, then reported the old pass as current. Benchmarks say the same thing about ML tasks (57% of frontier-agent runs take a planted shortcut, and telling the agent not to barely helps). sober gives you your own number, then stops the pattern with two hooks.

  • Deterministic. Regex and transcript structure only. No LLM, no API key, nothing leaves your machine.
  • Precision first. Anything it cannot see is could not check, never unverified. The flagged set was tuned over six rounds of double-blind labelling until two independent raters agreed with every flag (details in gate/REPORT.md).
  • Reads the output, not just the exit code. pytest -q | tail -3 returns tail's exit code; sober reads the last N passed / N failed summary instead, and reports a contradicted claim when the summary disagrees with the sentence.

Install

pip install sober-cli      # Python ≥ 3.9, standard library only
sober audit                # Claude Code (~/.claude/projects) + Codex (~/.codex/sessions)
sober audit --agent claude-code --json findings.jsonl   # every claim with context
sober share                # writes ~/.sober/sober-card.svg (+ .png on macOS / with rsvg-convert)

Make it stop happening: sober guard

sober guard install --dry-run   # shows the hooks it would add to ~/.claude/settings.json
sober guard install
sober guard status | uninstall

Two Claude Code hooks, both tiny and deterministic:

Hook When What it does
Stop the agent is about to end its turn If the reply claims tests pass / fixed / pushed … and this turn shows no matching check after the last code edit, the turn is blocked once with the exact sentence and the missing step. The agent either runs the check and reports the real output, or rewrites the sentence as unverified.
PreToolUse (Bash) before a command runs A test or build command piped through tail/head without set -o pipefail loses its exit code. The call is denied with the one-line fix.

If your project already has a verify skill or script, the Stop hook recognises its run as evidence; it does not fight your existing workflow.

How a claim is judged

  1. Scope: one turn. Everything the agent did between your prompt and its reply.
  2. Last code edit. Edit/Write tools, or sed -i, cat > file, heredocs that write files. Edits to docs, logs, notes, memory, .env, temp dirs or .agent/ state do not count.
  3. Matching check after it. Tests for tests pass; lint/type/build/check tools for check passed; render tools for rendered; git push / kaggle … push for pushed; tests, checks or renders for fixed (a generic script run is not evidence that a fix works).
  4. Its output. The last summary line decides: 12 passed backs the claim, 2 failed contradicts it, fail 0 is a pass. A narrowed run (pytest -k, one file) cannot back "all tests pass".
  5. Everything invisible → could not check: subagents, background tasks, your own terminal, piped commands with no summary in the output, remote runs (CI, Kaggle), syntax-only checks.
  6. Not a claim: plans ("I'll run the tests"), questions, quotes, code blocks, sentences reporting a previous turn.

Forked sessions are de-duplicated so the same turn is counted once.

Precision

Every rule change was followed by a labelling round: the author and an independent Claude agent (fresh context, no access to the author's labels) each judged every flagged claim.

Round Flagged unverified Author precision Independent precision What was fixed next
1 38 56% 69% doc/log/memory edits counted as code edits; versioned hyperframes@x check missed
2 22 53% 52% variable paths, .agent/state.json, heredoc bodies; judge output by the last summary line
6 12 12/12 11/11 (+1 unsure) quote-aware multi-line splitting; writing heredocs never count as verification

Recall is not measured. sober would rather say could not check 35 times than flag one verified claim.

What it is not

  • Not a judge of correctness. A verified claim means the check ran after the edit and its output agreed with the sentence; it does not mean the code is right.
  • Not a leaderboard of models. The per-model table is your sessions only.
  • Not Anthropic's or OpenAI's. Independent, MIT, unaffiliated.

claude-guard-hooks and groundtruth block unbacked "done" claims with keyword matching; superpowers asks for verification in a skill (prompt-level). sober differs in reading command output, scoring your history across agents and models, and refusing to count what it cannot see.

中文说明见 README.zh-CN.md。

Metadata

Release files for sober-cli 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sober-cli 0.1.0
File Size Uploaded Provenance
sober_cli-0.1.0.tar.gz 29.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sober-cli 0.1.0
File Interpreter ABI Platform
sober_cli-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.1 kB

Release files / sober_cli-0.1.0.tar.gz

Download URL sober_cli-0.1.0.tar.gz
Size 29.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7c66890ab81550d59bc7a4d7d858db6e8a64a522f46a3a11fb0b0ef82cea156a
BLAKE2b-256 checksum
How to use checksums
99d362cf4c8021c6027379b4f10f119dce53a0bb93055b2d322c1aed101797e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.0

Release files / sober_cli-0.1.0-py3-none-any.whl

Download URL sober_cli-0.1.0-py3-none-any.whl
Size 25.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
86c6b2de8d9ac657079cc00b6f7503c2dfdad50c3a517031880c4f509f3701c4
BLAKE2b-256 checksum
How to use checksums
57396332eb4d347ff444a39182c1f620e60feb4694362c86bc93d606b7f2dbb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.0

Security for sober-cli 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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page