Commands

review.py

Everything you do to rules by hand: read them, add them, approve or reject them, edit them, pin them, say whether a repository is yours, preview what the agent is sent, and export them to Copilot files.

Synopsis

python3 review.py --name PROJECT COMMAND [options]

--name is required and comes before the command. Rule ids are the eight-character ids shown by list.

CommandDoes
listShow rules.
addWrite a new rule.
approve / unapproveActivate pending rules, or move them back.
rejectDelete rules.
editChange a rule's text or scope.
pin / unpinSend a rule with every request, or stop.
trust / untrustSay whether rules may be activated here without you.
resolvePreview what the agent would be sent.
usageSee which approved rules the agent actually receives.
syncExport active rules as Copilot instruction files.

list

python3 review.py --name myapp list
python3 review.py --name myapp list --status pending
python3 review.py --name myapp list --details       # where each rule came from, its tags and links
python3 review.py --name myapp list --auto          # only what Lore activated by itself

Options: --status {active,pending}, --details, --auto. Each line shows the id, status, scope and text, then flags:

[pinned]
The rule is always sent.
[auto-activated 2026-10-18]
Lore activated it; no person approved it.
[!! looks risky: …]
The text matches an attack pattern. approve --all will skip it.
[!! N hidden character(s) …]
The stored text hides characters, shown as <U+XXXX>. It is never served and cannot be approved.

--details adds the source, when it was created and edited, how often it was re-proposed, the evidence, up to five links, and its tags. Notes on stderr tell you how many approved rules still have no tags.

b8371d86  active  section:src/api          Use the repository layer for database access
          source: standards.md  created: 2026-10-18T00:48:59
8fa4eac1  active  section:src/api          Return errors as problem+json
          source: standards.md  created: 2026-10-18T00:48:59
-- 2 rule(s)

add

python3 review.py --name myapp add "Wrap SDK calls in an adapter" --scope section:src/api
python3 review.py --name myapp add "Never commit secrets" --pin
python3 review.py --name myapp add "Prefer small functions" --pending

Options: --scope (default global), --pending (store as pending instead of active), --pin (send with every request). Prints added: <id>, or duplicate / promoted when a near-identical rule exists. A rule that reverses a similar one is added with a warning on stderr.

approve

python3 review.py --name myapp approve 1a2b3c4d 5e6f7a8b
python3 review.py --name myapp approve --all
python3 review.py --name myapp approve --all --yes

Options: ids, --all, -y/--yes.

  • --all asks first. It lists every pending rule it will approve, with its scope and source, and asks [y/N]. No answer (empty or closed input) counts as "no". --yes skips the question.
  • Risky rules are never bulk-approved. Rules that match an attack pattern, or hide characters, are skipped with a warning and need approve <id> on their own.
  • Explicit ids confirm risky rules. If an id you name looks risky, the reasons and the rule are shown and you are asked "Approve it anyway?". Rules with hidden characters cannot be approved at all until you edit or reject them.
  • Approving clears a rule's automatic mark.
About to approve 1 pending rule(s). Once approved, the agent is told to follow them:
  eb159b38  global                 Prefer small functions
          from: AGENTS.md
approved 1 rule(s)

unapprove

python3 review.py --name myapp unapprove <id>… moves active rules back to pending, so they stop being served but are kept.

reject

python3 review.py --name myapp reject <id>… deletes the rules and forgets their usage counters. This is also how you undo anything Lore activated by itself. A rule you rejected from learn.py stays rejected, because its review comments are remembered.

edit

python3 review.py --name myapp edit 1a2b3c4d --text "Wrap SDK calls in an adapter module"
python3 review.py --name myapp edit 1a2b3c4d --scope section:src/api

Changes the text and/or scope; the id and status are kept. Give at least one. The new text goes through the same hygiene checks, and an edit that would duplicate another rule in the same scope is refused.

pin and unpin

python3 review.py --name myapp pin <id>… marks rules always: they are sent with every request that touches a file in their scope, whatever the task. unpin reverses it, including for rules the agent marked. Most people never need this, because the agent decides; use it to override the agent. See tagging.

trust, untrust

python3 review.py --name myapp trust            # always treat this repository as yours
python3 review.py --name myapp untrust          # never activate rules here by themselves
python3 review.py --name myapp trust --reset    # let the automatic check decide again

Lore normally decides itself (no remote, or a GitHub repository you can push to). Your decision is permanent until you reset it. Prints the result, for example myapp: trusted (set by you with review.py trust). See trust.

resolve

python3 review.py --name myapp resolve src/api/orders.py
python3 review.py --name myapp resolve src/api/orders.py src/api/users.py --task "add pagination"
python3 review.py --name myapp resolve src/api/orders.py --max-tokens 300

Shows exactly what the agent would be sent for these files. Paths may be absolute or relative to the project. With --task it applies the same selection as get_rules (and says how many rules were left out); without it, every eligible rule is shown. --max-tokens is an optional cap. Previews never count as "served".

Rules for project `myapp` (follow before writing code; sections: src/api)
- [section] Use the repository layer for database access
- [section] Return errors as problem+json
- [global] Prefer small functions
- [global] Keep functions small and focused

usage

Lists approved rules least-used first: never served, then longest since last served. The counters come from the MCP server and live in usage.json.

served  last served         id        scope                    rule
never   -                   eb159b38  global                   Prefer small functions
12      2026-10-17T16:02:11 b8371d86  section:src/api          Use the repository layer for database access
-- 4 approved rule(s); 1 never served

Read it with care: "never served" only means no file the agent worked on matched that rule yet. Give a rule weeks of real use before deleting it.

sync

Writes active rules to <project>/.github/instructions/lore-*.instructions.md, grouped by scope, with matching applyTo globs. Copilot (VS Code and CLI) loads these natively, so it is the fallback for clients without MCP.

---
applyTo: "src/api/**"
---
<!-- generated by lore; edit rules with review.py, not this file -->

- Use the repository layer for database access
- Return errors as problem+json
  • Files are marked as generated, rewritten on every sync, pruned when stale, and never imported back as rules.
  • Rules with hidden characters are not exported. A target that is a symlink, or an output folder that resolves outside the project, is refused.
  • Section-scoped rules need the section in the map; otherwise they are skipped with a warning (re-run memorize.py).
  • This writes into your repository, and there is no per-task selection, so it costs more tokens than MCP. See the static fallback.

Exit status

0 on success; 2 with error: … on stderr for an unknown project, a bad scope, a refused approval, or a missing id on edit. Unknown ids on approve, reject, pin and unapprove produce a warning and still exit 0.