Aletheia

Rules: write standing instructions once and sync them to every tool

Aletheia (aletheia-mem) keeps your standing instructions as rules in one list and writes them into the instruction file that each AI coding tool reads. A rule is one instruction, such as "Run the tests before you commit."

What a rule is

A rule has these parts:

Rule ids look like r_d459528269. The same text in the same scope is never stored twice.

Scopes

A rule has one of three scope tiers.

aletheia rules add creates everywhere rules. Create project and situation rules in the Rules tab, through the MCP add_rule tool (scopeTier and scopeName), or with POST /api/hub/rules.

Sync does not filter rules by the folder you sync into. A rule for the project demo is written under ## In demo in every file you sync, and the tool reads it as text. To make a rule reach only some tools, set its tools list when you create the rule (tools in POST /api/hub/rules).

Add and list rules

aletheia rules add "Run the tests before you commit."
aletheia rules add "Use bun, not npm." --when "running scripts in this repo"
aletheia rules list
Added r_d459528269.
Added r_069d2c0e9e.
on  r_d459528269  Run the tests before you commit.  [everywhere]  (added 2026-10-29, source: you, last confirmed 2026-10-29)
on  r_069d2c0e9e  When running scripts in this repo: Use bun, not npm.  [everywhere]  (added 2026-10-29, source: you, last confirmed 2026-10-29)

Enabled, stale, confirm and retire

A rule is either on or off. aletheia rules retire <id> turns a rule off. It does not delete it, and you turn it back on in the Rules tab. Replacing a rule in the dashboard keeps the old rule and marks it as replaced.

Use an id from aletheia rules list:

aletheia rules retire r_dc75399976
Retired r_dc75399976: turned off, not deleted. Turn it back on in the Rules page.

The "still right?" re-check

Aletheia computes a stale flag every time it reads a rule. The flag never turns a rule off or edits it. A rule is flagged when any of these is true:

aletheia rules list --stale
on  r_d459528269  Run the tests before you commit.  [everywhere]  (added 2026-06-21, source: you, last confirmed 2026-07-01) [re-check: Not confirmed for 120 days (review window 90 days, last confirmed 2026-07-01).]

(--older-than N lists rules last confirmed more than N days ago. When nothing matches, the command prints No rules yet.)

If the rule is still right, confirm it. The rule text does not change. Only its last-confirmed date moves to today.

aletheia rules confirm r_d459528269
Confirmed r_d459528269 on 2026-10-29. The rule is unchanged.

The MCP confirm_rule tool does the same. An agent should call it only after you agree the rule still holds.

The recheck note

A flagged rule is still delivered. Aletheia adds a recheck note to its text, in synced files and in the session-start context, so the agent knows to verify it before it applies the rule:

- Run the tests before you commit. [re-check: Not confirmed for 120 days (review window 90 days, last confirmed 2026-07-01). Verify before applying.]

aletheia rules import strips the note again, so it never becomes part of the rule text.

The managed block

For most tools Aletheia writes one block between two marker comments and leaves everything else in the file alone:

# My project

Existing notes the user wrote.

<!-- aletheia:rules:begin -->
# Rules

Managed by aletheia-mem. Edit them in the Rules page; this block is rewritten on sync.

## Everywhere

- Run the tests before you commit.
- When running scripts in this repo: use bun, not npm.

## In demo

- Keep hooks free of network calls.
<!-- aletheia:rules:end -->

The next sync replaces whatever sits between the markers, so edit rules in Aletheia, not in the block. When the file already exists, the first change keeps a copy next to it as <file>.aletheia-<timestamp>.bak. A sync that would change nothing writes nothing.

Two files are owned by Aletheia and written whole, with the front matter the tool expects: the project rules file for Cursor (.cursor/rules/aletheia.mdc) and for Windsurf (.windsurf/rules/aletheia.md). Text you add to those files is lost on the next sync, apart from the backup.

Which files Aletheia writes

Tool idProject fileGlobal file
claude-codeCLAUDE.md~/.claude/CLAUDE.md
command-codeAGENTS.md~/.commandcode/AGENTS.md
codexAGENTS.md~/.codex/AGENTS.md
gemini-cliGEMINI.md~/.gemini/GEMINI.md
cursor.cursor/rules/aletheia.mdcnone
windsurf.windsurf/rules/aletheia.md~/.codeium/windsurf/memories/global_rules.md
opencodeAGENTS.md~/.config/opencode/AGENTS.md
copilot.github/copilot-instructions.mdnone
aiderCONVENTIONS.mdnone
agents-mdAGENTS.mdnone

