Ask Codex for one small file and you may get a module tree, several subagents, a new dependency, and a SHA-256 checksum nobody uses.
Every step comes with a careful explanation. The requested work is still not finished, and a noticeable part of the token budget went to work Codex invented for itself.
Adding “do not overengineer” to AGENTS.md helps until the file becomes a
history of every behavior that annoyed you. Stop That Shit turns the small,
high-confidence part of that history into a Skill and an executable Guard.
Stop That Shit gives Codex a task boundary. The default Guard combines one small Skill with two Hook events. Codex still reads the repository and follows necessary consequences. When it crosses a boundary that the Guard can prove, it gets a red stamp:
STOP / INTENT
Guard returned permission deny.
Reason: MODE_FORBIDS_MUTATION
State: ARMED / review
Event: evt_...
Version 0.0.3
is Technical Preview 3. LLM runs vary, and Hooks see only part
of a Codex run. The Skill and Guard can reduce some unwanted work. Neither can
guarantee how the model will behave.
| Start with | What it adds | Friction |
|---|---|---|
| Skill + Guard | Stop Ladder plus machine-enforced boundaries | Default; trust two Hooks |
| Skill only | The Stop Ladder and task-mode guidance | Optional; no enforcement |
Install in two commands
codex plugin marketplace add lennney/stop-that-shit
codex plugin add stop-that-shit@stop-that-shit
Restart Codex. In a fresh CLI TUI, enter /hooks and trust
UserPromptSubmit and PreToolUse after you inspect their commands. See
Install for expected status and the no-Hook option. You can also
give INSTALL_FOR_AGENTS.md to Codex and let it run
the non-interactive steps.
OpenCode from GitHub
OpenCode 1.18.18 or newer can install this repository globally without cloning it:
opencode plugin github:lennney/stop-that-shit -g
Restart OpenCode and use $stop-that-shit review -- .... The command installs
the Guard; the bundled Skill and optional /sts alias are not registered
automatically. See INSTALL.md for
details.
Bad Case / Good Case
BAD CASE
User Review this diff. Do not edit.
Codex Calls apply_patch.
STS STOP / INTENT: review does not authorize mutation.
GOOD CASE
User Fix the P1 finding only.
Codex Applies one patch and runs the affected check.
STS ALLOWED: the requested result needs this action.
The Good Case matters as much as the stop. Shipped data can require a migration. A release pipeline can require a checksum. A shared contract can require a broad test run. If the user or repository supplies the reason, that work stays.
SHIT happens
The name labels four ways a bounded task gets away from you:
| Failure | A familiar shape | |
|---|---|---|
| S | Scope creep | One fix turns into a refactor. |
| H | Hashing and hypothetical hardening | Codex adds digests or defenses with no current job. |
| I | Intent violation | A review or question turns into an edit. |
| T | Task thrashing | Codex rereads, retests, or re-reviews settled work. |
The plugin does not count lines or reward smaller diffs. It asks whether each extra action is requested or required by reachable code, data, and acceptance criteria.
The pain tends to look reasonable one decision at a time:
- checksum files that no command reads;
- guards for inputs that no supported path can produce;
- a rubric or audit loop where the task needs an engineering decision;
- feature flags, migration frameworks, and wrappers for a future no one asked for;
- one more guard whose only reason is to protect the previous guard.
Each piece has an explanation. Together they can leave a tiny feature buried under hundreds of lines of defensive code.
Why hashing is blocked by default
Hashing is concrete enough for the Hook to recognize on covered tool paths. It also has a clean question: does the digest save real work and change the next action?
We use the test documented by HERO: the digest must replace a costlier operation, and its result must control what happens next.
STOP
Hash every row, then compare every row anyway.
ALLOW
Use a digest to skip rereading an unchanged large file.
0.0.3 denies a recognized new hash operation by default. Use hash=allow
when the user or the repository supplies the missing job. The Hook does not try
to infer that job from code it has not seen.
Use it
Most tasks need one line:
$stop-that-shit change -- Fix the failing config test.
$stop-that-shit review -- Review this diff. Report findings; do not edit.
Add a boundary when you know it in advance:
$stop-that-shit lock change files=src/config.cjs|test/config.test.cjs -- Fix this behavior.
$stop-that-shit change deps=allow -- Add the requested parser dependency.
$stop-that-shit change hash=allow -- Generate the requested release checksum.
$stop-that-shit change agents=1 -- Use one independent test shard.
Skip files= when you do not know every affected file. Codex should inspect the
real call path and update the callers, fixtures, or tests needed to finish the
request.
Installation begins in OBSERVING / unconfirmed: covered actions are checked
and recorded, but the Guard does not infer authorization or return permission
deny. review, answer, monitor, or change explicitly arm it; watch
keeps observation-only behavior.
Inspect the local evidence chain without changing the current task contract:
$stop-that-shit status
$stop-that-shit runtime
$stop-that-shit explain evt_...
$stop-that-shit label evt_... correct|incorrect|inconclusive
permission_deny_returned describes the Guard response, not a proven host
effect. Stop That Shit reports host effect as unobserved.
What the Guard stops
| Codex action on a covered path | Default | You can allow it with |
|---|---|---|
Write during review, answer, or monitor |
Stop | Switch to change |
| Add a dependency | Ask | deps=allow |
| Launch a subagent | Stop above budget | agents=N |
| Add a recognized hash operation | Stop | hash=allow |
| Write outside a file lock | Stop | Expand files= |
The Hook needs a supported event and enough input to make the decision. It does not infer whether a cache, retry, abstraction, migration, compatibility layer, or new file belongs in your project. The Skill handles those choices with four questions:
- Did the user ask for it?
- Does the requested result need it?
- What reachable evidence shows that need?
- Would the current acceptance fail without it?
Codex reports or defers the extra work when the answers do not support it.
How it works
The Skill guides semantic choices. The Hook enforces explicit facts before a supported tool runs. A small host Adapter translates Codex events into the core decision interface.
Codex is the only implemented Adapter in 0.0.3. Another harness can use the
same core when it provides an equivalent before-action event. See
HOST-ADAPTER-CONTRACT.md.
Limits and evidence
Specialized tool paths can bypass normal Hooks. The plugin does not judge code quality, repair Codex runtime bugs, or act as a security sandbox.
The test suite proves policy behavior on covered events. It does not prove a general improvement in model behavior. EVIDENCE.md records the tests, live runs, null results, and exclusions.
In my own use, I have not seen the unnecessary SHA-256 behavior recur since
enabling Stop That Shit. That is a personal observation, not a controlled
benchmark. The local Runtime records metadata-only Hook checks and separates
checked actions, context responses, and permission denies. It still reports
host effect as unobserved.
Install
Default: install the Guard
The Guard supports Codex desktop and CLI installations with Plugin and Hook support. It requires Node.js 18 or newer. Read the Hook source before trusting it, then install:
codex plugin marketplace add lennney/stop-that-shit
codex plugin add stop-that-shit@stop-that-shit
Restart Codex. Open a fresh Codex CLI TUI, enter /hooks, and review the two
Stop That Shit handlers. A trusted installation shows Active 1 / Review 0 for
UserPromptSubmit and PreToolUse. Stop 0 is expected because the plugin
does not install a Stop handler. If Codex Desktop sends /hooks as a normal
message, use the CLI TUI for this review, then restart Desktop.
Optional: Skill only
If you do not want command Hooks, install only the advisory Skill:
$skill-installer Install stop-that-shit from https://github.com/lennney/stop-that-shit/tree/0.0.3/skills/stop-that-shit
Start a new task, then invoke $stop-that-shit. This path needs no Hook trust,
but it cannot enforce a task boundary or change your Codex sandbox and approval
settings.
See INSTALL.md for the complete Skill and Guard paths. Run the local checks:
npm test
npm run eval
npm run eval:paired -- --dry-run
npm run release:check
The paired command prints a 72-cell plan and starts no model runs by default.
Live runs require a dedicated Codex home with only this plugin enabled. See
the paired Codex eval before using --run.
Help define the boundary
This project grows through case pairs, not through more prohibitions:
report -> counterexample -> reproduction -> enforcement
A report can stop at the first step and still be useful. You do not need to write Hook code or build a benchmark. Enforcement comes last, and only when the evidence is reproducible and the decision is reliable.
- Codex did work the request did not need? Report a Bad Case.
- A guard would stop work that was actually necessary? Report a Good Case.
- Have a public reproduction? Turn one case pair into a fixture and open a PR.
A useful pair changes one fact and keeps the rest of the task the same. The Bad Case shows where Codex crossed the boundary. The Good Case keeps the rule from becoming another blunt restriction. Only reproducible, high-confidence parts belong in the Guard; the rest can improve the Skill and case catalogue.
Start with the case catalogue and contribution guide. Remove private code, secrets, account data, full transcripts, and identifying paths before you post. A small, sanitized issue is enough.
No comments yet
Be the first to share your take.