Skip to main content

A white ceramic robot dog sits at an open, lit door, a scroll in its mouth, its paws stopped at a glowing amber line on the threshold

housebroken

Agent-written pull requests that do not make a mess in someone else's house.

Stars Release PyPI Works with Claude Code MIT license

12 gates 29 merged pull requests across 23 projects 5 closures turned into gates shellcheck clean

29 merged upstream · 23 projects · 5 closures, each one now a gate
Derived from GitHub on 7 September 2026: one account, every patch written by an agent, every filing governed by these rules as they were learned. Apple, Microsoft, Google, Apache and JetBrains are among the mergers. The numbers · the twelve gates.

You know the maintainer. She runs the project on evenings and weekends, has for nine years, and opened GitHub this morning to four pull requests from accounts created last month. Each one rewrites a function she wrote in 2019. Each carries a paragraph of comments in code that had none, a six-hundred-word body, and a footer naming the tool that wrote it. One of them re-argues a decision she closed in April. She closes all four without reading them.

She is right to.

housebroken is the set of rules that get a pull request past her, written as scripts that refuse to file until every rule is met. The rules are not opinions. Each one was paid for with a closed pull request, and the closure is named next to the rule.

Before / after

Before: one branch, fourteen files, three unrelated fixes, a planning document and an agent config directory in the diff, a comment on every added line, a body that explains the tool, filed against a ruling already made in a closed issue, the project's own test target never run.

After:

one finding, one pull request
9 lines changed in the project's own style, no comment where the file has none
1 test that fails on their main and passes with the patch
body under 120 words, in their template, no footer
prior art read and quoted before the branch existed
their CI target green on a fresh clone of their main
the CLA known before filing, the SECURITY.md route taken when it applies

The second one gets merged. Sometimes in twelve minutes.

Numbers

Every rule here was learned on real repositories with real maintainers. Between late July and 7 September 2026, one account filed pull requests on projects it had never touched before, every patch written by an autonomous agent, every filing governed by these gates as they were learned. Derived from GitHub on 7 September 2026:

count
pull requests filed 115
merged 29, across 23 projects
open, waiting on a maintainer 81
closed without merging 5

The merged patches include ones accepted by Apple, Microsoft, Google, Apache, JetBrains, and the URL parser that Node.js ships. The fastest merge came twelve minutes after filing. Several came the same day.

The five closures matter more than the merges. Each became a gate. Two of the five were the same class, three days apart, because the first lesson was written as prose and prose is followed when remembered. That is why the rules here are scripts that refuse, not a checklist that suggests.

How it works

An obsidian book with chrome corners titled The Housebroken Agent, a treatise on manners for machines calling at the homes of maintainers

A pull request passes through the door in order. Each step is a script or a rule, and each names the closure that put it there. The verdicts themselves, in the maintainers' words, are in docs/lessons.md.

1. Read the house rules before knocking. check-ai-policy.sh reads the repository's contribution policy on its development branch and in the organization's .github repository, and prints the sentence, not a verdict. Some projects ask contributors not to use AI for pull request text; those are never filed. Some accept pull requests only for issues they have labelled; those get an issue with the fix offered. distinct-outside.sh counts outside contributors merged in the last 120 days. A project that has merged none is closed to outsiders whatever its README says.

2. Is it already on the table? prior-art.sh lists every issue and pull request, open, closed and merged, that touches the file or symbol, with the type taken from the API field and the closing ruling quoted for every closed item. Two closures built it: a pull request that duplicated an open pull request because a search mixed issues and pull requests and nobody checked the type, and a pull request that argued against a ruling in a closed issue nobody had read.

3. Is it a fix or an opinion? A change that rejects an input the project tolerated, or changes a default, is a breaking change on a stable major. It becomes an issue, never a pull request. Two closures, one class, two projects, before this was a rule.

4. Prove it red first. On a fresh clone of the upstream default branch, the new test fails. With the patch, it passes. The proof lives in the pull request as the test, not in the body as a claim.

5. Run their CI, not yours. The project's own test target, on the fresh clone, including the lint, format and mutation gates its workflow runs. Two pull requests went red on gates the author had never run, and the maintainer saw it before the author did.

6. Match the house style. comment-census.sh counts added code lines against added comment lines and compares them with the file. No comment in code that has none. Body under 120 words, in the project's template if it has one. No tool footer, no session link, no co-author trailer. When a template asks whether AI was used, the answer is one truthful sentence. Three maintainers said the same thing about comment density before it became a script.

7. Know the paperwork. Every organization gets a card before the first filing: CLA, DCO, signed-commit requirement, template. Some CLA bots post nothing on the pull request and put the instructions in a failed job's log; the card is where that is written down.

