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:

  1. Did the user ask for it?
  2. Does the requested result need it?
  3. What reachable evidence shows that need?
  4. 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.

License

MIT