Model or dataset
lennney/stop-that-shit avatar
lennney/stop-that-shit

Stop That Shit: a hook layer that denies AI agent actions outside the stated task

Stop That Shit(别再造史了)|面向 Codex/GPT 场景的多平台 Hook + Skill Guard:拦截 AI coding agent 无需求的哈希、校验和与任务范围膨胀。 A multi-platform Hook + Skill Guard for AI coding agents in Codex/GPT workflows: stop unrequested hashes, checksums, and task-scope creep.

2,014 stars49 forksJavaScriptMIT

At a glance

What is it?
Stop That Shit is an MIT-licensed JavaScript hook and skill guard for Codex, Claude Code, OpenCode, Hermes Agent CLI and Pi. It checks agent tool calls against an explicit task contract and returns permission deny when an action falls outside it.
Who is it for?
Stop That Shit fits teams already running Codex, Claude Code, OpenCode, Hermes Agent CLI or Pi who want a machine-checkable boundary on agent tool calls rather than another paragraph in AGENTS.md. It does not fit workflows where the agent's scope is genuinely unknown up front, or where nobody will maintain the host hook configuration.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The failure mode it targets: an agent that finishes the task and then keeps going

The README opens with a concrete scene. You ask the agent to export one result file. It also emits a SHA-256 checksum, and no later command reads that file. The task is not one step shorter, and the downstream flow is unchanged. The same pattern shows up as a guard nobody calls, a compatibility shim for a future that has not arrived, a full test sweep after a one-line change, or a review request that turns into a patch.

The author is explicit that this is not a model-specific defect. Codex, Claude Code, OpenCode, Hermes Agent CLI and Pi all do it, because each individual step has a local justification while the user never asked for it and the current task does not need it. The README also names the workaround that failed: appending more lines to AGENTS.md telling the agent not to over-engineer. The rules grow, and AGENTS.md itself becomes the next piece of unrequested output.

The audience is therefore narrow and specific. It is people who already run one of those five hosts, who can write an authorization line before the agent starts, and who want that line enforced by a hook rather than suggested by a prompt. If you are not running an agent that exposes tool-call hooks, there is nothing here for you to install.

SHIT as four named drift directions, not a general quality score

The project decomposes the problem into four letters. S is scope creep: fix one point, refactor half the repository. H is hashing and hypothetical hardening: adding a digest, a defense, or a disclaimer with no present consumer. I is intent violation: asked to review or answer, the agent edits files. T is task thrashing: something already checked, tested or reviewed gets done again from the start.

What matters is the boundary the README draws around this taxonomy. Stop That Shit does not count lines of code, and it does not treat a smaller diff as automatically better. The single question it asks is whether the step was requested by the user or is genuinely required by the current code, data and acceptance conditions. That distinction is what keeps the tool from becoming a diff-size linter with a moralizing tone.

The README is equally clear that the ALLOWED case is as important as the block. Published data may need migration. A release pipeline may really consume a checksum. A shared contract change may force cross-component tests. When the user asked for it, or when code, data and release process in the repository demonstrate the need, the work should stay. A guard that cannot express this is just an obstacle.

How the guard decides: modes, contracts, and the covered hook path

The mechanism is a task contract written into the prompt, plus a hook that inspects tool calls against it. You set the mode with review or change, then optionally constrain files, dependencies, hash operations and subagent budget. According to the README, the guard checks these explicit boundaries on covered hook paths. The agent can still read the repository, and it must still handle callers that are genuinely affected.

When the guard concludes an action is out of bounds, it returns a permission deny with a reason and a state. The README shows the shape of that response: STOP / INTENT, reason MODE_FORBIDS_MUTATION, state ARMED / review, plus an event identifier. The paired bad case is a user saying review this diff, do not modify, followed by the agent calling apply_patch and the guard denying it. The good case is a user asking for a P1 fix, the agent submitting a narrow patch and running the affected checks, and the guard allowing it.

The README states that after installation the default is OBSERVING / unconfirmed: the guard inspects and records covered actions but does not guess task authorization and does not return permission deny. That default is the honest part of the design. A hook that denied actions before you had declared a contract would be guessing, and the project declines to guess.

