lore:
0.1.0-alpha.5 GitHub

Guide

From nothing to a shipped feature

This guide sets up lore in a small app, writes the notes it already needs, and takes one feature, due dates on tasks, through the whole flow. Every block of output below is what lore printed.

Install

With Homebrew, on macOS or Linux, which brings ripgrep too:

Homebrew
brew install apisandipas/lore/lore

Without Homebrew, the install script puts a standalone lore in ~/.local/bin. It needs no Bun or Node, and checks the download against the release’s checksums.

Linux and macOS
curl -fsSL https://apisandipas.github.io/lore/install.sh | sh

lore finds citations with ripgrep, so install that too: brew install ripgrep or apt install ripgrep. Run the script again to upgrade; LORE_VERSION picks a release. Windows builds are on the releases page.

With Nix, the flake brings Bun and ripgrep itself:

try it without installing
nix run github:apisandipas/lore -- help

To keep it, add the flake as an input and install lore.packages.${system}.default. For work on lore itself, nix develop gives you bun and rg, and bun src/main.ts <command> runs from source.

Set up a repo

Run lore init at the root of a git repo. It writes the schema that says which kinds of note exist, a template for each, and a WORKFLOW.md that the agent skills read first. It never overwrites a file that is already there.

~/app
lore init
created .lore/schema.yml
created .lore/WORKFLOW.md
created .lore/templates/Spec.md
created .lore/templates/Decision.md
created .lore/templates/Effort.md

skills: found in ~/.claude/skills, ~/.agents/skills

Read .lore/WORKFLOW.md, then start a spec with lore-spec.

If the lore-* skills are missing, init says how to add them:

~/app
npx skills add apisandipas/lore

Your first notes

Start with what a newcomer would get wrong. Our app has an auth package, and a rule about money. A decision is the right note for a rule with a reason: lore new numbers it and fills in the template.

~/app
lore new Decision "Money is integer cents"
created docs/decisions/0003-money-is-integer-cents.md

Fill it in. The anchors field claims the code it governs, and the ## Decision section becomes the summary lore shows.

