Blog · 17 September 2026

Part of: Assurance · Ārai· Status: Shipped· For: Teams running coding agents

Ārai 1.1.2: three hosts, one commit gate, and a fail-open we found ourselves

Native Codex hooks, the same rules at git commit for any tool, rules that know where they live — and a Grok Build hook that had been silently doing nothing until we checked.

Ārai is the open-source half of our assurance work: it turns the instruction files a coding agent already has — CLAUDE.md, AGENTS.md, Cursor rules — into rules that are enforced before a tool call runs, with a local, hash-chained record of what fired and whether the model obeyed. The last release was in early July. Since then we have merged a block of work that changes what Ārai can honestly claim, and this post is the roll-up. It is one release, 1.1.2, on every install path: the install script, npm, crates.io and now Homebrew.

A third host: Codex

Ārai could block in two assistants before this release, Claude Code and Grok Build. It now registers native hooks for Codex as well: the same three events (before a tool runs, after it runs, and when you submit a prompt), written into the project’s Codex hooks file by arai init.

Codex needed one thing the other hosts did not. It edits files through a patch format rather than a write-file tool, so a rule about creating a migration would never have seen a “write” at all. Ārai now parses the patch itself: an added file is checked as a write, an updated file as an edit, and a moved file as both at its destination, so a rename cannot slip past a creation rule. A malformed patch is refused rather than waved through, and the hook never executes the patch — it only reads it.

One boundary to state plainly: Ārai writes the hook registration, but Codex decides whether to trust it. You enable the hooks once in Codex’s own /hooks review. Ārai cannot grant that trust for you, and it says so.

A fail-open we found ourselves

In August we re-verified Grok Build against its 1.0 release and found that our hook was silently doing nothing. The host had moved its event names to a different case convention; Ārai only recognised the old one, so every rule failed its timing check and the hook returned an empty, permissive answer. Nothing was blocked and nothing complained. Two smaller gaps were hiding behind the same symptom: the host’s live name for its shell tool was not mapped to our shell rules, and a project with no instruction files never had hooks registered at all, so rules added later had nowhere to fire.

All three are fixed and the deny path is re-verified on Grok Build 1.0.0, both headless and over its agent protocol. The evidence is in the repository. We are writing it up here because a guardrail that fails open is worse than no guardrail: it lets you stop checking. The follow-up work below is mostly about making that class of failure visible.

Registration is not activation

Several small changes share one idea: Ārai should tell you what it can see and admit what it cannot.

Rules that can never fire are refused. A rule has to name something Ārai can intercept — a shell command, a file write, an edit. arai add now rejects a rule that maps to nothing, arai scan and arai lint warn when an instruction file contains one, and the guardrail list marks them. You can keep a documentary rule on purpose, but you have to say so.

Status reports the last firing. “Hooks registered but never invoked” used to be invisible unless you read the audit log by hand. arai status now shows the last recorded firing, and states that a registration on disk is not proof the host has activated it.

Hooks point at the binary that registered them. Registrations use the absolute path of the running executable, so a stale copy earlier on your path cannot quietly take over.

The same rules at git commit

Host hooks are per-tool, and not every tool has one. arai check-diff runs the same rule engine over a git diff: added files are checked as writes, modified and renamed files as edits, and any blocking rule fails the check. arai init --pre-commit installs it as a local git hook, and the repository ships a manifest for the pre-commit framework. The effect is a floor under every tool: a change that breaks a rule is stopped at commit whether Cursor, Copilot, or a person produced it. It is a local hook, so like any pre-commit hook it can be skipped with --no-verify; it is a floor, not a fence.

Rules that know where they live

Instruction files have grown structure that Ārai used to flatten. Discovery now keeps it. A nested CLAUDE.md or AGENTS.md applies inside its own directory. Claude’s rules directory honours each file’s paths; Cursor’s honours globs and alwaysApply. So a rule scoped to a migrations folder fires on writes there and nowhere else. Scope that cannot be parsed aborts the scan instead of silently widening the rule. A re-scan replaces the previous snapshot in one transaction: deleted files drop out, a failed scan leaves the last good rule set in place, and per-rule severity overrides survive.

The same change draws a line we needed for Kete. Rules an organisation supplies through Kete are held separately from rules discovered on your machine; a local re-scan never prunes or reclassifies them. Ārai’s library surface gained the pieces Kete embeds — the shared severity calculation, a project-scoped configuration loader, and read-only access to the audit day-buckets so evidence ships as the exact bytes that were hashed. One matcher, one calculus, two products.

Hardening

The rest is the unglamorous work of a tool whose job is to be hard to get around. Concurrent sessions writing the audit log now serialise across processes and resume from the real tail of the chain rather than a stale head. Malformed hook payloads fail closed. Diff parsing validates hunk lengths and quoted paths, so added content cannot pose as a file header, and copy-or-rename paths cannot dodge creation rules. A compound shell command that merely starts with arai no longer bypasses matching. Blocking rules survive relevance ranking instead of being crowded out by advisory ones. Release builds cannot ship a lean binary mislabelled as the full one.

Claims we walked back

We also corrected our own copy. The site and README used to describe Cursor, Windsurf and Cline as getting “strong advisory enforcement” over MCP. That overstated it. Over MCP the agent can read the rules, add new ones and check its own recent decisions, but nothing is injected and nothing is blocked unless the agent chooses to ask. Blocking needs a native hook host (Claude Code, Grok Build, Codex) or the commit gate. Under Grok Build, blocking is the guarantee and advisory context is best-effort, and project hooks stay inert until the folder is trusted. Live re-scanning of edited instruction files happens only on hosts that emit the events, which today means Claude Code; elsewhere you run arai scan. And “no data egress” became “the audit log stays local”, because anonymous usage telemetry exists and is opt-out.

What is still not guaranteed

Codex hooks are covered by Ārai’s tests, including the generated Windows command, but whether a given Codex session has activated them is a host-level check we cannot make for you. Deleting a file in Codex is checked as an edit of its path; there is no delete-specific policy yet. Glob-scoped rules fire on file actions, not on shell commands that happen to touch the same files. Cursor has no native hook adapter in this release. Ārai matches rules against classified actions and terms; it is not a shell interpreter or a filesystem permission boundary, and we would rather you know that than assume otherwise.

Ārai is Apache-2.0 / MIT and runs entirely on your machine. Install it, read the full changelog, or file an issue if a rule of yours does something other than what this post says it will. That is the kind of report we most want.

— The Taniwha team

Building agents that need somewhere real to stand?

See what ships today, or tell us what you're building.