Lore

Quickstart

Self-host Lore with Docker and run the write → pack loop.

All you need is Docker (with Compose). lore init runs from the published image and prints a docker-compose file — nothing to clone or build. The default extractor is an offline, deterministic fixture, so the whole write → pack loop runs with no API key of your own.

Start the stack

docker run --rm ghcr.io/lore-gpt/lore:v0.0.3 init > docker-compose.ymldocker compose up -d --wait

up applies migrations and runs a one-shot that provisions a first project, writing its id and API key to ./.lore/credentials. The generated compose is pinned to the image's version, so init and the stack it scaffolds never drift.

On Windows PowerShell, redirect with docker run --rm ghcr.io/lore-gpt/lore:v0.0.3 init | Set-Content docker-compose.yml.

Load your credentials

set -a; source ./.lore/credentials; set +a   # sets LORE_PROJECT_ID and LORE_API_KEY

The credentials file holds a key. If ./.lore sits inside a git repository, add .lore/ to your .gitignore.

Check health

Unauthenticated, so orchestrators can probe it:

curl localhost:8080/healthz
# {"status":"ok","version":"v0.0.3","db":"ok","queue":"ok","workmem":"ok","embedder":"fixture-embed-v1@64"}

Write an event, then pack the context

A run groups a stream of events; the project comes from your key, never the body. Write an event — the response carries a server-assigned seq — then pack a budget-fit context for the run.

# Create a run
RUN_ID=$(curl -sX POST localhost:8080/v1/runs \
  -H "Authorization: Bearer $LORE_API_KEY" -H "Content-Type: application/json" \
  | grep -o '"run_id":"[^"]*"' | cut -d'"' -f4)

# Append an event → returns { "event_id": "...", "seq": 1 } (HTTP 202)
curl -X POST localhost:8080/v1/events \
  -H "Authorization: Bearer $LORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"run_id\":\"$RUN_ID\",\"agent_id\":\"researcher\",\"payload\":{\"note\":\"auth flow moved to v2\"}}"

# Pack — min_seq asserts read-your-writes
curl -sX POST localhost:8080/v1/pack \
  -H "Authorization: Bearer $LORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"run_id\":\"$RUN_ID\",\"query\":\"auth work\",\"min_seq\":1}"

Install the SDK with npm install @loregpt/sdk, then:

// Adapted from clients/typescript/examples/hero.ts (compile-tested in CI).
import { LoreClient } from "@loregpt/sdk";

const lore = new LoreClient({ apiKey: process.env["LORE_API_KEY"] ?? "" });

const { runId } = await lore.createRun();
const { seq } = await lore.write({
  runId,
  agentId: "researcher",
  content: "Auth flow moved to v2 — PR #42 merged",
});

const pack = await lore.pack({
  runId,
  query: "current state of auth work",
  minSeq: seq,
  tokenBudget: 2000,
});

pack.coveredSeq; // ≥ seq once distilled; until then the write is in the raw tail — either way, reflected
pack.savedTokens; // token savings vs raw history — a coarse estimate; small packs may round to 0

Install the SDK with pip install loregpt, then:

# Adapted from clients/python/examples/hero.py (type-checked in CI).
import os

from loregpt import LoreClient

lore = LoreClient(api_key=os.environ["LORE_API_KEY"])

run = lore.create_run()
result = lore.write(
    run_id=run.run_id,
    agent_id="researcher",
    content="Auth flow moved to v2 - PR #42 merged",
)

pack = lore.pack(
    run_id=run.run_id,
    query="current state of auth work",
    min_seq=result.seq,
    token_budget=2000,
)

covered_seq = pack.covered_seq  # >= result.seq once distilled; until then the write is in the raw tail
saved_tokens = pack.saved_tokens  # a coarse estimate vs raw history; small packs may round to 0

The read-your-writes contract: keep the seq a write returns — passing it as min_seq to a later pack guarantees the pack reflects that write. Anything newer than the server's distilled checkpoint comes back as a raw tail until extraction catches up, and the response's covered_seq tells you exactly how far the distilled view has advanced. See Core concepts for the full model.

Inspect what's stored (optional)

Read-only and project-scoped — browse or lexically search the distilled memories, or replay a run's pack trace. Search uses only the lexical index, so it needs no embedding model:

curl -s "localhost:8080/v1/memories?limit=10"  -H "Authorization: Bearer $LORE_API_KEY"   # browse (keyset-paginated)
curl -s "localhost:8080/v1/memories?q=auth"    -H "Authorization: Bearer $LORE_API_KEY"   # lexical search
curl -s "localhost:8080/v1/runs/$RUN_ID/trace" -H "Authorization: Bearer $LORE_API_KEY"   # this run's pack history

The compose stack also starts a read-only web Inspector at localhost:3000 — browse memories and run traces, bound to localhost only.

Tear it down

docker compose down -v

Prefer to run the binary directly? Every step above is also a lore subcommand for running outside Docker — lore provision (create a project and mint a key), lore pack (fetch a context pack), and lore doctor (check the database, schema, and server), with lore serve and lore worker running the API and the extraction worker. Point LORE_DATABASE_URL at your own Postgres and run lore --help for the full list. See Configuration for every setting.

Port 8080 already in use? Pick a free host port; the container still listens on 8080: LORE_HTTP_PORT=18080 docker compose up -d --wait.

On this page