For AI agents: this page as Markdown · llms.txt · JSON Schema

Rule scoping

Rerail keeps rule configuration and execution history in one per-user SQLite database: $RERAIL_HOME/rerail.sqlite, or ~/.rerail/rerail.sqlite when RERAIL_HOME is unset.

Repositories and checkouts

A repository is keyed by its remote address; each working copy of it is a checkout.

Two clones of one remote are one repository and share its configuration. A fork has its own remote, so it is its own repository.

How keys and checkouts are assigned

The remote address is normalised: lower-case, without scheme, user, port, trailing / or .git. The https, ssh and scp forms of one address give one key.

The clone id lives in rerail-repository-id in Git's common directory, or .rerail/repository-id for a folder outside Git.

A person links an alias with repository_link. An address that already belongs to another set-up repository is refused.

A checkout is recorded once, under its physical (symlink-resolved) Git top level, and joins the first of:

  1. the repository of another recorded checkout of the same clone;
  2. the repository its remote names, by key or alias;
  3. a new repository.

When a checkout of a clone-keyed repository later has a remote, the remote's repository adopts it:

A checkout whose folder is gone, or that Git no longer lists, is forgotten with its own settings.

Start and stop

Rerail is off until it is started, per checkout or for a whole repository.

A checkout uses its own start value, else that of the nearest recorded checkout of the same repository that contains it and has one, else the repository's.

State What happens
started Rules run.
stopped Nothing is recorded, evaluated or delivered; hooks don't contact the daemon.
not-set-up Started, but the repository has no configuration yet: sessions are recorded, no rule runs.

Stopping keeps rules and history.

Set-up

Set-up gives a repository its first configuration, normally the rule packs recommended for its code.

A repository is Not set up until its first configuration. Starting Rerail there runs set-up. It asks before reading the repository, recommends rule packs with a reason for each, and asks you to confirm:

Where packs go, and other cases

A set-up repository runs only what is attached to it, plus each checkout's own rule documents in .rerail/rules/ (a worktree's own rules). Installed packs' rules run only in repositories that add them; no other rule file in the working tree is read.

The repository's own lint config

So Rerail does not steer against what a repository deliberately configured, set-up reads its lint config at the repository root. The added packs' rules get matching settings, owned by the repository.

It reads ESLint, oxlint and Ruff configs as data and never runs them. A rule the config turns off for every file starts off; set-up never turns a rule on.

