Start

Core concepts

The handful of ideas everything else builds on: what a project and a rule are, how a rule is scoped and tagged, and where Lore keeps its data.

Project

A project is a folder Lore knows about: a name and a root path. The name is the folder's name by default (letters, digits, ., _ and -; a name already used by a different folder is refused). A project is registered automatically the first time an agent works in a git repository, or by hand with memorize.py.

Registering builds a map: the project's sections, languages and manifest files. The map holds no file contents.

Section

A section is a folder-level area of a project. A file's section is its top-level folder, except that for folders that merely group real areas (src, packages, apps, services, lib, libs, modules, internal, cmd, pkg) it is the folder plus the next level. Files in the root belong to the section root.

FileSection
src/api/users.pysrc/api
tests/test_users.pytests
docs/intro.mddocs
README.mdroot
src/main.pysrc

Unusual layouts can use a glob: scope instead. Vendored and build directories such as node_modules, vendor, dist and .venv are ignored when mapping.

Rule

A rule is one short sentence an agent should follow, with the metadata Lore needs to manage it. Rules are stored as plain JSON in ~/.lore/<project>/rules.json.

{
  "id": "4d138ebe",
  "text": "Paginate list endpoints with a cursor",
  "scope": {"type": "section", "value": "src/api"},
  "status": "active",
  "source": "agent",
  "evidence": "seen in 3 reviews",
  "created": "2026-10-18T09:12:44",
  "hits": 0,
  "refs": ["https://github.com/acme/shop/pull/41#discussion_r1"],
  "always": false,
  "title": "Cursor pagination",
  "triggers": ["list", "endpoint", "page", "paginate"],
  "tagged": "agent 2026-10-18T09:13:02",
  "auto": "2026-10-18T09:12:44"
}
FieldMeaning
idEight hex characters derived from the normalised text and the scope. The same wording in another scope is a different rule.
textThe rule itself: at most 500 characters, one line, no hidden characters or HTML comments.
scopeWhere it applies: global, a section, or one or more globs. See below.
statuspending (no effect) or active (served to agents).
sourceWhere it came from: manual (review.py add), ui, feedback, agent, review (learn.py), discover, or the file it was read from (AGENTS.md, docs/standards.md).
evidenceWhy Lore believes it: numbers from discovery, the reviewers' wording, a user correction.
refsWeb links to what justifies it, such as review comments. Only http(s) links are kept.
hits / editedHow often the same rule was proposed again, and when a person last edited it.
alwaysThe rule must be followed on essentially every edit in its scope, so it is sent on every request.
title / triggersA 3–6 word name (up to 60 characters) and up to 12 words (40 characters each) a task contains when the rule matters. Written by the agent; see how rules are chosen.
taggedWho wrote the tags and when, such as agent 2026-10-18T09:13:02. Empty means untagged.
autoWhen Lore activated the rule itself, with no person approving it. Empty for rules a person approved.

Scope

A rule's scope says which files it covers. There are three kinds:

ScopeWritten asCovers
GlobalglobalEvery file in the project.
Sectionsection:src/apiFiles in that section. api matches both src/api and api; src matches src and everything below it.
Globglob:**/*.{ts,tsx}Files matching one or more comma-separated patterns. **, *, ? and {a,b} are understood, and a bare *.py matches anywhere.

When several rules cover a file, the most specific are listed first: glob (file level), then section, then global. Section names and globs may not contain quotes, backslashes, backticks, line breaks or hidden characters, and are limited to 200 characters.

Status

  • Rules you write (review.py add, the UI) and rules trained from your own documents (train.py) start active.
  • Rules from discover.py, learn.py and instruction files imported by memorize.py start pending.
  • Rules the agent proposes are activated by Lore when they pass screening, and wait as pending otherwise. See automatic mode.
  • Approving a rule yourself clears its auto mark. Rejecting deletes the rule.

Tags and pinning

Three optional fields decide when an active rule is sent. They are written by the agent once per rule, not on every request:

always
Sent on every request that touches a file in the rule's scope. Meant for style, safety and architecture rules. Pinned from the CLI or UI by a person, or set to true by the agent. The agent can never switch it off.
title
Names the rule in the list of rules that were not sent.
triggers
Words (with synonyms) that a task contains when the rule matters, used when ranking.

Session

One MCP server process serves one agent session. During it, Lore remembers which rules it already sent (so it never repeats them), which projects the agent is working on, and how many rules it activated by itself. A new session starts from nothing.

Usage counters

Every time get_rules or search_rules hands over a rule, Lore counts one delivery in usage.json. review.py usage lists approved rules least-used first, and the web UI shows "served 12× · last 2026-10-10" on each. Previews (review.py resolve, the UI's preview) never count. "Never served" only means no file the agent worked on matched that rule yet; give a rule weeks before calling it dead weight.

Where the data lives

Everything is under ~/.lore. Set LORE_HOME to use another folder.

~/.lore/
  config.json              settings (optional): approval, auto_register, auto_limit
  <project>/
    project.json           name and root folder
    map.json               sections, languages, manifests (no file contents)
    rules.json             every rule
    usage.json             how often each rule was handed to an agent
    review-ledger.json     review comments already proposed or dismissed, and when they were last read
    trust.json             whether the repository counts as yours (cached for a week)
    .rules.lock  .usage.lock    lock files, so two processes never overwrite each other

Files are written atomically (a temporary file, then a rename) and writers take a lock, so two agent sessions can use Lore at once. Rules and usage are kept in separate files so that counting can never overwrite an edit. Nothing is sent anywhere by Lore itself; the only network use is through your own gh login when reading review comments or checking push access.

Hygiene: what can become a rule

All text that can reach an agent is checked before it is stored, and refused with a message rather than quietly cleaned:

  • Hidden characters: zero-width, bidirectional controls, Unicode "tag" characters, variation selectors and blank look-alikes.
  • HTML comment markers (<!--, -->), which hide text in rendered views.
  • More than 500 characters, or empty text.

Rules saved before these checks that contain such characters are shown with <U+XXXX> markers and a warning, are never served or exported, and cannot be approved until edited or rejected. More in security and trust.