Skip to content

How it works

anti-hall is built around a Rust engine, ah-engine. It is the core of the plugin, not an add-on: every hook the assistant's harness fires is answered by it. The guards, tasks, handovers and the other features are what the engine does; this page is how it does it.

Status

The plugin fetches the engine binary itself. Node.js is a temporary compatibility fallback during the migration to the engine: it only answers when the engine cannot, and it is removed entirely in v1.0, after which the Rust engine is the only runtime.

The core: one engine, one thin trigger

ah-engine is a small program that stays running in the background, one per user. Each hook event in the plugin's hooks.json is one thin trigger, hooks/ah-hook.sh <Event>, that hands the event to the engine. The engine decides which checks apply to that event and answers from memory.

Claude Code / Codex
   │  hook event, JSON payload
   ▼
thin trigger    hooks/ah-hook.sh <Event>      (one per event)
   ▼
engine client ──socket──▶ ah-engine (one resident process per user)
                              │ reads at run time, from the plugin:
                              ▼
                    engine/logic/*.js     the rules' logic
                    engine/defaults/*.toml   settings and message texts

This replaced one Node.js process per hook per tool call. The engine's design notes measured the nine pre-tool hooks of a Bash call at about 409 MB of memory combined and 187 ms of CPU, most of it Node's own start-up. The engine answers from one long-lived process of about 5 MB, through a client of about 2 MB.

The plugin owns the rules

The engine is a runtime; the rules are the plugin's own files, read when the engine starts, when the plugin updates and when a file changes. Nothing is compiled into the binary.

What Where in the plugin Format
Logic of each check engine/logic/<check>.js, with shared helpers in engine/logic/lib/ JavaScript, run inside the engine in a sandboxed interpreter
Settings, limits, intervals, message texts engine/defaults/*.toml TOML
Which checks answer which event engine/defaults/dispatch.toml TOML

Changing a rule or a message means editing a plugin file, not rebuilding the engine. Your own overrides live in ~/.anti-hall/settings.json; see Settings.

The temporary Node fallback

While checks are still being moved into the engine, the trigger keeps a compatibility fallback so a guard is never weaker than before:

Situation Who decides
Engine installed, check handled by the engine Engine, from memory
Check not yet moved into the engine, or the engine cannot decide it exactly The original Node.js hook, for that one event
Engine missing, busy, slow or broken The original Node.js hooks, with a one-line note

This is a migration aid, not a mode you choose. It goes away in v1.0, together with the Node.js prerequisite.

The engine binary is downloaded by a small bootstrap script and checked against a sha256 checksum pinned in the plugin. Supported platforms are the same as the plugin: macOS and Linux, including WSL.

Binary download and verification

The engine is a prebuilt binary that the plugin fetches itself, so it is worth knowing exactly what that does. Every point below is read from the code in this repository.

Question Answer
What is fetched One archive, ah-engine-vX.Y.Z-<target>.tar.gz, for your platform (macOS arm64/x86_64, Linux x86_64/arm64 on glibc or musl; WSL counts as Linux). Only the single ah-engine file is extracted from it.
From where https://github.com/talas9/anti-hall/releases/download/ah-engine-vX.Y.Z/ over HTTPS (TLS 1.2 or newer, 120 s limit, 128 MB cap). Nothing about you or your project is sent.
Which version The one pinned in plugins/anti-hall/ah-engine.lock, which ships inside the plugin. The version and the sha256 of every asset come from that file, never from the network.
How it is verified The download is installed only if its sha256 equals the lock's entry. There is no trust on first use. The extracted binary must also run and report the pinned version.
If it fails A download error, a checksum mismatch, a binary that does not run, or an unsupported platform installs nothing. The reason goes to ~/.anti-hall/ah-engine/bootstrap.log, the session carries on, and the temporary Node.js hooks keep answering. A failed attempt is retried after 6 hours.
Install location ~/.anti-hall/ah-engine/bin/ah-engine, replaced atomically, previous copy kept as ah-engine.prev.
Provenance Each release carries SHA256SUMS and a GitHub build-provenance attestation, created by .github/workflows/ah-engine-release.yml. Check one with gh attestation verify <archive> --repo talas9/anti-hall.
Immutability Tags v* and ah-engine-v* are covered by a repository ruleset that blocks deletion and updates, and the repository has immutable releases enabled, so a published release's assets and tag cannot be changed.
Opt out The setting engine.bootstrap = false, or AH_ENGINE_BOOTSTRAP=0 (which overrides the setting). The Node.js hooks then do everything.

What the binary does on the network. The engine runs as a per-user background process that listens only on a private Unix socket. Its only HTTP client (ureq with rustls) lives in the opt-in Jev module, which is off by default; with Jev off the engine makes no network connections. The download above is done by the shell script, not by the engine. The sources are in ah-engine/ and the dependency list is ah-engine/Cargo.toml.

Build from source. There is no switch that makes the bootstrap build or fetch from a different place. What is supported is a binary you put in place yourself: the bootstrap never overwrites ~/.anti-hall/ah-engine/bin/ah-engine when it did not install it (or when it no longer matches what it installed), and the trigger runs that file. Turn the download off too, so a pinned release is not fetched when the file is absent.

git clone --branch ah-engine-vX.Y.Z --depth 1 https://github.com/talas9/anti-hall.git
cd anti-hall/ah-engine
scripts/build.sh                     # cargo build --release --locked; prints the binary's path and sha256
mkdir -p ~/.anti-hall/ah-engine/bin
cp target/<triple>/release/ah-engine ~/.anti-hall/ah-engine/bin/ah-engine   # <triple> as printed by build.sh
export AH_ENGINE_BOOTSTRAP=0         # or set engine.bootstrap = false

The AH_ENGINE_BIN variable is a test-only override and is ignored in normal use. Full procedure and offline builds from the vendored source archive: RELEASING.md.

Learn more