Reins puts a synchronous policy check in front of every agent action
Stop AI agents from doing things you didn't ask for.
At a glance
- What is it?
- A Node CLI and agent hook that scores irreversibility, blocks destructive tool calls before they execute, and appends every decision to a local JSONL file. The repo's manifest still reads 0.0.14 while the newest release is 0.0.22.
- Who is it for?
- Reins earns a place on a machine where an agent has shell or browser access and you cannot review each action by hand, because the guarantees it claims are the ones that matter for an interception layer: synchronous, offline, and fail-closed. It does not help if you want to know what an agent was asked to do, only what it tried to do, and the README's own documentation lives at reins.sh/docs rather than in the repository.
- Can I use it commercially?
- Yes. Apache-2.0 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 last received commits 142 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The agent cannot continue until the hook exits
Reins is published as @pegasi-ai/reins, a Node package with a single binary, and it installs in two commands:
npm install -g @pegasi-ai/reins
reins initThe design bet is on interception rather than observation. The README calls out five guarantees, and two of them define the shape of the whole thing. The check is synchronous, meaning the agent cannot proceed until the hook exits, and it is fail-closed, meaning any unhandled hook error blocks the action instead of letting it through. Either choice can be argued with, but together they mean a bug in Reins produces a stopped agent rather than an unrestricted one.
The third guarantee is that there is no network in the hot path. Policies are cached locally and enforced offline, so the decision about whether a tool call runs does not depend on a service being reachable. That also means the enforcement path cannot be slowed down by a remote dependency, which matters when the thing being guarded is a shell command.
The last two are the audit and the framing. Every action is evaluated before execution, which the README labels zero trust, and every decision is preserved in an append-only log.
decisions.jsonl is the only record of what was blocked
The audit trail is a single file: append-only JSONL at ~/.openclaw/reins/decisions.jsonl. One line per decision, appended, never rewritten, which is what makes it usable as evidence rather than as a log you have to trust.
The path carries its own detail. It sits under ~/.openclaw, the OpenClaw agent's directory, rather than under a neutral location, so the log is colocated with the agent whose behaviour it records. That is convenient while one agent is in play. With Claude Code hooks and MCP-compatible agents in the same policy set, the README does not say whether each writes to the same file or to a path of its own, so anyone planning to correlate decisions across agents needs to check that before relying on one timeline.
Reins also tracks drift over time, which is the reason to keep append-only lines rather than a current-state file. A policy set that is edited to allow what an agent wanted last week leaves a record of both edits and the calls they permitted.
CONFIRM-prefixed tokens are how a pause becomes an approval
Blocking everything would make an agent useless, so Reins splits its response into three verbs. Prevent covers the mechanical part: block destructive actions before execution, score irreversibility, and detect risky browser state. Pause is the human-in-the-loop path, and Pause is where the tokens come in.
High-impact actions get routed through a terminal or messaging approval flow instead of being denied. Catastrophic operations require an explicit token in the CONFIRM- form before they proceed. The distinction matters for the design of your workflow: a denied action is a dead end, while a paused one leaves a place to type an approval, and the token is the thing that proves a human meant it rather than the agent retrying until it got lucky.
Prove is the third verb, and it is the one already covered by the log. Every decision, approval, and block is preserved, which means the three parts share one record: what the policy said, what the person did, and what ran.
A skill file is the second install path, copied by curl
Reins ships a Claude Code skill as well as a CLI. The documented install writes a single markdown file into the skills directory:
mkdir -p ~/.claude/skills/reins
curl -o ~/.claude/skills/reins/SKILL.md \
https://raw.githubusercontent.com/pegasi-ai/reins/main/.claude/skills/reins/SKILL.mdNote what that command fetches: a file from the main branch, at the moment you run it, with no version or checksum in the URL. Cloning the repository instead gets the same skill from the tree at .claude/skills/reins/, which is the path to prefer if you want the content pinned to a commit you chose rather than to whatever main holds later.
The skill is the awareness half of the product, the part that tells Claude Code what your security posture is. The hook is the enforcement half. The repository carries both shapes: .claude-plugin/, plugin/ and openclaw.plugin.json for agent plugin loading, .claude/ for the skill, and src/ plus test/ for the code the CLI is compiled from.
OWASP ASI10 scanning reads configs, not traffic
Alongside runtime interception, Reins scans your configs for OWASP ASI10 vulnerabilities and reports drift over time. This is a different job from the hook, and the README does not blur the two.
A config scan is a static read. It looks at how agents are configured and reports what the configuration permits, which is useful before a session starts and cheap to run on a repository. The hook is the runtime read: it evaluates an action that is about to happen, with no network call and no delay budget beyond the sub-50 milliseconds the README claims for policy evaluation.
So there are two ways to find out that an agent can do something you would rather it could not. The scan tells you in advance, the hook tells you at the moment of the attempt. The README's demo belongs to the second category: an OpenClaw agent tries to bulk-delete 4,382 Gmail messages and Reins blocks it before execution. A message count that specific is chosen to make the irreversibility score obvious, since a bulk delete has no undo path and the number is not the interesting part.
package.json reads 0.0.14, the newest tag is 0.0.22
The manifest and the release history disagree, and that is the first thing to check before installing. The package manifest in the repository declares version 0.0.14. The releases page shows 0.0.22, tagged 2026-04-14 and named for a Watchtower integration, with beta-0.0.2 on 2026-04-07 and a v0.0.1-beta on 2026-02-25 behind it.
Nothing here says which is wrong. A version that only moves at publish time is a normal pattern, and it would mean the repository always shows the previously published number. Either way the effect for a reader is the same: the version in the tree is not the version you get from npm.
The last push to the main branch was 2026-05-22, several months before the newest release tag, which is a normal gap for a small project but worth noting if you are judging activity. The rest of the manifest is unremarkable and useful: Node 18.0.0 or newer, TypeScript compiled with tsc into dist/, a bin entry pointing at dist/cli/index.js, and a published files list of dist, LICENSE, README.md and openclaw.plugin.json. Tests run through node --test on .mjs files after a build.
Editorial conclusion
Reins earns a place on a machine where an agent has shell or browser access and you cannot review each action by hand, because the guarantees it claims are the ones that matter for an interception layer: synchronous, offline, and fail-closed. It does not help if you want to know what an agent was asked to do, only what it tried to do, and the README's own documentation lives at reins.sh/docs rather than in the repository. Before you wire it into a session, pin a version deliberately, since the manifest in the repository reads 0.0.14 while release 0.0.22 is the newest published tag, and confirm the hook is actually registered in your agent, because a missing hook is indistinguishable from a passing one until something destructive is attempted.
Frequently asked questions
How do I install Reins?
Run npm install -g @pegasi-ai/reins followed by reins init. The package requires Node 18.0.0 or newer, and the CLI binary is dist/cli/index.js.
What happens when Reins sees a destructive agent action?
It scores the action's irreversibility and blocks destructive calls before execution. The README demo describes an OpenClaw agent attempting to bulk-delete 4,382 Gmail messages, which Reins blocks before it runs.
Where does Reins record its decisions?
In an append-only JSONL file at ~/.openclaw/reins/decisions.jsonl. Every decision, approval, and block is preserved, which is also what lets Reins track policy drift over time.
Does Reins need network access to enforce a policy?
No. Policies are cached locally and enforced offline, so there is no network call in the hot path. The README states policy evaluation completes in under 50 milliseconds.
Which agents does Reins work with?
Claude Code through its PreToolUse and PostToolUse hooks, OpenClaw through the plugin manifest, and any MCP-compatible agent. Enforcement is synchronous, so the agent waits until the hook exits.
What version of Reins should I install?
The package manifest in the repository declares 0.0.14, while the newest published release is 0.0.22 from 2026-04-14. Check which one npm resolves before you pin a version in an agent setup.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pegasi-ai-reins)