Continual learning layer for coding agents and software projects.
Project description
Continual learning layer for coding agents
Lerim is a continual learning layer that gives coding agents persistent memory across sessions. It watches your agent conversations (Claude Code, Codex, Cursor, OpenCode, ...), extracts decisions and learnings, and stores them as plain markdown files that both humans and agents can read. Memories are refined offline over time through merging, deduplication, archiving, and decay-based forgetting. You can query stored memories anytime to bring relevant past context into your current session.
Summary
Lerim is file-first and primitive-first.
- Primitive folders:
decisions,learnings,summaries - Project memory first:
<repo>/.lerim/ - Global fallback memory:
~/.lerim/ - Search default:
files(no index required) - Orchestration runtime:
pydantic-ailead agent + read-only explorer subagent - Extraction/summarization:
dspy.RLMrole-configured models (default OpenRouterx-ai/grok-4.1-fast) - Graph source of truth: explicit id/slug references (and
relatedwhen present)
This keeps memory readable by humans and easy for agents to traverse.
Lead flow:
- Extract candidates from transcript archive.
- Lead agent orchestrates with runtime tools and delegates a read-only explorer subagent.
- Lead runs deterministic decision policy for
add|update|no-op. - Lead writes memory only through boundary-enforced runtime write/edit tools.
syncstays lightweight;maintainruns offline memory refinement (merge duplicates, archive low-value entries, consolidate related memories, apply time-based decay).
Sync path
The sync path processes new agent sessions: reads transcript archives, extracts decision and learning candidates via DSPy, deduplicates against existing memories, and writes new primitives to the memory folder.
Maintain path
The maintain path runs offline refinement over stored memories: merges duplicates, archives low-value entries, consolidates related memories, and applies time-based decay to keep the memory store clean and relevant.
Quick start
1. Install
pip install lerim
Lerim's extraction pipeline requires Deno:
brew install deno
2. Connect your agent platforms and start the learning loop
lerim connect auto # detect Claude Code, Codex, Cursor, OpenCode sessions
lerim daemon # sync sessions + maintain memories in a continuous loop
That's it. Lerim now watches your sessions, extracts decisions and learnings, and refines them over time.
3. Teach your agent about Lerim
Install the Lerim skill so your agent knows how to query past context:
npx skills add lerim-dev/lerim-cli
This works with Claude Code, Codex, Cursor, Copilot, Cline, Windsurf, OpenCode, and other agents that support skills.
4. Get the most out of Lerim
At the start of a session, tell your agent:
Check lerim for any relevant memories about [topic you're working on].
Your agent will run lerim chat or lerim memory search to pull in past decisions and learnings before it starts working.
Dashboard
The dashboard gives you a local UI for session analytics, memory browsing, and runtime status.
Run it locally
# simple
lerim dashboard
# explicit host/port
python -m lerim dashboard --host 127.0.0.1 --port 8765
Then open http://127.0.0.1:8765.
Tabs
- Overview: high-level metrics and charts (sessions, messages, tools, errors, tokens, activity by day/hour, model usage).
- Runs: searchable session list (50/page) with status and metadata; open any run in a full-screen chat viewer.
- Memories: library + editor for memory records (filter, inspect, edit title/body/kind/confidence/tags).
- Pipeline: sync/maintain status, extraction queue state, and latest extraction report.
- Settings: dashboard-editable config for server, model roles, and tracing; saves to
~/.lerim/config.toml.
Notes
- Top bar filters (
Agent,Scope) update dashboard metrics and run listings. - Graph Explorer code is kept in the project but currently hidden in the UI.
CLI reference
Full command reference: skills/lerim/cli-reference.md
lerim connect auto # detect and connect platforms
lerim sync # one-shot: sync sessions + extract
lerim maintain # one-shot: merge, archive, decay
lerim daemon # continuous sync + maintain loop
lerim chat "Why did we choose this?" # query memories
lerim memory search "auth pattern" # keyword search
lerim memory list # list all memories
lerim memory add --title "..." --body "..." # manual memory
lerim memory reset --scope both --yes # wipe and start fresh
lerim dashboard # local web UI
lerim status # runtime state
Development
uv venv && source .venv/bin/activate
uv pip install -e .
tests/run_tests.sh unit
tests/run_tests.sh all
Configuration
TOML-layered config (low to high priority):
src/lerim/config/default.toml(shipped with package -- all defaults)~/.lerim/config.toml(user global)<repo>/.lerim/config.toml(project overrides)LERIM_CONFIGenv var path (explicit override, for CI/tests)
API keys come from environment variables only (ZAI_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY, optional ANTHROPIC_API_KEY).
Default role model config (from src/lerim/config/default.toml):
lead:provider=openrouter,model=x-ai/grok-4.1-fastexplorer:provider=openrouter,model=x-ai/grok-4.1-fastextract:provider=openrouter,model=x-ai/grok-4.1-fast,sub_model=x-ai/grok-4.1-fastsummarize:provider=openrouter,model=x-ai/grok-4.1-fast,sub_model=x-ai/grok-4.1-fast
Tracing (OpenTelemetry)
Lerim uses PydanticAI's built-in OpenTelemetry instrumentation for agent observability. Stderr logs are kept minimal; detailed traces (model calls, tool calls, tokens, timing) go through OTel spans instead.
One-time setup:
uv pip install logfire
logfire auth
logfire projects new
Enable tracing:
# env var (quick toggle)
LERIM_TRACING=1 lerim sync
# or in config
# .lerim/config.toml
[tracing]
enabled = true
View traces at https://logfire.pydantic.dev.
Config options ([tracing] in TOML):
| Key | Default | Description |
|---|---|---|
enabled |
false |
Enable tracing (or set LERIM_TRACING=1) |
include_httpx |
false |
Capture raw HTTP request/response bodies |
include_content |
true |
Include prompt/completion text in spans |
Connecting coding agents
Lerim ingests session transcripts from your coding agents to extract decisions and learnings. The lerim connect command registers an agent platform so Lerim knows where to find its sessions.
Supported agents
| Platform | Session store | Format |
|---|---|---|
claude |
~/.claude/projects/ |
JSONL files |
codex |
~/.codex/sessions/ |
JSONL files |
cursor |
~/Library/Application Support/Cursor/User/globalStorage/ (macOS) |
SQLite state.vscdb, exported to JSONL cache |
opencode |
~/.local/share/opencode/ |
SQLite opencode.db, exported to JSONL cache |
How to connect
Auto-detect and connect all supported platforms at once:
lerim connect auto
Or connect a specific platform:
lerim connect claude
lerim connect codex
lerim connect cursor
lerim connect opencode
List currently connected platforms:
lerim connect list
Disconnect a platform:
lerim connect remove claude
Custom session path
If your agent stores sessions in a non-default location, use --path to point Lerim to the correct folder:
lerim connect claude --path /custom/path/to/claude/sessions
lerim connect cursor --path ~/my-cursor-data/globalStorage
The path is expanded (~ is resolved) and must exist on disk. This overrides the auto-detected default for that platform.
Search
Retrieval is file-first: scan markdown memory files directly. No index required.
Memory layout
Project scope:
<repo>/.lerim/
config.toml # project overrides
memory/
decisions/
learnings/
summaries/
YYYYMMDD/
HHMMSS/
{slug}.md
archived/
decisions/
learnings/
meta/
traces/
sessions/
workspace/
sync-<YYYYMMDD-HHMMSS>-<shortid>/
extract.json
summary.json
memory_actions.json
agent.log
subagents.log
session.log
maintain-<YYYYMMDD-HHMMSS>-<shortid>/
maintain_actions.json
agent.log
subagents.log
index/ # reserved
Global fallback scope follows the same layout under ~/.lerim/.
Primitive frontmatter (lean)
decision:id,title,created,updated,source,confidence,tagslearning:id,title,created,updated,source,confidence,tags,kindsummary:id,title,description,date,time,coding_agent,raw_trace_path,run_id,repo_name,created,source,tags
All metadata lives in frontmatter — no sidecars.
Reset policy
Memory reset is explicit and destructive.
lerim memory reset --scope project|global|both --yes- Deletes
memory/,workspace/, andindex/under selected root(s), then recreates canonical folders. --scope project: resets<repo>/.lerim/only.--scope global: resets~/.lerim/only (includes sessions DB).--scope both(default): resets both.- Sessions DB lives in global
index/, so--scope projectalone does not reset sessions.
Fresh start:
lerim memory reset --yes # wipe everything
lerim sync --max-sessions 5 # re-sync newest conversations
Docs
- Runtime architecture:
docs/architecture.md - CLI reference:
skills/lerim/cli-reference.md - Agent skill:
skills/lerim/SKILL.md
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lerim-0.1.0.tar.gz.
File metadata
- Download URL: lerim-0.1.0.tar.gz
- Upload date:
- Size: 141.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f2c0daf085c334056f11a78511a5a9b4dbb19495fa7b87d0e7c38bfb636daca
|
|
| MD5 |
6cd4ce2e287a70900b15784902b971ed
|
|
| BLAKE2b-256 |
90b2dc79418073f84f36ad1fc595eae86ab5a1cd0c4552ae48c073869be8b62f
|
File details
Details for the file lerim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lerim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 114.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01907a4ce0c850d34d879d73009d78bc892d2329afd98d8216e94cd8b3f3a5eb
|
|
| MD5 |
cc9db848ba7e6a6b57d3681fca88e708
|
|
| BLAKE2b-256 |
29dd292a8c5bc572bbc2f7f42ec1ba22a6d8ad2f543c715cc667046b1c9c2d89
|