8. Security goes through the side door. A memory-safety or remote-abort finding in a library goes by the project's SECURITY.md route, privately, and never becomes a public pull request until the project answers.

9. File through the gate. branch-check.sh reads the branch before anything leaves the machine: it refuses a dirty working tree, a file whose mode disagrees with its own siblings, a committed file the repository's own .gitignore excludes, a working artifact, and a branch that is not on top of its base, and it prints every absolute claim the added prose makes so each can be falsified against the code. Three of those came from one review round on a single pull request. file-pr.sh wraps the pull request creation and refuses when the prior-art printout for that repository is missing or older than a day, or when the body carries a footer, a trailer, or a typographic dash.

10. Watch it land. verify-filed-pr.sh re-derives from GitHub that the head is the intended commit, the diff is exactly the intended files, and CI settled green. pr-sweep.sh lists every open pull request where the ball is in your court: a maintainer's comment unanswered, a review requesting changes, a red check, a conflict. Every maintainer comment gets a same-day answer. A ruling in a closed issue is never argued with. When the maintainer is right, concede and let them close it.

11. Clean up. fork-hygiene.sh deletes the fork branch of every merged or closed pull request and lists forks with no pull request left, which are deleted when the work is over. No planning file, agent directory or build output ever enters a diff.

12. Three per repository, one finding each. A repository gets at most three pull requests, each one finding, each meeting every rule above on its own.

Install

You need bash, gh (signed in) and jq. Then, from PyPI; pipx install housebroken-cli and uv tool install housebroken-cli work the same way:

pip install housebroken-cli
housebroken install-skill

The first line puts the housebroken command on your path. The second puts the skill where Claude Code loads it, so the agent runs the door itself before it opens anything upstream. Until the package is on PyPI, install from the repository instead:

uv tool install git+https://github.com/lenamonj/housebroken

housebroken help prints the door in order. Every gate is also a plain bash script under scripts/, runnable on its own.

What is in the repository

script gate
scripts/check-ai-policy.sh reads the AI-contribution policy where it actually lives
scripts/distinct-outside.sh outside contributors merged in 120 days
scripts/prior-art.sh issues and pull requests on the touched files, type stated, rulings quoted
scripts/comment-census.sh added code versus added comments, per branch
scripts/diff-defaults.sh default arguments and one-line wrappers added to keep call sites untouched
scripts/branch-check.sh the branch's mechanical facts: clean tree, file modes, artifacts, absolute claims
scripts/file-pr.sh the only way a pull request gets filed
scripts/verify-filed-pr.sh the filed pull request is what was meant, and CI settled
scripts/pr-sweep.sh every open pull request where the ball is in your court
scripts/notes.sh what this repository's maintainers have asked for before
scripts/fork-hygiene.sh branches deleted after merge or close, orphan forks listed

The scripts are bash and need gh and jq. They came out of one operator's workshop and some still carry that operator's assumptions; each script's header says what it assumes. Generalizing them is the current work.

Not in scope

housebroken does not find bugs and does not write patches. Any agent that produces a change can use it. It governs what leaves your machine and how it behaves once it arrives.

FAQ

Is this only for AI-written pull requests? No. Every rule here predates agents. Agents made it cheap to break all of them at once, on a hundred repositories, before breakfast.

Does it make maintainers like agent pull requests? No. It makes the pull request indistinguishable from a careful human's, and answers truthfully when they ask.

What if the maintainer closes it anyway? Then the maintainer is the judge and the ruling stands. Read why, write it down, and if it is a class of mistake, make it a gate.

Why "housebroken"? Because the alternative is what maintainers are calling it.

License

MIT.

Release files for housebroken-cli 0.3.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 housebroken-cli 0.3.0
File Size Uploaded
housebroken_cli-0.3.0.tar.gz 37.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for housebroken-cli 0.3.0
File Interpreter ABI Platform
housebroken_cli-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 80.8 kB

Release files / housebroken_cli-0.3.0.tar.gz

Download URL housebroken_cli-0.3.0.tar.gz
Size 37.3 kB
Tags Source
SHA-256 checksum
How to use checksums
844559e53f2609181d1bfd58dd0264a0a627776f4a2dcb1a8b71d8cf67cc53b1
BLAKE2b-256 checksum
How to use checksums
423d4a7e98f309e97e5878fc6e082ea64bd6724db45d3f875d72b365bcde9da5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release files / housebroken_cli-0.3.0-py3-none-any.whl

Download URL housebroken_cli-0.3.0-py3-none-any.whl
Size 43.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8a048b17e1ac2bfe68921c15caeef98438c006cb77d9142bdb27388ab340f09b
BLAKE2b-256 checksum
How to use checksums
840a39c59ce775160086af667dc2240e9b3725b6c159589b482154f6f1289ba9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

This release

0.3.0 This release

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

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