The paths come from each tool's own documentation as recorded on 2026-10-26 in rules-targets.md. They were not fetched again for this page. The Copilot and Aider formats were not verified in that pass. Aletheia's tests write each file in temp folders. No tool was launched to confirm that it read the file it was given.

Cursor, Gemini CLI and Windsurf: config written from docs, not tested on a real install. No hook ran in Cursor, Gemini CLI, Windsurf or OpenCode.

Preview before you write

aletheia rules sync is a dry run until you add --write. It prints one line per tool and changes nothing:

aletheia rules sync --tools claude-code,cursor,codex,windsurf,copilot,aider,gemini-cli --dir .
- claude-code: .../w/CLAUDE.md — 3 rules, would change (add --write)
- cursor: .../w/.cursor/rules/aletheia.mdc — 2 rules, would change (add --write)
- codex: .../w/AGENTS.md — 3 rules, would change (add --write)
- windsurf: .../w/.windsurf/rules/aletheia.md — 2 rules, would change (add --write)
- copilot: .../w/.github/copilot-instructions.md — 2 rules, would change (add --write)
- aider: .../w/CONVENTIONS.md — 2 rules, would change (add --write)
- gemini-cli: .../w/GEMINI.md — 2 rules, would change (add --write)

The counts differ because one rule was limited to claude-code and codex. Add --write to apply the change. Use --global instead of --dir to write the files under your home directory.

aletheia rules sync --tools claude-code,cursor,windsurf --dir . --write
- claude-code: .../w/CLAUDE.md — 3 rules, written (backup .../w/CLAUDE.md.aletheia-2026-10-29T19-48-01-019Z.bak)
- cursor: .../w/.cursor/rules/aletheia.mdc — 2 rules, written
- windsurf: .../w/.windsurf/rules/aletheia.md — 2 rules, written

Running the same command again prints already up to date for each file and writes nothing.

In the dashboard, the Rules tab has a Preview changes button that shows the new content, and a confirmation before Write files. The API follows the same order: POST /api/hub/rules/preview returns the before and after text, and POST /api/hub/rules/sync refuses to write unless the body has "confirm": true.

Check for drift with diff and lint

aletheia rules diff compares each tool's managed block with the rules in the store. It reads files and writes nothing. After someone edits the block by hand it reports:

claude-code  .../w/CLAUDE.md  differs
  only in store  r_5a235350fa  Write commit messages in the imperative mood.
  only in file   .../w/CLAUDE.md:18  Never push to main.
  text differs   r_d459528269 vs .../w/CLAUDE.md:12
    store: Run the tests before you commit.
    file:  Run the tests before every commit.
1 tool out of sync.

A file with no managed block is reported as not compared.

aletheia rules lint checks the rules themselves and the drift. It prints one finding per problem with a fix hint, and exits with status 1 when it finds any. The checks are:

r_d459528269  stale_rule  Rule r_d459528269 may be out of date. Not confirmed for 120 days (review window 90 days, last confirmed 2026-07-01).
  fix: Confirm it with aletheia rules confirm, or retire it with aletheia rules retire.

Import rules from an existing file

aletheia rules import reads the bullet lines from a tool's file and adds each one as a rule with the source import:<tool>. It reads the managed block when there is one, and the whole file when there is not. A ## In <project> heading becomes a project-scoped rule. Rules already in the store are skipped.

aletheia rules import --tool claude-code --dir .
{
  "found": 4,
  "added": 2,
  "skipped": 2
}

Let Aletheia suggest rules

aletheia rules suggest scans your captured prompts for corrections such as "use X instead of Y", "always", "never", "don't" and "from now on". Each match becomes a pending suggestion with dated quotes. A suggestion seen once or twice is Light, three or four times is Steady, five or more is Strong. Nothing becomes a rule until you approve it in the Rules tab.

aletheia rules suggestions
#1 [pending] Use pnpm, not npm for installs  (demo, confidence 0.8)

Next steps