For AI agents: this page as Markdown · llms.txt · JSON Schema
#Reference
Rerail in detail: rules, the database, install, updates, the daemon and its API, audits, and internal-testing surfaces. Start with the README for an overview.
#How rules work
Rules live in the Rerail database, attach to repositories per folder, and run as code rules or conversation rules.
- Rerail database (
$RERAIL_HOME/): the source of truth for rule configuration. There are no rule files in the working tree.rerail. sqlite - Attachments add rule packs, By Rerail rules and rules created by you to a repository, per folder.
- Rule settings turn rules or packs on or off and set their mode, for the repository or one checkout.
- Code rule: a path scope plus clauses the native engine evaluates against source.
- Conversation rule (internal testing): a standing semantic query over one event source and boundary. Its reference describes what to detect; its action, the context to deliver.
Each file is judged by the checkout that owns it; conversation rules come from the folder the session started in. See Rule scoping.
More settings, and when changes apply
Rule settings also choose whether linters' suppression comments (eslint-disable, noqa, ...) silence a rule, and can set a By Rerail code rule's option values.
Changes made through the daemon, dashboard or MCP apply on the next event or tool call. OMP and Pi load conversation rules at session start and re-read configuration before every ingested event. Every runtime compiles code rules into the kernel and re-reads them before each audit. The Rust kernel only loads and evaluates what the database hands it.
#Where rules come from
The package ships no rules. Each rule is one of:
- By Rerail: from a Rerail rule pack, an npm package (
@neralabs/) installed intorerail-pack-<id> $RERAIL_HOME/packs. - By its publisher (
By @acme): from a third party's pack (rerail-pack-<id>or@<scope>/), not reviewed by Rerail.rerail-pack-<id> - Created by you: stored once per machine in the library.
rerail rules export writes the library and all repository configuration to $RERAIL_HOME/rules.json (or --output <file>); rerail rules import <file> [--approve] loads it back.
Pack rules, edited copies and backups
A third party's pack installs into $RERAIL_HOME/packs too. Pack rules are read from the installed packs, never copied into the database. They run only where a repository adds the rule or a pack that holds it.
Editing a By Rerail rule stores a copy in the library, added where the original was. The original switches off there once the copy is approved.
rerail update first copies the whole database to $RERAIL_HOME/. rerail reset never touches rules.
#Packs
A rule pack (packs/<id>/, pack format) holds rule documents in rules/ and a pack.json, but no code. Set-up recommends the packs that fit; rerail packs list, add, remove and recommend manage them afterwards. See Rule packs.
How matching works, and your own packs
pack.json lists each rule's document, title and group, and a match definition saying which repositories the pack fits: file globs, or dependencies in package.json, requirements*.txt, pyproject.toml or composer.json.
Set-up fetches every Rerail pack from npm and matches each against the repository locally, with no model. It installs only the packs you confirm, at the versions shown.
For your own conventions, name a pack's package.json rerail-pack-<id> or @<scope>/ and install it with rerail packs add <folder>. Rerail's packs use the @neralabs scope and win any pack id or rule id clash.
#Rule documents
A code rule is a rerail.policy/v1 document: a path scope plus regex, AST or relational clauses, each with the violation it reports. The code-rule DSL reference documents every construct; Tool-call rules covers tool calls.
A conversation rule file:
{
"version": 1,
"rules": [
{
"id": "persisted-session-events",
"mode": "steer",
"reference": "Changing persisted session events, replay, or branch restoration",
"match": {
"operator": "gte",
"threshold": 0.82
},
"sample": {
"source": "assistant-text",
"boundary": "sentence",
"minimumTokens": 3
},
"action": {
"content": "Preserve replay idempotency and verify restoration from an interrupted turn."
},
"repeat": {
"mode": "after-gap",
"gapTurns": 3
}
}
]
}Field values
| Field | Values |
|---|---|
match.operator |
gte (semantic similarity), lte (dissimilarity) |
match.threshold |
-1 through 1, inclusive |
sample.source (event source) |
assistant-text, user-input, tool:<tool-name> |
sample.boundary (inspection boundary) |
sentence, message, turn, tool-call |
repeat |
once, always, { "mode": "after-gap", "gapTurns": 3 } |
Every rule, conversation or code, needs a mode:
logrecords a match for review; no guidance.steersends the rule's guidance to the agent.block(internal testing) steers until block enforcement lands.
How Block reports that it steers
A block rule is stored and reported as block but delivered exactly like steer. Whatever puts a rule on block says so. rerail rules add, rerail rules import, rerail rules list and rerail rules approve print that Block does not block in this release. library_rules_upsert, repository_settings_set and repository_ return a note. The dashboard shows Block (steers for now).
Start small, from real incidents, repeated review feedback and key architectural decisions. A rule should give a specific action or invariant, not generic advice.
Good:
This touches persisted session events. Preserve replay idempotency and verify restoration from an interrupted turn.
Weak:
Remember to consider edge cases and write tests.
#Rerail database
One SQLite file per Rerail home holds all rule configuration, your rules and the machine's execution history.
The file is $RERAIL_HOME/ (~/.rerail/rerail.sqlite when RERAIL_HOME is unset). Its main tables:
- Rule configuration:
repositories,checkouts,rule_attachments,rule_settings,library_rulesand bookkeeping tables (Rule scoping). sessions: one row per harness session.events: the append-only transcript.work_links: references from a session to branches, pull requests or issues.steer_feedback: agents' reasons for not following steers (Steer feedback).audits: every rules run over a session, live or re-run.
Schema, access and columns
Harness adapters, runtimes and the daemon open the file from Node via drizzle-orm/. The OMP extension runs in OMP's Bun-based host and never opens SQLite; it uses the daemon's native-session IPC.
The schema is Drizzle tables in src/. npm run generate:schema renders it to the committed src/ (RERAIL_SCHEMA_STATEMENTS). openRerailDatabase applies it to a fresh file; test/ checks it for drift.
sessions:host,cwd,repository_id,started_at,ended_at.repository_id, the checkout's repository key, attributes history to a repository.events:kind,observed_at,payload_json, or apayload_v8blob when not JSON-representable.work_links:kind(such asgit-branch,github-pr,linear-issue),reference, optionalurl. No foreign key, so links can precede the session row.steer_feedback: local only; no foreign key.audits: scope (repository,touched-files,ai-output), independent run mode (steer,log), session, paths, source revision, timestamps, violations and execution failures. Terminal records are immutable. Closing or reopening a session interrupts unfinished audits, keeping partial results.
#History across repositories
The daemon serves every repository on the machine; a coding agent on /mcp sees only its own repository (Run).
Filters and code-rule paths
Listings (sessions, audits, violations, repository audits, rule activity) take an optional repository key or alias, else cover everything. A session id is found wherever it was recorded.
Code-rule path filters (scope.include, scope.exclude; exclusions win) apply to all three audit scopes in either run mode. Paths are relative to the session's cwd.
#Reset, scrub and seed
rerail resetdeletes the current repository's history across all its worktrees. Rules and settings stay.rerail scrubredacts secrets earlier versions stored, with the scrubber all writes now use (src/).engine/ secret-scrub.ts rerail seedidempotently adds mock data for MCP and UI work.
What each command touches
rerail reset deletes, in one transaction, ended sessions and all events, work links, steer feedback, audits, audit requests and repository audits. Rules, other repositories, audit settings and presentation preferences stay. The file is never unlinked, so open handles are unaffected. A running session keeps its row, minus earlier events, and keeps recording.
rerail scrub covers:
- Database: event payloads, audit findings (message, captured variables, fix text) and audit errors, in batches, then
VACUUMin place asrerail resetdoes. - Ledgers: each checkout's
.rerail/(linked folders skipped). Sample text and delivery content are scrubbed; a secret-holding preimage becomes its SHA-256 and size.sessions/ */ events. jsonl - Held steers:
.rerail/, under the hook's session lock.sessions/ <host>-pending/ *.json daemon.log.
Ledgers and daemon.log are rewritten in place, never shrunk or written past the end last read, so concurrent appends survive. Shorter text is space-padded. Longer text first reserves room with a {"rerail-scrub-reserve":…} line, removed by the next pass. Violation identity (clause, path, span, code) is unchanged.
A failing step (a busy lock or full disk, a ledger written mid-line, an unreleased lock) is reported, the rest run, and the exit code is 1. rerail reset also exits 1, history already deleted, if its rewrite fails or another reader holds the WAL. Re-run either to finish; re-running a complete scrub changes nothing.
rerail seed adds three code rules covering forbid with regex, ast and llm clauses, and two conversation rules (one off). They go into the library and the current repository (set up if needed). It also adds a session with events and two work links, attributed to that repository.
#Steer feedback
An agent that won't follow a steer tells the user why in one line and records it with rerail feedback.
rerail feedback <rule-id> <reason> # keep the note on this computer
rerail feedback list [--rule <rule-id>] # print the notes, oldest first, to attach to an issueRerail sends notes nowhere. To share them with Nera, attach rerail feedback list --rule <rule-id> output to a Rule misfire issue. Read the reasons first: each is the agent's own sentence about its work.
What is recorded and printed
A steer asks the coding agent to fix the problem, or tell the user in one line why not and record it: rerail feedback <rule-id> '<that line>'. A line containing ' goes on stdin: rerail feedback <rule-id> - <<'LINE'. The id appears in the command only if a shell reads it as one word.
Notes go to steer_feedback with the rule's pack and version, repository, coding agent, last-steered session and Rerail version, for tuning rules that get pushback. Ids or reasons with control or invisible characters (bidi override, zero-width space) are refused.
Each listed note shows time, rule id, <pack>@<version> (own rule if none), coding agent, Rerail version and reason; never session or repository.
#Install
This section is the install guide, for you or for the coding agent you ask to install Rerail.
In the repository you want Rerail in, run:
npx @neralabs/rerail setupFrom a Rerail checkout, just rerail does the same. For another repository, answer "Scan a different repo…" or pass --repo ~/code/your-repo.
- What it does. Installs into
~/.rerailwithout admin rights, proposes rule packs, and on your yes starts Rerail and connects your coding agents. Rerail starts in your next new session. - In a terminal: ↑/↓ and Enter, or type the number.
- From a coding agent: give it this section. It runs
npx @neralabs/and asks you each question.rerail setup --relay - If your coding agent can't install it, run the same line in a terminal.
- If something goes wrong, see Troubleshooting and Supported and not supported.
Set-up choices and relay mode
Set-up turns nothing on by itself. It asks before reading the repository and gives a reason for each pack. On your yes it starts Rerail in every checkout you haven't stopped on its own. It connects the coding agents it finds (Claude Code, Cursor, Codex, OMP, Pi), or those you name, and ends with a short summary and a dashboard link.
- Before the scan: this repo, another, or pick packs yourself (no code read; none is fine).
- After the scan: start, change packs, or not now (nothing installed or turned on).
- Outside a repository: it asks which folder; or skip and type
/rerail-startlater in a session in any repository.
With --relay, set-up prints each question for the coding agent to ask you verbatim, with the command per answer (rerail setup --relay --answer … --repo … --agents …), even where the agent has a terminal. The agent waits for your reply and runs the command for your answer. Without --relay, set-up does this whenever there is no terminal.
Supported and not supported lists the operating systems, Node versions, shells and coding agents Rerail runs with, and those it doesn't.
Prerequisites (set-up checks them before changing anything, and says what to do):
- Node.js 24 or newer.
- Git on your
PATH. - macOS (arm64, x64), Linux with glibc 2.28 or newer (arm64, x64), or Windows MSVC (arm64, x64). Not Alpine or other musl Linux.
- npmjs, Rerail's only registry; no npm account needed.
Why these prerequisites
- Rerail reads every repository through Git. It skips a
gitinside the repository ornode_modules, so a repository'sbin/can't shadow it. With none onPATH, it falls back to the usual install locations. - Linux needs glibc 2.28 because Node 24 does. The package carries prebuilt native kernels for every supported target; nothing is compiled on your machine.
- The package is public, so npm needs no login.
#What set-up installs
setup installs under ~/.rerail/, points ~/.rerail/current and the launcher ~/.rerail/bin/rerail at it, and adds ~/.rerail/bin to PATH.
rerail setup [--answer <answer>] [--repo <dir>] [--agents omp,takes the answers as arguments.pi, claude-code, codex, cursor] [--port <n>] [--json] [--relay] rerail install --agents <list> [--dry-run]only connects coding agents.rerail install --removeremoves Rerail, keepingrerail.sqlitein a dated backup.
Launcher, PATH and removal details
On Windows the launcher is rerail.cmd, plus rerail for Git Bash. The PATH entry is a marked block in your shell startup file, or the Windows user Path; RERAIL_MODIFY_PATH=0 leaves PATH to you. rerail update adds it where an older set-up didn't. rerail update shells out to npm with your ~/.npmrc.
rerail install --remove disconnects every coding agent, takes Rerail off PATH and stops the daemon. It moves rerail.sqlite to a dated backup, so rules and history are kept. Then it deletes current, the launcher, every version, the rule packs and ~/.cache/rerail, naming each.
Installing Rerail is the short guide; How set-up works details each step, removal and the managed layout.
#Commands in each coding agent
Every coding agent gets the same commands (command reference). Restart the coding agent after installing or rebuilding.
- OMP and Pi register them natively.
- Claude Code and Cursor get user-level command files in
~/.claude/commands/and~/.cursor/commands/. - Codex gets one skill per command in
~/.codex/, invoked asskills/ <name>/ SKILL.md $rerail,$rerail-manage,$rerail-start, and so on.
/rerail-start covers the current checkout and the worktrees that follow it; /rerail-stop stops them and detaches the runtime immediately.
Settings, audits, status, version, update checks and reset are rerail CLI commands. See Scan and settings controls for targeting and coding-agent differences.
Registration details
From the main checkout, /rerail-start covers every linked worktree without its own setting. Claude Code and Cursor command files come from rerail install or rerail setup and are removed by rerail install --remove. The CLI commands are rerail settings, rerail scan, rerail status, rerail version, rerail update check and rerail reset.
Registration removes Rerail's own files under retired names (/rerail-session; /rerail-ui and /rerail-rage-quit, now /rerail-manage and /rerail-uninstall). rerail update re-registers connected agents (rerail install --refresh); a coding agent never connected stays untouched. Generated files are replaced without a .bak; a same-named file Rerail didn't write is backed up first.
#Native targets and host entrypoints
Native targets: macOS arm64 and x64; Linux glibc arm64 and x64, built against glibc 2.17; Windows arm64 and x64 (MSVC).
OMP and Pi run Rerail inside their extension host; Claude Code, Codex and Cursor hooks send events to the daemon.
Entrypoints and event paths
- OMP:
dist/, in the package'shosts/ omp/ default-extension.js ompmanifest. - Pi:
dist/, in thehosts/ pi/ pi-extension.js pimanifest; loadable withpi -e. - Persistent event stream:
dist/orharness/ event-stream.js rerail events(internal testing). - Claude Code and Codex:
createandClaude Event Handler(...) createCodexEventHandler(...)for harness-owned hook registration. - Cursor:
.cursor-plugin/, backed byplugin.json dist/.hosts/ cursor/ cursor-hook.js
Lifecycle ingestion is not an MCP tool surface. OMP and Pi run a session-scoped RerailRuntime in their extension host. Claude Code, Codex and Cursor hooks send normalized events to the daemon's resident kernel over an owner-only Unix socket or local Windows named pipe, so policy state outlives each hook process. Persistent integrations can use the newline-delimited RERAIL-EVENTS/1 stream. All share one event runtime, cosine registry and executable-policy bridge.
#Activate
Activation binds a machine to a signed customer profile; it is in internal testing.
rerail --profile acme activate \
--code <one-use-code> \
--activation-url https://activation.example.com \
--trust-root ./activation-roots.json
rerail --profile acme profile statusFor an air-gapped machine:
rerail --profile acme activation request \
--deployment acme-airgap \
--output activation-request.json
rerail --profile acme activate \
--file acme-profile.jws \
--trust-root ./activation-roots.jsonThe trust-root file must arrive through an authenticated channel independent of the profile. Device private keys and returned credentials go to macOS Keychain, Linux Secret Service or Windows Credential Manager. The signed profile selects the customer control plane and limits automatic updates to its authorized npm dist-tag.
#Update
Updates are explicit: Rerail never checks a registry or installs on its own.
rerail version # the installed version
rerail update status # active and previous versions, channel, last check
rerail update check # resolve the channel without installing
rerail update # install and activate a newer versionrerail update backs up the database, installs and validates the new version, activates it, and re-registers your connected coding agents.
Update steps and failures
rerail events, hooks and the daemon run only the active version. rerail update:
- Copies the database to
$RERAIL_HOME/for manual restore (Database compatibility).rerail. sqlite. pre-update - Installs the configured npm dist-tag's version under
~/.rerail/versions. - Validates its native runtime and event stream.
- Activates it atomically for new harness sessions;
rerail update statusnames the replaced version. - Updated or not, re-registers every connected coding agent (
rerail install --refresh, which also runs on its own), adding new commands, skills and hooks and removing retired ones. A coding agent never connected is left alone.
An agent that can't be re-registered is named with the reason, the rest are refreshed, and the update exits 1 with the new version active. One whose configuration can't be read is named and skipped. Coming from a version without step 5, run rerail install --refresh once.
#Run
rerail daemon start runs the rules kernel, transcript database and browser view as one background daemon.
rerail daemon start # background daemon on the port it last ran on, else http://127.0.0.1:4737/ (a free port when those are held), opens nothing
rerail daemon start --open # same, then opens the browser view
rerail daemon start --host 0.0.0.0 --allow-remote --public-host rerail.example --tls-cert cert.pem --tls-key key.pem # bind off loopback over https (see below)
rerail start # start Rerail in this checkout and the checkouts inside it (--repository: every checkout); in a repository that is not set up, first runs set-up's questions there
rerail stop [<host> [<session-id>]] # stop Rerail in this checkout and the checkouts inside it (--repository: every checkout); the shared daemon keeps running for other checkouts and coding agents, and the reply names rerail daemon stop. A coding agent's host sets the reply's command sigil, and its session (rerail stop codex: CODEX_THREAD_ID) makes the reply name the rules that steered it
rerail state # prints started, stopped, or not-set-up for this checkout
rerail status # whether Rerail is on here, then the daemon, its engine and its model (Model: ok, or the problem and file, e.g. checksum mismatch (model.safetensors)); exit 3 when the daemon is not running, 4 when it does not answer, 5 when its engine or model is not ok
rerail manage [--print] # prints the dashboard's Overview URL and opens it; --print only prints
rerail session [<host> <session-id>] [--open] # this session's status line and page URL; --open opens it
rerail daemon stop # shut the daemon down for every checkout and coding agent; graceful stop where supported; forced termination after 10 s, and an error if the process outlives that by 5 s. A coding agent's session in a checkout where Rerail is started starts it again with its next event, unless RERAIL_AUTOSTART=0Native binding check before launch
Before spawning, rerail daemon start probes the better-sqlite3 binding under the daemon's Node. It rebuilds the binding in place if a Node upgrade changed the ABI. If it still fails, the launch stops with the reason rather than crashing into ~/.rerail/daemon.log. Autostart runs the same check, and rerail update applies it to an installed version that fails validation.
#What the daemon serves
The daemon owns the resident kernel and exposes the database over HTTP, OpenAPI and MCP.
GET /healthz: version, health, and engine and model status.GET /openapi.json: OpenAPI 3.1 for/api.POST /mcp: MCP Streamable HTTP, each/apioperation a same-named tool./api/*: the operations below.- Anything else: the bundled UI.
Endpoint details and degraded modes
The daemon writes rules and work links; the shared runtime records harness events.
/healthzreports version, pid, database path and presence, kernel status,installedAt, andmodel: bundled model files checked once per process againstmodel/manifest.json,okor the problem and file.healthymeans engine and model are ok;statusonly means the daemon answers./mcpis stateless and JSON-response. Non-POST gets405 Allow: POST; there is no SSE listener or transport session.- UI client-side routes fall back to
index.html.
Without the native addon the daemon still runs: status, /healthz and the UI header report the kernel unavailable, and transcripts stay readable. Model files can fail model/manifest.json; a clone without Git LFS has a pointer for model.safetensors. Then rerail status prints Model: checksum mismatch (model. and exits 5, and /healthz reports it. The dashboard header turns red naming the file, and session attaches fail until the files are fetched and the daemon restarted.
#API operations
Every operation is both an HTTP route under /api and an MCP tool of the same name. Each is defined once (id, route, zod schemas, handler) in src/api/operations.ts or src/, so a new operation needs no other wiring.
All operations, wiring and error codes
| Operation (HTTP and MCP tool) | Route | Purpose |
|---|---|---|
repositories_list |
GET /api/repositories |
Known repositories: key, name, aliases, set up, started, checkout count. |
repository_context_get |
GET /api/ |
A repository's clones and checkouts (own and effective state), and the caller's checkout and folder. |
repository_rules_get |
GET /api/ |
Rules per attachment folder with on, mode, suppressions, config, what decided each, addedAt, and updatedAt for your rules; unresolvable ones marked unavailable. |
repository_settings_set |
PUT /api/ |
On/off, mode, suppressions per repository or checkout (owner) and folder; By Rerail code rule config (whole repository). Null clears. |
repository_ |
PUT /api/ |
Follow .gitignore (default on): ignored files aren't audited (shell writes, direct edits, repository audits); tracked files are. New sessions only; summary field followGitignore. Agents may only turn it on, before set-up. |
repository_ |
PUT /api/ |
Add or remove packs, By Rerail rules and library rules per folder, with optional settings. The first addition (or configure: true) sets the repository up. |
repository_start |
POST /api/ |
Start; scope is checkout (and checkouts inside) or repository. |
repository_stop |
POST /api/ |
Stop, same scopes; rules and history kept. |
repository_link |
POST /api/ |
Resolve another remote address here. People only. |
repository_reset |
POST /api/ |
Clear history like rerail reset. Ended sessions go; running ones keep recording; rules and settings stay. People only. |
rules_activity |
GET /api/ |
Per rule since a time: violations (log-only count), sessions, last sighting, audits, steers; removed rules with violations as removed: true. sessions: { started, withViolations }. |
rule_packs_list |
GET /api/ |
Packs with npm package, publisher (rerail, or a third party's scope or package name) and rules (kind, title, group, mode, on/off, examples). With a checkout (MCP: the caller's), also its .rerail/rules as pack and publisher worktree, skipped files in skipped. Read-only. |
rule_packs_recommend |
GET /api/ |
Packs fitting a checkout: rule count, reason, folder. Local; changes nothing. |
coding_agents_list |
GET /api/coding-agents |
Per coding agent: found, connected, problem, and whether its tools can read Rerail's data (rerailData: access is kept-out, file-tools or open, with why). Dry run; shown in Settings and rerail status. |
rerail_rules_list |
GET /api/ |
By Rerail rules with their pack. |
library_rules_list |
GET /api/ |
Rules created by you. |
library_rules_get |
GET /api/ |
One rule created by you. |
library_rules_upsert |
PUT /api/ |
Create or replace your rule (attach: true adds it to the target); a By Rerail id stores an edited copy. |
library_rules_remove |
DELETE /api/ |
Delete your rule, its attachments and settings. |
sessions_list |
GET /api/ |
Sessions newest first with counts, steeredViolations, lastEventAt; total, nextCursor. |
sessions_get |
GET /api/ |
Summary with gaps over the whole transcript: undelivered events, boundaries answered before checks ran. |
session_events |
GET /api/ |
Ordered events, at most 500 per page, forward from after or the page before before; nextAfter continues. Agents get some payloads withheld (details). |
work_links_list |
GET /api/ |
A session's external references. |
work_links_add |
PUT /api/ |
{ kind, reference, url; re-linking updates the url. |
audit_settings_get |
GET /api/ |
Defaults (scope, mode, experimental steerStrategy) and the first repositoryAudit for the session's canonical workspace, with its repositoryAuditRecord. |
audit_settings_update |
PATCH /api/ |
People only (rerail settings). Set defaults, which outlast the session: mode steer/log; steerStrategy message/rewind/subagent. |
audit_requests_create |
POST /api/ |
Internal testing. Queue an audit for a session. |
audit_requests_list |
GET /api/ |
Internal testing. { auditRequests } with their auditIds. |
audits_list |
GET /api/ |
{ audits, total } with violations and failures; mode is run mode. |
violations_list |
GET /api/ |
Violations newest first with ruleId, clauseId, session, host, auditId; total, nextCursor. |
repository_audits_list |
GET /api/ |
Internal testing. Each repository's repositoryAudit and latest audit summary with violationCount. |
repository_ |
GET /api/ |
Internal testing. Paged entries; kind violation/failure, mode the rule's mode. |
src/api/http.ts mounts the operations with Hono and emits OpenAPI; src/api/mcp.ts registers them as MCP tools.
Validation failures return 400 { error: "invalid-request", issues }. Handler errors carry a status and a code: rule-not-found, rule-id-mismatch, rule-conflict, repository-, target-required, target-mismatch, agent-not-permitted, invalid-cursor.
#MCP bridge
rerail install registers a rerail MCP server with OMP that relays requests to the running daemon. OMP lists it under /mcp; run /mcp reload if the daemon started after the session. Other harnesses can run the same command or read the URL from daemon.json.
How the bridge finds the daemon
rerail install (and rerail setup) adds a rerail entry to ~/.omp/agent/mcp.json, beside the extension symlink. It is a stdio server running the installed rerail mcp-bridge ({ "command": "<node>", "args": ["<install>/). --remove deletes only that entry.
The bridge relays to the daemon recorded in daemon.json, following port changes and restarts, so the entry never needs editing. It first waits for that daemon's /healthz to answer with the recorded pid. A stale file therefore yields "Rerail daemon is not running" rather than reaching whatever holds the port.
After that check a request costs one file read, and the bridge re-checks only on connection failure. Suppose a checked daemon is killed with SIGKILL, its pid is reused, and another daemon takes its port before the next request: that request reaches the other daemon.
#Targets and what a coding agent may change
/api callers are people; /mcp callers are coding agents. This scopes agent tools; it is not authentication, since any local process can call /api.
An agent reaches only its checkout's repository and checkouts nested in its own, and may change little there. Anything else is 403 agent-not-permitted with the dashboard URL to do it there: <origin>/?repository=. See Rule scoping.
Targets and exactly what an agent may change
Repository and rule operations take a target in the query or body: repository (a key such as remote:github.com/ or clone:<id>, or an alias), checkout (an absolute path; wins over repository) and folder. An MCP call with neither uses the caller's checkout, from the x-rerail-caller-cwd header the bridge sends: the URI-encoded real path of the session's starting folder.
repositories_list shows an agent only its own repository. Naming another, or calling without a caller folder, is 403 agent-not-permitted. Within its reach, an agent may:
- start, stop and change settings in its checkout and those inside it;
- change attachments and settings only before set-up, or to add a rule it creates in the same call, or its copy of a By Rerail rule;
- edit or delete your rule only where no other repository runs it;
- turn Follow
.gitignoreon, never off, set up or not: reading ignored files is the person's choice.
Status line preferences and ongoing audit settings belong to the person.
#What a coding agent may read
An agent reads only its own repository's history, since transcripts hold prompts and tool output and violations hold source. session_events gives it prompts, assistant text, lifecycle, steers and Rerail's bookkeeping; payloads it may not see become { withheld, reason }.
How other repositories are hidden, and what is withheld
sessions_list,violations_list,audits_list,repository_audits_listandrules_activitycover its repository. Naming anotherrepositoryis403 agent-not-permitted, as is an MCP call withoutx-rerail-caller-cwd.- Another repository's session or audit looks missing.
sessions_get,session_events,work_links_list,work_links_addand the audit settings and request operations return404 session-not-found.repository_returnsaudit_ entries_ list 404 repository-.audit- not- found presentation_getreturns nosession.
session_events withholds:
- every
result'soutput, since it may be a file's contents; - a
call'sinputnaming a hidden or secret-like path (cat .env,.ssh/id_rsa,cat {.env,.npmrc}, a Kubernetes..data/; seesrc/), or a session-folder path linking to one (engine/ path-boundary.ts docs/a.mdlinking to.env), though not one merely inside a hidden folder likenode_modules/.pnpm/. A call's first 64 tokens are resolved, the rest judged by name; - a
call'sinputtoo deep or large to read whole; - an event kind not listed in
src/, whole, asengine/ transcript-boundary.ts { withheld: "event payload", reason }.
The check reads names, not a shell, so paths built at run time are missed. rerail rules evidence names such calls by tool only, and lists no Git-ignored standards file.
Violations in secret-named files (secrets.yaml, credentials.json, token.txt, gcp-key.json, kubeconfig, prod.sops.yaml, anything under .aws/; SENSITIVE_FILE_NAMES and SENSITIVE_FOLDER_NAMES; hidden alone doesn't count) reach an agent by rule and place only. The steer, violations_list, audits_list and repository_ withhold the message (which metavariables may fill with file text), variables and fix, and the steer says so. The steer also judges a file by where it links. Audits still run, and people see full findings via /api and the dashboard.
#Network binding and TLS
The daemon binds 127.0.0.1 by default (--port, --host override). Any --host other than 127.0.0.1, localhost or ::1 needs --allow-remote, since the whole network could then reach it.
A daemon reachable from other machines (off loopback, or answering a --public-host) serves https with --tls-cert <pem> and --tls-key <pem>. A self-signed certificate works: openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 365 -subj /CN=.
Certificate rules and pinning
--tls-cert takes the certificate, or a chain with the server's first. Both files are read once at start, and also work on loopback. A key file with any group or other permission bit (such as 0644) is refused; chmod 600 it.
Without TLS such a daemon won't start, since the access capability would cross the network in clear. --insecure-http overrides this for a trusted network: a container port published only on host loopback, or a local TLS-terminating proxy.
The daemon records an https:// URL and its SHA-256 fingerprint (tlsFingerprint256) in daemon.json and prints the fingerprint. Rerail's clients (CLI, hooks, MCP bridge, OMP, Pi) accept only that exact certificate, whatever its issuer or names. Browsers warn; compare fingerprints.
#Access capability
Every request needs the daemon's access capability in the x-rerail-access header, or gets 401 { "error": "access-required" }. The dashboard link carries it; rerail manage prints and opens that link.
Scope, storage and lifetime
The header covers routes, /mcp, /native/*, /healthz and /openapi.json. Only the page's static files (/, /index.html, its .js, .css and other files outside /api/) load without it, since npm ships them to anyone. The page then sends the capability on every request. Host, Origin and loopback are no boundary: another local user, or a sandboxed process allowed localhost, reaches 127.0.0.1:4737 as you do.
- Value: 256 random bits, stored as
accessTokenindaemon.json(mode0600) for Rerail's processes (CLI, hooks, MCP bridge, OMP, Pi). - Lifetime: a loopback daemon keeps it in
access-tokenin the Rerail home (mode0600) across restarts; delete the file to rotate. With--allow-remoteor--public-host, a new one is minted every start. - Browser: it arrives in the dashboard link,
<url>?rerail-access=. The page stores it per origin (scheme, host and port), strips it from the address, and is served with<capability> Referrer-Policy: no-referrer. A header, not a cookie: cookies reach every port of a host, while a custom header can't cross origins without a CORS preflight, which the daemon never answers.
Where the link is printed
rerail daemon start prints the link at a terminal (--open opens it), but not when piped, as for a coding agent. For a daemon on every interface it says 127.0.0.1; adjust the host. rerail manage prints the plain URL when piped. rerail session --open, set-up and /rerail-manage add the capability from daemon.json when opening your browser. Links for coding agents (session-start note, a steer's why?) never carry it; a browser without it is told to run rerail manage.
An agent with a shell runs as you and can read daemon.json: the capability separates you from other users and sandboxes, not from that agent; only the operating system can. If the daemon rejects the recorded capability (edited, or another daemon's), rerail status, rerail daemon start and the MCP bridge say so; run rerail daemon stop, then rerail daemon start.
#Host and origin checks
Every request's Host header must name loopback, the --host address or a --public-host name, which blocks DNS rebinding.
Accepted hosts and response headers
Loopback alone doesn't authorize writes, because DNS rebinding lets a page on another site resolve its name to 127.0.0.1. Host must name:
127.0.0.1,localhostor[::1]on any port (port mappings and reverse proxies present ports the daemon never bound);- the literal
--hostaddress (IP literals can't arrive by rebinding, and the daemon's state URL dials it); - a hostname from
--public-host <name,...>.
Anything else, including /native/*, /mcp, /healthz and the page, gets 421 { "error": "host-not-allowed" } before routing. An /api write with an Origin must come from one of those hostnames on the addressed port, or gets 403 api-origin-forbidden; Rerail's processes send no Origin. The page is served with X-Content-Type-Options: nosniff, its HTML with Content-Security-Policy: frame-ancestors 'none' and X-Frame-Options: DENY, so no site can frame it.
#Daemon state
~/.rerail/daemon.json (or $RERAIL_HOME/daemon.json) holds pid, port and database path; output goes to daemon.log beside it. RERAIL_AUTOSTART=0 stops automatic daemon creation, so command hooks need an existing daemon or explicit endpoint.
Ports, reuse and the kernel socket
daemon-port.json remembers the last port (or --port), reused by a start without --port so dashboard links survive restarts. rerail daemon start reuses a running daemon and says where; stale state from a crash or reboot is cleared. stop, status and manage run from the launcher you invoked, not the managed version, so they work mid-update.
daemon.json also records kernelSocketPath (Unix socket or Windows named pipe), which hooks reuse; RERAIL_ENGINE_SOCKET selects an explicitly managed endpoint. Events there need x-rerail-access. For a RERAIL_ENGINE_SOCKET socket, hooks send the capability from the Rerail home's daemon.json if it names the same socket.
#Session storage
Each session keeps its ledger (events and file preimages) under a storage root, <workspace>/.rerail/ by default, and loads the bundled embedding model. RERAIL_STORAGE_ROOT and RERAIL_MODEL_PATH replace them: a relative value resolves against the session's workspace, the folder the coding agent runs in, and an empty one counts as unset. Hooks, rerail events, OMP and Pi (in process or through the daemon) and the daemon itself all resolve them this way. Only the default root gets a .gitignore of *; a custom one may hold your own files, so Rerail leaves it as it is.
#Event ordering and edit capture
Each session has its own serialized lane, and native tool-call IDs pair edits with their results.
Ordering, restarts and per-host capture
- Pairing holds even for concurrent calls to one tool.
- Lanes are keyed by runtime configuration and session ID. One agent's open, audit or delivery never holds up another, and separate databases or workspaces never share a lane, even when session IDs coincide.
- Pending calls and captured preimages survive daemon restarts.
- Turn checkpoints catch filesystem changes from shells or tools without explicit edit paths. They keep source fingerprints, not a copy of the source or a baseline of violations.
OMP captures pre-edit source in its awaited tool_call hook and submits post-edit source from tool_result for background evaluation. Its asynchronous tool_execution_start and tool_execution_end notifications aren't execution barriers and aren't used.
Cursor Read and Write hook phases may share a native tool-call ID but keep distinct normalized event identities. If the CLI omits prompt and response hooks, Rerail reads the host's JSONL transcript incrementally with a durable byte cursor; native prompt hooks win when present. Transcript tool-use records never become invented tool events.
#Scan and settings controls
An audit runs code rules at one of three scopes, in one of two independent run modes. Full-repository scanning (rerail scan, explicit audit requests, the automatic first repository audit, repository audit operations) is in internal testing.
#Scopes and run modes
| Scope | Reportable code |
|---|---|
repository |
All eligible code, existing violations included; for diagnostics. |
touched-files |
Whole touched files, existing violations included. |
ai-output |
Added or changed lines, from captured pre-edit source. Untouched regions report nothing. |
steerrun mode records results and sends violations ofsteerandblockrules to the agent;logrules' violations are only recorded.logrun mode records the same with no conversation output.
Nothing is acknowledged, baselined or suppressed as already seen: changing relevant source can raise the same violation again.
#Steer strategies (experimental)
The workspace's steerStrategy (internal testing) sets how a code-rule steer reaches the agent: message (default), subagent or rewind. It needs RERAIL_ for the process running Rerail's runtime; otherwise every steer is a message.
What each strategy does
The runtime process is the daemon for OMP, Claude Code, Codex and Cursor, and the agent for a Pi session running Rerail in process.
message(also how older saved settings read): a separate message.subagent: the same, ending with an instruction to delegate the fix to a subagent (rerail_fixin Pi, registered by Rerail;taskin OMP;Taskin Claude Code and Cursor;spawn_agentin Codex) and stay on task.rewind: if an edit's own check steers before its tool result is answered, every file the call captured returns to its preimage (created files deleted), all or none. The steer goes into that tool result, saying what was restored and that the edit must be redone following the rule. The rollback is audited inlogmode, so the restored file steers nothing on its own.
rewind falls back to message when the preimage was unreadable, the call didn't capture the file, or the steer came after the result was answered (a one-shot hook waits a second). Ledger delivery entries record each steer's strategy, plus a rewound edit's toolCallId and rewound paths.
#Defaults and requested audits
Rerail audits a repository only when asked, and user-requested scans are log-only.
Runtime defaults and the first repository audit
RerailRuntime accepts ongoing auditSettings: { scope, mode, steerStrategy }; NativeCodeRuleEnforcer accepts scope and mode.
With RERAIL_ set for the runtime's process, Rerail runs one independent log-mode full-repository audit the first time it sees a canonical workspace in local storage. It is never repeated there. User-requested scans cover the whole eligible repository or the tracked, staged and untracked files in the current Git diff.
#How AI-output scope finds changed lines
AI-output scope diffs source, not violation IDs: it compares each edit with pre-edit source captured at the host's tool-call boundary. A new file is entirely generated. A file Git wrote is no edit at all, whichever session ran the command.
Fallbacks when no pre-edit source was captured
Without a boundary (a shell write, a Codex apply_patch its hooks don't show), Rerail uses the file's last-seen text this session (from the most recently changed 64 MB). Else it uses the file's Git index or HEAD blob. Each counts only if its SHA-256 matches the pre-change file. Blob reads never fetch a partial clone's missing objects.
If nothing matches, the edit reports its whole file, as touched-files does, until Rerail has seen the file change in the session. Parsing and cross-file query context may exceed reporting scope. Source, parse and match caches are incremental; repository scans stream bounded batches through a separate native workspace.
What counts as Git's write
- a file that now holds exactly its
HEADblob after anything but a commit movedHEAD(a checkout, switch, pull, merge, rebase, reset), or withHEADwhere it was (git restore,git stash); - a file a move removed;
- the files of a merge or rebase stopped on a conflict;
- a new linked worktree's files.
A file written and committed in one command stays an edit, measured from the tree before the commit. One written in the command that moved HEAD is measured from what Git wrote.
#Delivery
OMP and Pi deliver steers in the background; polling hook hosts get buffered violations at their next event.
Revisions, superseded steers and failures
Results carry source revisions: empty checkpoints keep buffered violations; relevant source changes invalidate them.
A newer edit drops a steer still queued for its file. In AI-output scope it also reports the lines generated since, as it does for an earlier edit it superseded before evaluation. An unseen violation therefore arrives once if still present, never if fixed. A shown one isn't repeated by edits elsewhere in the file.
Delivery is not an audit: it has no acceptance callback, acknowledgement persistence, retry chain or exactly-once guarantee. An audit returns violations and execution failures, never unknown. Unreadable sources, unavailable generated ranges, missing capabilities, exhausted budgets and evaluator errors go to audits, never the conversation. audit_requests_create requests an audit; GET /api/audits pages records.
#Command reference
OMP and Pi expose these natively, with slash-completion descriptions; Claude Code and Cursor as user-level prompt commands; Codex as $rerail-* skills.
| Command | Interaction |
|---|---|
/rerail |
Whether Rerail is on here, rule count, steers this session, dashboard link and all commands. |
/rerail-manage |
Open the dashboard Overview for this repository and checkout. |
/rerail-create |
Create or tune a rule in your words, or from suggestions. See docs/writing-rules.md. |
/rerail-start |
Start in this checkout and its worktrees, attached to the session; runs set-up's questions first if needed. |
/rerail-stop |
Stop recording, evaluation, steering and daemon autostart here and in its worktrees. |
/rerail-update |
Install the newest version. |
/rerail-uninstall |
rerail install --remove, keeping a backup of rules and history. Asks first. |
/rerail-help |
Same as /rerail. |
/rerail-show-me |
One-minute demo: the agent breaks a demo rule, is steered and fixes it. |
/rerail-bug-report |
The agent reads a support bundle to tell an engine bug, a shipped-rule bug or your rule's bug. |
Command details
/rerail: rendered byrerail session; Cursor gets the repository-level form./rerail-manage: the same link the footer's rule count carries./rerail-create: suggestions come from sessions (rerail rules evidence) and written standards. Followingskills/rerail-create, the agent drafts the rule, tests it (rerail rules test <draft.json>) and reads it back. On your yes,rerail rules add <draft.json>andrerail rules approve <id>add it to your library and this repository, setting the repository up with that rule if needed. It also tunes misfiring rules, and audits a pending rule or pack before asking you to approve it./rerail-start: OMP and Pi ask set-up's questions via their picker; Claude Code and Cursor as text./rerail-stop: the shared daemon keeps running; the reply namesrerail daemon stop, run in a terminal./rerail-uninstall: OMP and Pi ask via a native selector; Claude Code doesn't pre-approve it./rerail-show-me:rerail show-meadds rulelocal:rerail-show-me, scoped torerail-show-me.js. The agent writes that file breaking the rule, is steered, and fixes it.rerail show-me --cleanupremoves both (a concurrent demo elsewhere keeps the rule). It needs Rerail on and set up, never starts or sets up Rerail, and touches only what it wrote. The steer stays in History./rerail-bug-report: followingskills/rerail-bug-report, the agent readsrerail support-bundleoutput (allowlisted, scrubbed diagnostics). It fixes your rule via/rerail-create's Tune. Otherwise it checks the bundle with you and offers a filled-in issue, or files it if asked. Nothing is sent without you (what the bundle holds). Claude Code pre-approves the bundle's fixed invocations,rerail update checkandrerail rules test;--output,rerail rules addand filing ask first.
#Testing and adding a rule draft
A draft is { kind, rule, folder. rerail rules test --help prints the format; Writing rules explains each field.
rerail rules testvalidates a draft, runs its cases and a repository pass, and writes nothing.rerail rules addstores the draft in your library and adds it, on, to this repository (or the draft'sfolder).- The rule runs in Log until
rerail rules approve [<rule id | package> …] [--repo <dir>]approves it as it is now (approval).
Test output and add details
- A case some clause couldn't check (say, unparseable) shows
not checked (<reason>), never passed. - The pass lists files the rule couldn't check and counts in-scope binary files, which no rule reads.
- Text output shows the first five matches and files;
--jsonshows all. Path andfile-query matches have no line. - A bare rule document, such as
.rerail/, gets validation and the repository pass only.rules/ <name>.json
rerail rules add sets the repository up with only that rule if needed, and won't replace a rule shipped by Rerail. rerail rules approve with no names lists everything awaiting approval and its source.
The repository pass shows file lines to the agent, so it skips hidden files, secret-like names, nested checkouts and files Git ignores.
Exactly what the pass skips
- hidden files and folders (
.env,.ssh/,.github/, any name starting with.); - secret-like names:
*.pem,*.key,id_rsa*,credentials,credentials.*,credentials-*orcredentials_*data files likecredentials-prod.json(not source likecredentials-helper.ts),secrets.*,*.tfstate,service-account*.jsonand the rest ofSENSITIVE_FILE_NAMESinsrc/;engine/ path-boundary.ts - a nested checkout of its own;
- files Git ignores.
It never follows symlinks; this is enforced in code, not instructions. Tracked files are never ignored. Turning Follow .gitignore off (dashboard Settings or /api; agents can only turn it on) lets the pass read ignored files; hidden and secret-named files have no such grant. Unreadable ignore rules make the pass refuse. The report counts skipped files and folders without names (repository.leftOut), so a rule about them shows why it matched nothing.
#Starting and stopping
Rerail is off in every repository until started. Rules belong to the repository; on/off belongs to each checkout. State lives in ~/.rerail/rerail.sqlite.
rerail start --repositoryandrerail stop --repository(or the dashboard) act on every checkout.- Stopping applies immediately in OMP and Pi, and before the next one-shot Claude Code, Codex or Cursor hook. It survives restarts and keeps history, rules and the shared daemon.
What stopping does, inheritance and the footer
A stopped checkout records nothing, runs no rules, delivers no guidance, and its hooks never autostart or contact the daemon.
A checkout without its own value inherits from the nearest containing checkout of the same repository with one, else the repository. Starting or stopping a checkout reaches the checkouts inside it, which follow it again.
In a repository not set up, /rerail-start (or rerail start) runs set-up first. It recommends packs, adds those you confirm (a language pack at its matched folder, a repository pack for the whole repository) and starts. A started repository that isn't set up records sessions but runs no rules.
With a daemon running, the Claude Code, OMP and Pi footer shows R E R A I L ○ not on here in a stopped checkout. It shows R E R A I L ○ not set up · rerail start in a started repository that isn't set up. /rerail and rerail status report the checkout's state.
#Scan and settings from the terminal
rerail scan and rerail settings take flags. Outside the coding agent, name the session; Rerail never guesses the latest. Without --session, rerail scan is a different command, a checkout scan in its own process with no daemon or session: Headless scan.
rerail settings --session <session-id>
rerail settings --session <session-id> --scope touched-files --mode log
RERAIL_EXPERIMENTAL_STEER_STRATEGIES=1 rerail daemon start # experimental: the daemon honours the strategy
rerail settings --session <session-id> --steer-strategy rewind
rerail scan --session <session-id> --scope repository --wait
rerail scan --session <session-id> --scope git-diff --wait --json| Exit code | Meaning |
|---|---|
0 |
Submission/completion succeeded. |
1 |
A request or execution failed or was interrupted. |
2 |
The wait expired while the scan remained queued/running. |
Waiting, output and where to look
Without --wait, the request prints immediately. --wait polls up to ten seconds and prints the latest state; --json prints the structured record.
Findings alone don't turn successful execution into a failure. Inspect outcomes in Diagnostics by the reported request/run IDs. The Rerail home's daemon serves every recorded session, so the commands work from any directory.
#Settings, Diagnostics and Sessions pages
For hosts without native selector components, the standalone UI has Settings (ongoing scope and enforcement mode), Diagnostics (log-only scans and results) and Sessions (transcript events).
The default is automatic ai-output audits in steer mode with the message strategy: an edit hears only about violations in lines it added or changed. --scope touched-files reports whole edited files.
Page operations, ownership and scan scope
| Operation | HTTP surface |
|---|---|
| Effective settings | GET /api/ |
| Save defaults | PATCH /api/ |
| Request an audit | POST /api/ |
| Inspect requests | GET /api/ |
| Repository audit index | GET /api/ |
| Filtered audit entries | GET /api/ |
Ownership and activation. Defaults belong to the canonical workspace checkout and are shared by its sessions. They are not shared by other worktrees, conversations, workspaces or a machine-wide preference. Checkout settings are never silently promoted. Rules belong to the repository, so another transcript database doesn't share them (Rule scoping). Effective settings name their workspace and storage location.
The default ignores what the rest of an edited file already broke. Saved settings keep their scope. Changes apply to later automatic evaluations, running sessions included, never to a running evaluation or recorded results.
Each repository in retained scan history gets one automatic full-repository, log-only baseline, never repeated. If Rerail becomes active in such a repository without one, it runs it before ordinary evaluation. A later user-requested scan becomes the latest Diagnostics result without changing saved defaults. History filters never change evaluation settings.
Scope and outcomes. Explicit repository scans cover the whole eligible workspace. Git-diff scans take tracked, staged and untracked changed files at request time; an empty diff fails rather than scanning everything. Automatic AI-output evaluation keeps using captured preimages and changed ranges.
#Budgets and coverage gaps
Full-repository work is capped by a five-minute execution budget, a 100,000-file or 512 MiB aggregate source ceiling, and 32-file/1 MiB native batches. Hitting a cap fails the scan with one summary failure, always listed.
- A coverage gap is a rule that still runs out of work on a file: not an execution failure.
- A blind file is one every rule failed on.
Per-file failures and large files
A single file may use the policy engine's 32 MB source allowance. Unreadable files never stop a scan. At most 20 per-file failures are listed; the audit record and session summary keep the total (failureCount, with unlistedFailureCount unlisted), and the footer says audit failed (N failures).
Large files have no fixed cut-off:
- A file's shared work (parsing, tape, anchor index) and each clause's allowance scale with its size.
- A clause may visit
maxVisitedNodesnodes or 16 per file node (maxVisitsPerNode), whichever is more. - Each clause has its own allowance, so a costly rule fails alone.
- A file's clauses may together spend eight allowances per evaluation; a clause finding that spent fails without running.
A rule exhausting its own allowance in a full evaluation of the file is stored and reused by later scans. Failures that depend on what else ran (shared work, the ceiling, a partial evaluation) are re-evaluated next scan.
How gaps and blind files are reported
A coverage gap's failure suggests simplifying the rule or excluding generated or vendored files. One failure per such rule is kept past the list cap, and the footer counts them. A rule stopped by the file's work (code file-budget-exceeded) is also a gap, advised to exclude or split the file, but isn't counted.
A blind file is listed once as a failure marked blind, never cut, and reported in blindFiles and blindFileCount. Blind by work (budget) is a gap. Blind by syntax (syntax) is a partly read file: a repository audit lists it and completes; a touched-files scan fails.
A scan whose only failures are gaps completes, rerail scan exits 0, and the footer counts unchecked files and the rules that ran out or were stopped, instead of "audit failed". Two cases are not gaps and fail the audit: more than maxWitnesses on a file (witness-limit), where the rule did read it, and a file past a rule's input limits (input-limit), which it never read.
#Diagnostics
Diagnostics keeps one-shot requests and results apart from ongoing settings and transcripts; a completed scan with no violations is a successful empty result.
Results, filters and host delivery
- Unreadable inputs and evaluator errors are execution failures, not violations.
- Queued or running requests aren't results; interrupted execution isn't success.
- Requests link to the audit IDs they produced; history keeps session, workspace, source revision and evaluated rule revisions.
- Historical records and work cancelled before evaluation have no compiled-rule provenance, so aren't attributed to today's rules. A recorded catalog with no individual revisions had no enabled code rules.
It indexes every repository in retained session history and shows the latest repository audit's violations and failures as separate accessible records. Filters run in the daemon with bounded pagination; the UI never loads or filters a full result set in memory. Filters are entry type (kind=violation|failure), rule mode (mode=log|steer|block), exact code, path substring and free text. Rule mode differs from an audit's run mode, filtered by mode=steer|log on /api/audits.
Host capabilities. Only the runtime owning a session executes its requests. OMP/Pi deliver in the background; Claude Code, Codex and Cursor get buffered guidance at their next supported hook event, so a finished scan doesn't prove delivery. Runtime failures stay diagnostics, never guidance. A closed or unavailable session can't be swapped for another.
#Operate
OMP and Pi manage conversation rules in-session with the conversation_rules tool and /cosine-rules, both in internal testing.
The tool supports add, remove, list and test. Rule changes and delivered-match state are session-scoped and replayable: OMP and Pi append native session entries; event-loop adapters append to the JSONL session ledger.
/cosine-rules supports:
/cosine-rules list
/cosine-rules model
/cosine-rules reload
/cosine-rules test <rule-id> <text>Use test to tune references and thresholds on positive and negative examples before enabling delivery.
#Semantic workspace
A lower-level programmatic interface to mark, select, embed and compare session content; it and its OMP and Pi tools are in internal testing.
markattaches application-defined metadata to stable content references.selectresolves mark expressions plus source, owner, session and time filters.projectrenders and embeds items, groups, windows or a whole selection, with explicit budgets and lineage.relatecompares projections by all-pairs, per-vector top-k or corresponding-group pairing, with optional reductions.
import {
bundledModelPath,
NativeSemanticEmbedder,
OmpMessageContentSource,
OmpWatermarkStore,
SemanticWorkspace,
} from "@neralabs/rerail";
const entries = () => ctx.sessionManager.getBranch();
const semantics = new SemanticWorkspace({
sources: [
new OmpMessageContentSource({
sessionId: ctx.sessionManager.getSessionId(),
entries,
}),
],
watermarks: new OmpWatermarkStore({
entries,
appendEntry: (customType, data) => pi.appendEntry(customType, data),
}),
embedder: new NativeSemanticEmbedder(bundledModelPath()),
});
const recent = await semantics.select({
from: { owners: ["user"] },
order: "time-descending",
limit: 1,
});
await semantics.mark({
kind: "attach",
targets: recent.items.map((item) => item.ref),
watermarks: [
{
namespace: "handoff",
key: "requirement",
value: true,
owner: "engineer",
visibility: "private",
createdAt: Date.now(),
},
],
});OMP and Pi expose these as native tools: rerail_mark, rerail_select, rerail_project, rerail_relate.
Mark semantics and adapter limits
These are building blocks, not a finished multiplayer coordination interface; marks stay local unless the caller supplies shared storage and synchronization.
ContentRef.spanaddresses a UTF-16 text range within an item.- Marks are exact-target: a mark on an item doesn't apply to its spans.
- Expired marks stay in the append-only ledger but drop out of selections.
visibilityis selection metadata, not access control.
Claude Code, Codex and Cursor lifecycle adapters aren't agent-visible tool surfaces; harness registrations call the event-loop interface directly.