What is read, per linter
Linter Read Not read
ESLint The config ESLint would use: the first flat config (eslint.config.{js,mjs,cjs,ts,mts,cts}) when it is data throughout, parsed and never run; else .eslintrc.json, or .eslintrc when JSON; else package.json's eslintConfig. JSON may have comments and trailing commas. Its own rules and its overrides' rules. A flat config that runs code (a function, a statement that changes something, a namespace, a loop). A flat-config value that needs code run (an imported config such as js.configs.recommended, a call's result, an imported variable). .eslintrc.{js,cjs,yaml,yml}. An .eslintrc's extends and plugins' presets.
oxlint .oxlintrc.json, top-level rules. Each key resolves to a built-in rule as oxlint 1.88.0 resolves it; a rule's last key applies. extends, overrides, categories, plugins (a key for a plugin the config leaves off still counts); rule options.
Ruff select, extend-select, ignore, extend-ignore, per-file-ignores, extend-per-file-ignores (from [lint] where set there, else the top level). From the file Ruff uses (.ruff.toml, then ruff.toml, then pyproject.toml's [tool.ruff]/[tool.ruff.lint]) and configs its extend names inside the repository. A config extend names outside the repository; per-file ignores of an extended config in another folder; Bandit config.
What set-up does with it

A port matches an upstream rule by the names its document honours suppression comments for. So custom/no-console, another plugin's rule, leaves the port of ESLint's no-console alone.

The exact reading rules (what counts as data in a flat config, the order ESLint applies entries in, how Ruff's selectors resolve) are in the header comments of src/engine/catalog/lint-config/.

Rules: attachments and settings

Rules come from three sources; attachments make them present in a folder, and settings decide how they run.

Source details
Attachment and setting fields

Folders are relative to the repository root, POSIX, without . or ...

A setting's fields:

A null field leaves it to the next owner.

suppressions governs only linters' comments. Rerail's own comment, rerail-ignore, is always honoured: // rerail-ignore complexity-cyclomatic-typescript -- generated.

Where rerail-ignore applies

It is written with //, #, /* */ or {{-- --}} per language. It silences the code rules it names by id at the node it covers:

Every code rule answers to it, with nothing in its document. docs/code-rule-dsl-reference.html#rerail-ignore has the exact rules.

Rule Path Criteria (scope.include, scope.exclude on a code rule, excludes winning) still narrow the paths a present rule evaluates. Execution scope and run mode still decide when it evaluates.

Precedence

Which rules apply to a file, and which setting decides each of their fields.

For a file at path p, the rules present are those attached in a folder that contains p (web contains web/x, not web2/x). Each field (on, mode, suppressions, and each option in config) of each rule is decided separately; the first value wins:

  1. by owner: this checkout, then the checkouts that contain it (nearest first), then the repository;
  2. within one owner, the deepest folder that contains p;
  3. within one folder, the rule's own setting before its pack's;
  4. without a setting, the value the pack starts the rule with, then the rule's own default (on, in its document's mode).
Defaults, sources and errors

For suppressions the pack's start is its honourSuppressionComments (honour unless the pack sets it to false); a rule outside a pack honours them. Without a config value, an option keeps its document's value.

So config merges per option: a checkout that sets { "option": "type" } keeps the other options the repository sets.

repository_rules_get reports what decided each field of every effective rule as onSource, modeSource, suppressionsSource and configSource. configSource names, per option, this checkout's or a containing checkout's setting, the repository's setting, the pack's starting value, or the rule's default.

If a stored config no longer applies to the rule's document (a later release removed the option), configError says why. The rule runs nowhere: it is quarantined with that reason.

Conversation rules, in internal testing, resolve the same way for the folder the session started in.

Approval

A rule Rerail did not publish runs in Log, whatever its settings say, until a person approves its content.

This covers library rules, rules in a worktree's .rerail/rules/, and every rule of a pack that is not Rerail's own from npm. A person approves with:

What is approved, and when it waits again

A pack that is not Rerail's own from npm is a third party's pack, or any pack installed from a folder or tarball. Rerail's own published packs need none.

While a rule waits, no setting decides its mode: modeSource is { "by": "awaiting-approval" }. Its approval gives the subject to approve (kind rule or pack, id, digest) and approved: false.

An approval is of content, on this machine:

An edit, or a new pack version, is new content and waits again. Going back to approved content needs no second approval. A library rule a person writes through the dashboard or HTTP API is approved with the write; one a coding agent writes, or rerail rules add adds, waits. Library rules stored before approvals existed count as approved.

How approving works, and its limits

rerail rules approve first prints what it approves: a rule's JSON in full, invisible characters written as escapes, or a pack's rule ids. Rerail's command files never pre-approve it, so a coding agent's host asks the person before it runs.

The session footer counts what waits (2 to approve), as does /rerail, and Overview lists it. An approval changes the configuration signature, so a running session picks it up at its next event.

rule_approvals_set refuses a coding agent, but rerail rules approve cannot tell who runs it: a coding agent with a shell can run it too. That the agent waits for the person's yes is the /rerail-create skill's instruction, not something Rerail enforces, as with the rest of the line between people and coding agents (coding agents). Approval keeps a rule no person read from steering by default; it does not stop an agent set on approving one.

Which checkout judges a file

Each file is judged by the checkout that owns it, with that checkout's configuration.

The owner is the nearest folder above the file holding a .git entry that Git confirms as a checkout's top level. Only checkouts that are recorded, started and set up evaluate files.

Nested checkouts and symlinks

The owner is found from both the file's lexical and real paths; a symlink into another checkout or out of its owner is not evaluated.

A nested checkout owns its files when it is a submodule the checkout around it declares, or a checkout Rerail has recorded (such as a worktree kept inside the main checkout). While it is stopped or not set up it runs nothing, and the checkout around it does not judge its files either. Only a nested repository Rerail never recorded (an untracked git init, a stray .git) is judged with the checkout around it.

A session that starts in a stopped or unrecorded checkout judges nothing.

Coding agents

What a coding agent may change, and what only a person may do.

The HTTP API (/api) is for people; MCP callers (/mcp) are coding agents. The distinction is advisory, not a security boundary. A coding agent may:

Anything else is refused with 403 agent-not-permitted and the dashboard URL where a person can make the change. Only a person links repository addresses, starts and stops a whole repository, or approves a rule's content (approval). A rule a coding agent writes runs in Log until then.

Copy on edit. Writing a By Rerail rule's id through library_rules_upsert stores an edited copy in the library instead (<id>-copy, -copy-2, …).

How the copy replaces the original

Management surfaces

One set of operation definitions drives both HTTP/OpenAPI and MCP.

Every operation names its target in the query or body, never the path: repository (key or alias), checkout (an absolute path in a checkout) and folder.

How the target resolves

A checkout wins, then the repository, then the calling agent's checkout. A repository that does not match the checkout is target-mismatch. Reads never record a checkout; writes default to the whole repository.

rules_activity, sessions_list, violations_list, audits_list and repository_audits_list take an optional repository. Without it they cover the whole machine for a person, and the caller's own repository for a coding agent.

Operations and HTTP routes
Operation Route Purpose
repositories_list GET /api/repositories Every repository: key, name, aliases, set up, started, checkout count.
repository_context_get GET /api/repository One repository with its clones and checkouts (own and effective state), and the caller's checkout and folder.
repository_rules_get GET /api/repository/rules Effective rules with on, mode, suppressions and config, what decided each, and unavailable references.
repository_settings_set PUT /api/repository/settings Owner repository or checkout, folder, targets (rule or pack), on, mode, suppressions and config (null clears; omitted keeps).
repository_attachments_set PUT /api/repository/attachments Add or remove packs and rules per folder, with optional repository settings. The first addition, or configure: true, sets the repository up.
repository_start, repository_stop POST /api/repository/start, /stop Scope checkout (with the checkouts inside it) or repository.
repository_link POST /api/repository/aliases Make another remote address resolve to this repository. People only.
rule_packs_recommend GET /api/rule-packs/recommendations The packs that fit a checkout, each with the folder to add it in.
coding_agents_list GET /api/coding-agents Each coding agent Rerail works with: found on this computer, connected, and any problem. Changes nothing.
rerail_rules_list GET /api/rerail-rules By Rerail rules, each with its pack.
library_rules_list, library_rules_get, library_rules_upsert, library_rules_remove /api/library-rules[/{id}] Rules created by you. Upsert can attach a new rule (attach: true) and copies a By Rerail rule on edit.
rule_approvals_set POST /api/rule-approvals Approve a rule's or pack's content: kind, id and the digest read from approval.subject, with checkout for a worktree's own rule. 409 approval-stale when the content changed since; 404 rule-not-found when no rule or pack that needs approval has that name. People only.

MCP caller. The MCP bridge sends x-rerail-caller-cwd on every request: the URI-encoded real path of the folder its session started in.

How MCP callers are scoped

Dashboard. A repository's dashboard link is <origin>/?repository=<key>&checkout=<path>#rules, which opens its Overview. rerail manage, /rerail-manage and the status line build it. Without a scope, the dashboard lists repositories to pick from. (#rules is the pre-v8 name the dashboard still resolves; its own is #overview.)

Export and import

How rule configuration moves between machines, and what each audit records about it.

rerail rules export writes a version 1 dump: the library, and each repository's key, name, aliases, set-up time, attachments and repository settings. rerail rules import <file> reads it back. Checkout settings, start state and approvals belong to this machine and are not exported.

Each audit records, per rule, its revision, payload hash, source (pack, By Rerail rule or library rule), repository key, checkout, and a placement array. Later edits don't rewrite past audits.

Import, reset and audit details

A setting's suppressions and config are written only when set, so a dump without them still imports into a Rerail that predates them.

An imported library rule whose content was not approved here runs in Log until a person approves it; the command says how many do.

Each folder's entry in an audit's placement has on, mode, suppressions, onFrom, modeFrom and suppressionsFrom. Audits recorded before suppressions existed lack those two.