The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Arai listing page.
An instruction file is advice — the model can read CLAUDE.md and still force-push anyway. Arai turns instruction files (CLAUDE.md, AGENTS.md, .cursorrules, and others) into enforcement via native hooks: rules derived from prohibitive language block the tool call outright, advisory rules inject the relevant constraint at the point it applies, and a tamper-evident audit log records, per rule, whether the model actually complied.

That's it. Arai discovers your instruction files, extracts the rules, classifies their intent, scans your codebase for context, and sets up native hooks so guardrails fire at the right moment.
When your AI coding assistant (Claude Code or Grok Build) is about to do something your rules cover, Arai injects the relevant guardrail — right when it matters. Rules derived from prohibitive predicates (never, forbids, must_not) actually block the tool call instead of just advising.
Rules only fire when relevant. No noise on ls. No repeating principles already in your instruction files.
Every firing is written to a local audit log, and every PostToolUse is correlated with the matching PreToolUse to produce a compliance verdict — so you can measure whether the model actually honours the rules you wrote.
| File | Tool | Enforcement |
|---|---|---|
CLAUDE.md | Claude Code | Hooks (block + advise) |
AGENTS.md / Agents.md | Grok Build (native) | Hooks (block; advise best-effort) |
~/.claude/CLAUDE.md | Claude Code (global) | Hooks (block + advise) |
~/.grok/ AGENTS.* files | Grok Build (global) | Hooks (block; advise best-effort) |
.cursorrules / .cursor/rules | Cursor | MCP (advise) |
.windsurfrules | Windsurf | MCP (advise) |
.github/copilot-instructions.md | GitHub Copilot | Ingest only |
Rules from every file are parsed, classified, and stored the same way — but enforcement strength depends on what surface the assistant exposes.
deny decisions and actually block tool calls.decision: deny + exit 2) when the
host invokes hooks (verified on 1.0.0 headless with --trust; project
hooks stay inactive until the folder is trusted). Advisory text is still
emitted as additionalContext on allow responses and recorded in the audit
log, but Grok's documented PreToolUse contract only specifies
allow / deny+reason — so warn/inform injection into the model is
best-effort until the host surfaces that field. Treat block as the
guarantee; treat advise as optional context. See
docs/upstream/grok-hooks-reverification-1.0.0.md.arai stats, arai diff, and the audit log.Arai hooks several more events alongside the standard tool-call events (when the assistant supports them) so the rule set stays accurate to the live working tree:
FileChanged + InstructionsLoaded — when an instruction file
(CLAUDE.md, rules-dir, memory file, ...) is edited on disk or loaded
into context, Arai spawns an arai scan in the background. The next
tool-call hook sees the updated guardrails — no manual rescan.CwdChanged — when Claude cds into a different directory
(monorepo navigation), Arai re-scans rooted at the new directory so
the next tool call matches against the right project's rules.PostToolBatch — when Claude does a batch of parallel tool calls,
Arai correlates each call individually against any PreToolUse firings
in the same session, so per-rule compliance verdicts (Obeyed /
Ignored / Unclear) stay accurate on parallel workloads.Arai doesn't just do keyword matching. It understands your rules:
migrations/versions/ triggers alembic rules even if the file doesn't mention alembic, because sibling files import itfrom alembic import op in file content being writtennever/always/don't/must, should/shouldn't, cannot/refuse, make sure/be sure, consider/recommend, bare No X prohibitions, conditional shapes (When X, do Y / Before X: do Y / If X → do Y), and the section-aware Use X style-guide pattern. Severity mapping mirrors grammatical weight: should is Inform (soft), should not is Block (the writer chose to call out a specific prohibition).| An instruction file alone | With Arai |
|---|---|
| Advice the model can skip under pressure | Prohibitions deny the tool call at the hook |
| No record of what was ignored | Hash-chained audit log; arai audit --verify |
| You hope it listened | Per-rule obeyed / ignored / unclear verdicts |
| Rewrite rules into a new policy format | Your existing files are the policy |
Beyond firing rules, Arai produces a tamper-evident local record of every guardrail decision and correlates it with what the model actually did. This is what tech leads and compliance reviewers want to see — the trail behind the enforcement.
~/.taniwha/arai/audit/<project>/<YYYYMMDD>.jsonl. Append-only, day-bucketed,
queryable with arai audit (filters: --since, --tool, --event,
--outcome, --rule). Owner-only on disk (0700 dir / 0600 file on Unix;
icacls-pinned on Windows).prev_hash
and hash (SHA-256 over canonical bytes); the chain is anchored per-day in
a .head.YYYYMMDD sidecar. arai audit --verify walks the chain across
every day-bucket and exits non-zero on any tamper / reorder / deletion —
drop it in a cron or pre-archive job to gate evidence integrity.arai audit --ship <url> sends pending
day-buckets with their chain-head sidecars to your own HTTPS
collector, so the hash chain verifies server-side too. Resume cursor,
idempotent re-ship, optional bearer auth via env var, explicit opt-in
only. See docs/audit-ship.md for the payload
and a minimal collector.arai audit --purge --older=90 drops day-buckets
older than 90 days; arai audit --purge --project=<slug> wipes a specific
project (offboarding / decommission). Today's bucket is always preserved
and whole files are deleted (never individual lines), so the hash chain on
retained days stays valid. Pair with --dry-run (and --json) for a
pre-purge review, or wire into a scheduled job for time-based retention
policy.from CLAUDE.md:42, layer-1 imperative).
Auditors can answer "why did this rule fire?" without code spelunking.arai stats --by-rule rolls these up into per-rule ratios with a ⚠ flag
on rules the model is routing around.arai severity pins individual rules so you can
ship a rule set in advise mode and escalate one at a time.
ARAI_DENY_MODE=off is the project-wide rollback path.arai test replays scenarios through the
live match_hook pipeline; arai record captures real firings as
fixtures. Rule changes become CI assertions, not vibes.checksums.txt (SHA-256). arai:extends upstream
policy fetches refuse loopback / RFC1918 / link-local / cloud metadata
and disable redirects; cached upstream policies carry a SHA-256
sidecar so a tampered cache file is detected before its rules reach
the parser.ARAI_MCP_AUTH_TOKEN. When set, initialize must
present a matching token (constant-time compare) before any tool call
succeeds.Designed to align with the SOC 2 Trust Service Criteria (CC6.1 logical
access, CC6.6 supply-chain, CC7.2 monitoring, CC7.3 detection, CC8.1 change
management, CC9.2 vendor management). Arai is not itself a certified
product — it gives you the controls and the evidence trail; the
certification is yours to pursue. A complete TSC mapping and enterprise /
procurement-team feature inventory is in
docs/arai-compliance-features.pdf.
The Word source (.docx) is committed alongside it for editing.
Every release binary is signed in CI using cosign keyless signing via the GitHub OIDC token. The signing certificate is issued by Fulcio and bound to this repo's release workflow, so verifiers pin to the workflow identity instead of a long-lived public key. No private keys, no key rotation.
The install.sh and npm paths verify SHA-256 checksums by default,
which is enough to catch a corrupted download but not a substituted one.
For higher-assurance environments, verify the cosign signature before
running the binary:
A successful verification prints Verified OK and exits 0. Failure
exits non-zero — do not run the binary.
The --certificate-identity-regexp and --certificate-oidc-issuer
flags are the load-bearing ones: they assert that the signing
certificate was issued to this repo's CI workflow on a tag push, not
to some attacker's fork. Loosening either flag defeats the point.
cosign answers "was this binary signed by this repo's CI?". SLSA provenance answers the harder question: "how was this binary built — which commit, which workflow, which inputs?". Together they cover both the signing identity (cosign) and the build process (SLSA), so verifiers can detect a tampered build pipeline even if the signing identity itself is intact.
Releases include a single <tag>.intoto.jsonl attestation generated
by the SLSA GitHub generator.
Verify consumer-side with slsa-verifier:
A successful verification prints PASSED: SLSA verification passed and
exits 0. Failure exits non-zero — do not run the binary.
--source-uri is the load-bearing flag: it asserts that the provenance
was produced from a build of this repo's source. --source-tag (or
--source-branch) further pins to a specific release.
| Attack | SHA-256 checksums | cosign keyless | SLSA L3 provenance |
|---|---|---|---|
| Corrupted download | ✅ caught | ✅ caught | ✅ caught |
| Substituted binary at release | ❌ checksums.txt would also be swapped | ✅ certificate identity ≠ this repo's workflow | ✅ provenance source-uri ≠ this repo |
| Stolen release-pipeline secret | ❌ | ✅ no long-lived secret to steal | ✅ provenance binds to specific workflow run |
| Tampered build process (compromised toolchain or workflow inputs) | ❌ | ❌ — cosign signs the artifact, not the build | ✅ provenance records the exact workflow, commit, and inputs |
SHA-256 stays the default in install.sh / npm because it doesn't
require any extra tooling client-side. cosign and SLSA are opt-in for
environments that need the higher tier.
| Operation | Median | p95 |
|---|---|---|
| Hook check (skip-tool — Read/Glob/Agent) | ~22 ms | ~36 ms |
| Hook check (full match pipeline) | ~32 ms | ~55 ms |
| Full init | <200 ms | — |
End-to-end wall clock per tool call (on supported assistants), measured by
bench/hot_path.sh. Cost is dominated by Rust binary fork+exec
(~20 ms floor on Linux/WSL); rule matching itself is sub-ms above 200
rules thanks to the LEFT-JOIN'd intent and Aho-Corasick content sniffing.
Rule count between 50 and 500 doesn't materially move the median —
matching is no longer the bottleneck.
Arai collects anonymous usage data to help us understand if guardrails are actually useful. We track:
We never collect file paths, rule text, code content, API keys, or anything that could identify you or your codebase.
Opt out at any time:
or in ~/.taniwha/arai/config.toml:
Organizations that want the usage signal on their own infrastructure can point the existing queue at their own endpoint — same events, same anonymity constraints, your retention rules:
Default behavior is unchanged when endpoint is unset. Opt-outs win
regardless of endpoint. HTTPS required (plain HTTP allowed only for
loopback dev collectors), batches retry on failure, and the payload
schema is documented in
docs/telemetry-payload.md so you know
exactly what you're receiving. The audit log remains a separate,
local-only channel.
The sections above are enough to install Arai and see it block. The full capability set is documented in focused guides:
arai severity), dry-run explanations (arai why), compliance
verdicts, rule expiry--verify chain checks,
arai status, arai stats, token economicsarai audit --ship to
your own collector, with server-side chain verificationarai diff, arai lint,
arai test, arai recordarai:extends, trust list, pinning,
signatures, private policy sourcesTaniwha.ai — extracted from the Kete code intelligence platform.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
"Arai", "Kete", and "Taniwha" are trademarks of Taniwhaai Limited. The source licenses above grant no rights to these marks — see NOTICE. You are welcome to fork this project; please distribute forks under a different name.