Why hashing is the first thing it blocks, and what the allow switch looks like

Hashing is prioritized because it is the action a hook can identify with relatively high confidence from a tool call. The README borrows its criterion from the HERO project: a digest must replace a more expensive operation, and the result must control the next step. The contrast given is direct. Hashing every line and then comparing line by line is a STOP. Using a digest to skip re-reading a large unchanged file is an ALLOW.

The current version denies recognizable new hash operations by default. The escape hatch is explicit: hash=allow, used when the user asked for it or when code and release process in the repository prove it necessary. The README adds a constraint that matters for anyone expecting the guard to be clever. The hook will not infer that purpose from code it has not read. So if your pipeline consumes a checksum and the guard cannot see that consumer on the covered path, the deny is a false positive and the fix is a contract line, not a bug report.

There is a related switch for dependencies, deps=allow, for cases like adding a parser dependency the user requested. These are per-task flags, not global settings, which means the authorization travels with the prompt rather than accumulating in a config file that later readers have to interpret.

Installation differs per host, and the Codex path pins a version tag

General hosts need Node.js 18 or later. Pi 0.84.4 requires Node.js 22.19 or later, and the Pi adapter is verified against @earendil-works/pi-coding-agent 0.84.4 specifically.

For Claude Code, from the repository root: claude plugin validate ., then claude plugin marketplace add ./, then claude plugin install stop-that-shit@stop-that-shit. Restart or run /reload-plugins, then invoke the namespaced skill as /stop-that-shit:stop-that-shit review -- followed by the instruction.

For Codex, the README gives codex plugin marketplace add lennney/stop-that-shit --ref 0.2.1 and codex plugin add stop-that-shit@stop-that-shit. The --ref flag pins the install to the version tag instead of the mutable main branch, which is the right default for a tool whose whole job is constraining agent behavior. After restarting Codex, you open /hooks in the new CLI TUI and trust UserPromptSubmit and PreToolUse after inspecting the commands. There is also an INSTALL_FOR_AGENTS.md file you can hand to Codex for the non-interactive steps.

OpenCode 1.18.18 or later installs globally without cloning: opencode plugin github:lennney/stop-that-shit -g. The README notes a caveat here. This command installs the Guard, but the built-in Skill and the optional /sts alias are not registered automatically. Hermes Agent CLI uses hermes plugins install lennney/stop-that-shit/.hermes-plugin --no-enable, then hermes plugins enable stop-that-shit and hermes plugins list; CLI users need a new process or session afterward, and Gateway users run hermes gateway restart. Pi installs from a local checkout with pi install /absolute/path/to/stop-that-shit, then either a new process or /reload in the TUI.

The narrow files= boundary is the part that has been hardest to get right

Release 0.2.1 is a fix release, and its subject is a false-allow class in the restricted files= contract. The release notes describe five changes. Absolute paths and host-reported relative paths based on cwd are now compared uniformly, with original path casing preserved. Unknown tools, or actions whose target path cannot be proven, request approval under a narrow files= boundary. An explicit files=** still means a wide boundary. An empty files= value no longer degrades into unlimited scope. And dot, dot-dot, repeated separators and Windows path casing are handled according to platform semantics. Five boundary scenarios have regression tests.

Read that list as a statement about where the difficulty lives. Path normalization across hosts is not glamorous, and getting it wrong in the permissive direction silently disables the guard for exactly the tasks where you bothered to write a narrow contract. The 0.2.1 notes are the maintainer admitting the earlier behavior allowed things it should not have.

The README also gives advice that cuts against the instinct to lock everything down. If you do not know all the affected files, do not force a files= list. Let the agent follow the real call chain and change the callers, fixtures and tests required to finish the task. A files= list you guessed at will either block legitimate work or, worse, be widened until it means nothing.

Stop That Shit Slop extends the same test from actions to sentences

Version 0.2.0 added a second surface. The 0.1.x line handled the action side: the .sha256 nobody reads, the compatibility layer for an imagined future, starting to edit during a review. The 0.2.0 framing is that performing an extra step is defending yourself with actions, and writing an extra sentence is defending yourself with words. A checksum nobody reads and a disclaimer that changes no decision have the same property: no consumer.