docs/decisions/0003-money-is-integer-cents.md
---
type: Decision
status: accepted
anchors: [pkg/billing/**]
---
# Money is integer cents

## Context
Floating-point dollars round differently on the server and in the browser.

## Decision
Money is a whole number of cents everywhere, converted to dollars only for display.

## Consequences
Every price field is an integer, and its name ends in `Cents`.

Code that follows a decision can say so. A comment with lore: and the note’s name is a citation; lore finds it, and lore check tells you if the note it names is ever retired.

pkg/billing/charge.ts
// Money is integer cents: lore:decision/0003
export function charge(customerId: string, amountCents: number) {
  if (!Number.isInteger(amountCents)) throw new Error("amountCents must be an integer");
  return gateway.charge(customerId, amountCents);
}

A directory with rules of its own gets a CONTEXT.md. It needs no frontmatter; its first paragraph is the summary.

pkg/auth/CONTEXT.md
# Auth package

Owns session issuance and validation. Never import from pkg/billing.

Ask what governs a file

Before you, or an agent, edit a file, ask lore about it. It reports every note that applies and why: a citation, an anchor, a CONTEXT.md above it, or a note one link away from one of those.

~/app
lore context pkg/billing/charge.ts
pkg/billing/charge.ts: 1 note

Money is integer cents  (Decision, accepted)
  docs/decisions/0003-money-is-integer-cents.md
  matched: cited at charge.ts:1; anchor pkg/billing/**
  Money is a whole number of cents everywhere, converted to dollars only for display.

--full adds each note’s body, for when a summary is not enough. Add --json to any command for a machine-readable version.

A feature, spec to ship

Now something new: tasks should have due dates. lore’s flow has four steps, and lore next always knows which one you are on. With nothing in progress, it says so:

~/app
lore next
nothing in progress; start a spec with lore-spec

1. Say what you want

With an agent, you say “use lore-spec, I want due dates on tasks”, and it interviews you. By hand, it is lore new Spec "Due dates" and an editor. Either way you end up with statements someone could test, and a list of what you are not doing:

docs/specs/due-dates.md
---
type: Spec
status: draft
anchors: [src/tasks/**]
---
# Due dates

A task can have a day it is due, and overdue tasks stand out.

## Behaviour
- A task may have a due date (a day, no time).
- Overdue tasks show in red at the top of the list.

## Out of scope
- Reminders or emails.

When it reads right, accept it. lore set checks the value against the schema before writing it.

~/app
lore set spec/due-dates status=accepted
updated docs/specs/due-dates.md
  status: accepted
lore next
next: lore-plan docs/specs/due-dates.md
  Due dates  (Spec, accepted)
  accepted spec with no effort

2. Plan the work

An effort is the plan: an approach, and a checklist of tasks small enough to finish and test in one sitting. --link fills in the spec it is planned against.

~/app
lore new Effort "Due dates" --link specs=spec/due-dates
created docs/efforts/due-dates.md
docs/efforts/due-dates.md
---
type: Effort
status: planned
specs: ["[[spec/due-dates]]"]
---
# Due dates

## Approach
Store the day as a real date column, sort in the query, and colour in the list view.

## Tasks
- [ ] Add a due_date column to tasks, with a migration
- [ ] Show a date picker when editing a task
- [ ] Sort overdue tasks first and colour them red

Once you agree with the plan, freeze it. lore records the version of each spec the plan was made against, and the effort is ready to build.

~/app
lore freeze effort/due-dates
froze docs/efforts/due-dates.md against:
  docs/specs/due-dates.md 34dd79dc3cec
lore next
next: lore-build docs/efforts/due-dates.md
  Due dates  (Effort, planned)
  0 of 3 done
  next item: Add a due_date column to tasks, with a migration

3. Build it, one task at a time

For each task: read the notes for every file you will touch, do the task, run the tests, tick the box. The next task is always the first open one, so you can stop at any point and lore next will know where you were tomorrow.

~/app
lore set effort/due-dates status=active
updated docs/efforts/due-dates.md
  status: active
lore context src/tasks/model.ts
src/tasks/model.ts: 1 note

Due dates  (Spec, accepted)
  docs/specs/due-dates.md
  matched: anchor src/tasks/**
  A task can have a day it is due, and overdue tasks stand out.
lore tick effort/due-dates
ticked docs/efforts/due-dates.md: Add a due_date column to tasks, with a migration
next: Show a date picker when editing a task  (1 of 3 done)

A choice someone might later undo deserves a decision. If the agent stores due dates as real dates because sorting text dates breaks, lore new Decision "Store due dates as dates" keeps that reason next to the code from now on.

4. Ship it

When every box is ticked, lore next names lore-ship. Shipping holds the work against each statement in the spec, makes sure lore check and the tests pass, brings the notes up to date, and sets the effort to done.

When the spec changes

Halfway through, you decide due dates can have a time after all. Edit the spec. Because the plan was frozen, lore notices the plan is now out of date, and stops sending you to build from it:

~/app
lore check
docs/efforts/due-dates.md:5: docs/specs/due-dates.md changed since this was frozen; review the plan, then run lore freeze effort/due-dates

7 notes, 2 citations: 1 problem
lore next
next: lore-plan docs/efforts/due-dates.md
  Due dates  (Effort, active)
  docs/specs/due-dates.md changed since it was planned

Revise the tasks, freeze again, and carry on. Once an effort is done, its frozen versions are history and check stops reporting them.

Keep it honest

lore check is the linter for your notes. Put it in CI: it exits 1 when something is wrong.

~/app
lore check
docs/specs/search.md:3: 'status' is 'finished'; expected one of draft, accepted, retired
docs/specs/search.md:7: link 'spec/indexing' matches no note
pkg/billing/charge.ts:6: citation 'lore:decision/0009' matches no note

8 notes, 3 citations: 3 problems