xout
X out the AI behavior you never want again.
Quickstart · Every rule proves itself · The map · Commands · Why trust it
Read in: English · 한국어 · Live explanation
Your coding agent shows two concrete ways it could behave. You X out the wrong one. Two minutes and 15 X's later, the surviving choices are compiled into 8 local rules that Claude Code loads from CLAUDE.md.
uvx xout --lang en
That's it. The whole session runs right in your terminal. X things out for about 2 minutes. Your agent gets 8 rules.
Nothing above is staged - the recorder photographs a live session, so every pair and rule on screen is the engine's real output.
No cloud. No telemetry. No LLM calls. One-line rollback.
v1.0.1 · Python 3.10–3.14 · MIT · zero third-party runtime packages
Other install paths (pip, venv)
pip install xout
xout
Or fully isolated:
python3 -m venv .venv
.venv/bin/python -m pip install xout
.venv/bin/xout
Upgrading from Popper 1.x? Just run xout once: your data in ~/.claude/popper/ moves to ~/.claude/xout/, and the owned import line is updated only when xout can prove it wrote it.
How it works
-
You X out the behavior you hate, across three real scenes: a routine bugfix, a new feature, and a risky production migration. Each pair shows two concrete agent behaviors - ask first vs act first, standard library vs install-a-package, rehearse the migration vs trust a re-read.
-
xout compiles the survivors into 8 executable rules, written atomically under
~/.claude/xout/with evidence and provenance. And when your X's diverge between routine and irreversible work, the rule compiles with that condition attached:Write a short plan first, then proceed immediately. However, for hard-to-reverse work like deletes, pushes, deploys, and migrations, always get approval before executing.
That condition is not a template. It exists because you X'd differently in the migration scene. No interview-based tool can produce it.
-
You apply with one keystroke. The completion screen asks "apply now?" - saying yes adds exactly one owned
@importline to~/.claude/CLAUDE.md.xout undoremoves only that line.
Repeat the request that used to annoy you in a fresh Claude Code session and watch the rule hold. When it ever feels stale, xout again.
Every rule can prove itself
xout why traces any rule back to the exact X's that created it:
$ xout why autonomy --lang en
[Autonomy]
rule: Write a short plan first, then proceed immediately. However, ... get approval before executing.
state: discriminated / source: your X
evidence:
- X'd ask_first in the routine-work scene (scn-bugfix) (session a3f2c9d1)
- X'd act_then_report in the hard-to-reverse-work scene (scn-risky) (session a3f2c9d1)
A rule you can't trace is a rule you can't trust. Every xout rule carries its receipts.
Sessions run in English with
--lang en(pairs, rules, and screen text); the default without the flag is Korean. The event ledger is language-neutral either way.
What you get
After the fifteenth X, three files land under ~/.claude/xout/:
| File | What it is |
|---|---|
XOUT.md |
8 executable rule lines for Claude Code |
manifest.json |
Rule value, confidence label, source, and content hashes |
settings.xout.json |
A reviewable settings proposal |
Rules you confirmed by X'ing are labeled confirmed; defaults xout guessed without asking you are honestly labeled guessed and queued for a quick re-pick. Nothing is ever activated without your explicit yes.
(Popper 1.x landed the same files as POPPER.md and settings.popper.json under ~/.claude/popper/; xout migrates them automatically on first run.)
The map
Eight axes, measured across three scenes. Five axes are measured in both contexts, so they can fork on the routine/irreversible boundary - with evidence.
| Axis | Routine scenes | Irreversible scene | Can fork |
|---|---|---|---|
| Autonomy | bugfix | migration | yes |
| Error behavior | bugfix | migration | yes |
| Verification before done | feature | migration | yes |
| Dependency policy | feature | migration | yes |
| Commit policy | feature | migration | yes |
| Scope adherence | bugfix + feature | - | cross-checked |
| Test discipline | bugfix + feature | - | cross-checked |
| Comments and docs | bugfix | - | style axis |
These eight axes weren't invented in a vacuum, and neither were the defaults. We surveyed 100+ high-star (10k-240k+) prompt and agent projects - shipped system prompts of codex/gemini-cli/Devin, the AGENTS.md files of rust/node/pytorch/transformers, community rules collections - and kept receipts: verbatim quotes, verified star counts, per-axis tallies, all in docs/mined-prior.md. Six of eight defaults matched the field's mode; two didn't and were corrected. And your own environment is a source too: xout mine reads the rule files you already have, with file:line receipts.
One more pair
You already know how this works. Two behaviors, one X:
(1)
You write CLAUDE.md from memory. The rules have no provenance, apply one-size-fits-all to a bugfix and a production migration alike, and drift silently until the agent annoys you again.(2) You cross out behaviors you have actually seen and hated. Every rule traces to your X's, forks on the routine/irreversible boundary only where your X's diverged, rolls back by one receipt-proofed line, and gets re-struck in two minutes when it goes stale.
That X is the whole product.
Commands
| Command | What it does | Writes to | Consent |
|---|---|---|---|
xout |
Start (or automatically resume) a session | own dir only | - |
xout why [axis] |
Trace a rule back to the X's that created it | nothing | - |
xout status |
Show your 8 rules and whether they are active | nothing | - |
xout undo |
Remove the one import line xout owns - full rollback | one owned line | - |
xout enable --grant |
Activate: add one owned @import line |
one owned line | explicit |
xout mine [paths] |
Read your existing CLAUDE.md/AGENTS.md/.cursorrules into axis observations, with file:line receipts | nothing | - |
xout pair / xout strike |
Headless JSON session for agents and scripts | own dir only | - |
Why you can trust it
- Local only. No LLM calls, no telemetry, no cookies, no network during a session.
- Crash-safe. Append-only ledger with atomic writes: interrupt anywhere, resume anywhere, land exactly once.
- Reversible. Activation is one owned import line;
xout undoremoves only what xout can prove it wrote. - Honest. A kept behavior is "not crossed out yet," never "proven right." Guessed defaults are labeled as guesses.
xout demands evidence from every rule, so its own claims file receipts in the same shape:
claim: interrupt anywhere, resume anywhere, land exactly once
evidence:
- the suite kills sessions mid-strike and replays the ledger from disk -
the reconstructed state is identical every time
- duplicate sessions are rejected; landing is atomic behind content hashes
- the full suite (400+ tests) on every commit, Python 3.10-3.14,
macOS/Linux/Windows
claim: xout cannot delete a line it cannot prove it wrote
evidence:
- before touching ~/.claude/CLAUDE.md it records a receipt - the file's
prefix hash and the exact byte where its one line landed
- xout undo re-verifies that receipt first; if the file changed around
the line, it refuses instead of guessing
claim: honesty applies to xout's own defects
evidence:
- while dogfooding the English pack, we caught xout why printing
"rule: None" - it read the wrong manifest key
- the defect is on the record in CHANGELOG.md; the fix landed with a
regression test in the same commit
The engineering behind those claims
Every strike is an append-only JSONL event with fsync; landing is atomic with content hashes; sessions replay deterministically; duplicate sessions are rejected; manual edits are detected before landing. Pair scheduling judges discriminative power per context, so routine strikes never starve the risky scene; a session is voided unless at least five axes carry real strike evidence. The 15 strikes narrow a 6,561-agent hypothesis space (3 values across 8 axes) down to one - and the survivor is only "not falsified yet," never "proven right." The sealed preregistration lives in docs/prereg/prereg_sealed.json; the frozen axis catalog lives in docs/axis_locality_table.md. The eight-axis catalog is deliberately frozen: xout is a local behavior compiler, not a prompt manager, cloud profile, or agent orchestrator.
Claude Code plugin & Agent Skills
xout also runs inside Claude Code as a conversation: /xout:xout shows each behavior pair in chat, you pick the one to X, and the agent records only your explicit choice. /xout:xout status, /xout:xout undo work the same way.
Or install the same skill through the open Agent Skills ecosystem - one command, any supported agent:
npx skills@latest add brnyxx/xout
Checksum-verified plugin install
Download xout-plugin-1.0.1.zip, SHA256SUMS, and verify_checksums.py from the v1.0.1 release, keep all three in one directory, then:
python3 verify_checksums.py SHA256SUMS \
--only xout-plugin-1.0.1.zip verify_checksums.py
DEST="$HOME/.local/share/xout-plugin-1.0.1"
test ! -e "$DEST" || { echo "destination already exists: $DEST" >&2; exit 1; }
python3 -m zipfile -e xout-plugin-1.0.1.zip "$DEST"
claude plugin marketplace add "$DEST"
claude plugin install xout@xout-marketplace
Then in a fresh Claude Code session: /xout:xout doctor, /xout:xout.
Remove
xout undo # deactivate: removes the one owned import line
Your rules and event history stay in ~/.claude/xout/ (yours to keep or delete). Uninstalling the package never touches them.
Development
python3 -m pip install -e '.[test,release]'
python3 -m pytest tests/ -q
CI covers Python 3.10-3.14 on macOS, Linux, and Windows. Releases ship wheel, sdist, plugin ZIP, SHA256SUMS, and artifact provenance.
Credits
The /xout skill installs through the open Agent Skills ecosystem (MIT) and follows the SKILL.md conventions that mattpocock/skills (MIT) established. Everything beneath the skill - the append-only event ledger, the pure-fold compiler, the sealed preregistration - is original to xout.
MIT © 2026 Brian Kim.
Release files for xout 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| xout-1.0.1.tar.gz | 1.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| xout-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.3 MB
Release files / xout-1.0.1.tar.gz
| Download URL | xout-1.0.1.tar.gz |
|---|---|
| Size | 1.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e3fade353d62b7e73dff17473995f13230aebefa614ae309743660a06b98ebe
|
|
BLAKE2b-256 checksum How to use checksums |
fd79c02a714e28b7d7d9d13dffb547688a09d37bc59624dfc9ae055372db38cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / xout-1.0.1-py3-none-any.whl
| Download URL | xout-1.0.1-py3-none-any.whl |
|---|---|
| Size | 132.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5bf544cf7da967c75ae298fa3bb894a4dd2585601f08134e7e808a739d24ffba
|
|
BLAKE2b-256 checksum How to use checksums |
2889a4e7a745daea57f5178e6f954c39653ce34451ee0b2d007536c54ba4aabf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|