The added component is called Stop That Shit Slop, and it applies a Sentence Consumer Test to decide whether a defensive sentence should be deleted, tightened, or kept. The README's example is the agent writing a proposal and then arguing against a critic who does not exist: this is not complete research, it does not cover every case, it is not guaranteed to apply to everyone. Those sentences consume tokens and change nothing.

The original Stop Ladder still decides whether an action should happen, and Slop is described as usable on its own. That separability is worth noting, because it means the sentence-level check has a different failure profile from the hook. Judging prose is a softer call than denying a tool invocation, and the README does not claim otherwise.

Where it is the wrong tool, and what it does not replace

The clearest limitation is coverage. The guard checks boundaries on covered hook paths, and the README says the hook will not guess a hash's purpose from code it has not read. Anything outside those paths is unconstrained. If your host does not expose PreToolUse and UserPromptSubmit, or you decline to trust them, you are left with the Skill alone, which the README describes as Stop Ladder and task-mode guidance with no execution interception. That is a prompt convention, not a guard.

The second limitation is the contract itself. A contract that is too wide does nothing; a contract that is too narrow blocks real work. The files= guidance exists precisely because the tool cannot resolve that tension for you. And a default install sits in OBSERVING / unconfirmed, which means it observes and records but returns no deny until you configure otherwise. Anyone who installs it and assumes they are protected has misread the default.

A third point is that the project does not measure diff size and does not treat small diffs as a goal. Teams looking for a line-count budget or a complexity metric will not find one here. The judgment is about authorization and necessity, which is a narrower and more arguable claim than a numeric threshold.

For comparison, the HERO project is cited in the README as the source of the digest criterion: a digest must replace a more expensive operation and its result must control the next step. HERO is an anti-over-defense reference point for reasoning about when a defensive measure earns its place. Stop That Shit takes that reasoning and puts it behind a hook that returns permission deny on the covered paths. The difference in approach is enforcement versus guidance. A rule in AGENTS.md is advisory text the agent may or may not weigh; a hook that returns deny is a host-level decision the agent has to route around. That also means the two are complementary rather than substitutes, and the README treats the prose approach as the thing that failed first.

Version pinning, licence, and what maintenance actually costs

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the extent of what can be said here; the repository's LICENSE file is the authority, and this is not legal advice.

The maintenance surface is real and mostly external. The project ships five adapters against five hosts, and the README pins specific versions for the ones where behavior was verified: Codex CLI 0.145.0 with gpt-5.6-sol and Codex CLI 0.147.0 with gpt-5.6-luna in the public record, @earendil-works/pi-coding-agent 0.84.4 for Pi, OpenCode 1.18.18 or later, and Node.js 18+ generally against Node.js 22.19+ for Pi. Host plugin APIs and hook trust flows change, and each change is a potential adapter break. The install commands themselves show this: Codex requires you to trust hooks in the TUI, Hermes requires a process restart or hermes gateway restart after enable, disable, update, rollback or reinstall, and OpenCode's global install does not register the Skill or the /sts alias.

The upgrade path is straightforward because the Codex install supports --ref, and the README recommends pinning to the version tag rather than following main. The 0.2.1 notes are a useful data point on what upgrades look like in practice: a fix release that tightened a boundary which had been allowing actions it should have denied. If you pin, you decide when to take that class of change. If you track main, you take it whenever it lands.

Editorial conclusion

Stop That Shit fits teams already running Codex, Claude Code, OpenCode, Hermes Agent CLI or Pi who want a machine-checkable boundary on agent tool calls rather than another paragraph in AGENTS.md. It does not fit workflows where the agent's scope is genuinely unknown up front, or where nobody will maintain the host hook configuration. Before adopting, verify that your host exposes PreToolUse and UserPromptSubmit, that the guard leaves OBSERVING / unconfirmed once you set a contract, and that hash=allow covers whatever your release pipeline actually consumes.

Official sources

  1. lennney/stop-that-shit on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes