Your repo's knowledge in AgentMemory

You already write down how your code works for your coding agents: a CLAUDE.md at the root, an AGENTS.md in a service, a LEARNINGS.md next to the code that burned you. OPVS can read those files and keep each section as a lesson in AgentMemory, attached to the file and folder it came from. An agent about to change src/billing/ then gets the rules for src/billing/, not the whole rulebook.

Your repository stays the source of truth. You change a lesson by editing the file, and the next sync brings the change in.

There are two ways in. If a machine in your workspace indexes the repository, this happens by itself. If not, you run one command. Either way you need a project with the repository attached.

Which files OPVS reads

File Where Index job opvs memory sync
CLAUDE.md, AGENTS.md, GEMINI.md, LEARNINGS.md Any depth Yes Yes
.cursorrules, .windsurfrules Any depth Yes Yes
.cursor/rules/*.mdc Any depth Yes Yes
.github/copilot-instructions.md Any depth Yes Yes
.claude/rules/*.md Any depth Yes No
learnings/*.md Any depth Yes No

What is left out. Anything your .gitignore excludes, and anything your root .opvsindexignore excludes. So to keep a file out of AgentMemory, list it there. An index job also skips folders it never reads, such as node_modules and dist.

Limits. 512 KB per file, 400 files and 4 MB per sync. Past a limit the sync is marked truncated with the reason, and nothing is cut silently. When an index job hits a limit, it keeps your instruction files first, then LEARNINGS.md files, then learnings/*.md with the newest dates first.

How a file becomes lessons

Each ## section is one lesson, and the text before the first ## is one lesson too. Deeper headings (### and below) stay inside their section, and a ## inside a code block is not a heading. This src/billing/LEARNINGS.md gives three lessons:

# Billing

Everything here applies to the invoice pipeline.

## Round totals half-even

Round invoice totals half-even, never half-up.

### Why

The tax authority audits the rounding mode.

## Never call the tax API in a loop

It is rate limited per account. Batch the lines instead.
Lesson Id
The text before the first ## knowledge:<project-id>:src/billing/LEARNINGS.md
Round totals half-even, including its ### Why knowledge:<project-id>:src/billing/LEARNINGS.md#round-totals-half-even
Never call the tax API in a loop knowledge:<project-id>:src/billing/LEARNINGS.md#never-call-the-tax-api-in-a-loop

The project is part of the id, so two microservices that each have a root CLAUDE.md never overwrite each other, as long as each repository has its own project. If a file repeats a heading, the later ones get -2, -3 and so on.

Each lesson is anchored to its file and its folder. A lesson from src/billing/LEARNINGS.md sits on that file and on src/billing/, and one from a root file sits on the file and on the repository root. Ask about any file and you also get the lessons on the folders above it, so asking about src/billing/tax.py returns the rules in src/billing/ and your root CLAUDE.md. OPVS works out the anchors itself, for your own project, and ignores any a client sends.

An anchor is not the same as a pinned lesson. Pinned lessons come first in search results, and nothing in this sync pins one.

A lesson can also name the test that checks it, with a Checked by: line. See A lesson checked by a test.

When you change a file

A sync is a full picture of one repository at one commit. OPVS compares it with what it already holds for that project and branch.

You do this The next sync does this
Edit a section Replaces that lesson
Change nothing Nothing. Sending the same files twice changes nothing
Delete a section or a file Retracts the lesson: it is kept, but search no longer returns it
Put the section back Makes the lesson active again
Rename a heading, or move a file Adds new lessons under the new id and retracts the old ones

A truncated sync retracts nothing, because a file missing from it may only have been past a limit.

Where your files go

Only into your own workspace. The workspace comes from your token, never from what the request says. Another workspace cannot read these lessons, and a project that is not yours answers 404, the same as one that does not exist.

This is stored text, unlike the code index. The code index keeps structure only. This feature keeps the text of the files listed above, and sends each lesson's text to an embedding model so that search can find it by meaning. Keep secrets out of these files, and use .opvsindexignore for any file you do not want stored.

Way 1: attach a repository

If a build machine in your workspace runs your index jobs, there is nothing to set up. Attach the repository and a branch to a project, and every index of that branch brings your knowledge files in with it.

If this sync fails, your index still completes and your existing lessons stay as they were. No route shows you the sync's result yet, so to check it, search for something you know is in one of your files:

opvs memory search "round totals" --type knowledge

Way 2: opvs memory sync

Use this when no machine indexes your repository. You still need a project with the repository attached: without one the command answers project not found.

# 1. Find your project id
opvs projects list

# 2. See what would be sent. This sends nothing.
opvs memory sync --project <project-id> --dry-run

# 3. Send it
opvs memory sync --project <project-id>

The command reports what it did. For example:

Files: 12
Entries: 64
Upserted: 64
Unchanged: 0
Retracted: 0
Truncated: no

Entries is the number of lessons in this sync, Upserted the new or changed ones, and Retracted the ones whose section or file is gone.

Option What it does
--project <project-id> Required. The project the repository is attached to
--branch <name> The branch to record. Defaults to your current branch
--dry-run Lists the files that would be sent, and sends nothing
--allow-dirty Syncs files with uncommitted changes, as they are on disk, against the current commit

Your token needs memory:ingest, and searching needs memory:read. New tokens ask for both by default, so you only need to act if the command tells you to. See Auth Commands.

Without an index, lessons are stored but not attached to code. With no index, OPVS has no code to attach them to. Search by text still finds them, but asking about a file does not, and the Code view shows no counts, until the repository has been indexed and synced again.

Three things to get right

  • Sync the whole repository, not a folder. opvs memory sync apps/api sends only that folder, and OPVS treats every sync as the whole repository. Each lesson outside apps/api/ is then retracted. Running the plain command from inside a folder is safe: it starts from the repository root.
  • Sync the attached branch. The branch is not part of a lesson's id, so a project holds one copy of each section. Syncing a feature branch replaces the matching lessons with that branch's text.
  • Use one way per project. If an index job already reads your repository, you do not need this command. It does not send .claude/rules/*.md or learnings/*.md, so running it on an indexed project retracts those lessons until the next index restores them.

If the command stops

You see What it means What to do
Refusing to sync a dirty worktree You have uncommitted changes Commit them, or pass --allow-dirty
No repository knowledge files to send. No file matched. Nothing is sent, so nothing is retracted either Check the table of files, your ignore files, and --dry-run
Knowledge path is not a regular file: CLAUDE.md The file is a symbolic link, often CLAUDE.md pointing at AGENTS.md. The whole sync stops Replace the link with a real file. An index job handles links for you, sending the file once
Knowledge file is not valid UTF-8: <path> The file is not UTF-8 text. The whole sync stops Save it as UTF-8, or exclude it
Could not read the current branch You are on a detached commit, as many CI jobs are Pass --branch <name>
No such remote 'origin' The repository has no origin remote Add one
request a token that includes memory:ingest Your token lacks the scope Get a token with memory:ingest and run it again
project not found The id is wrong, the project belongs to another workspace, or it has no repository attached Check the id, and attach the repository

How a session finds them

Search by words. This works in any repository:

opvs memory search "tax API" --type knowledge

Ask about the code you are about to change. This returns the lessons on those files and on the code around them:

opvs memory near src/billing/tax.py --project <project-id>

See them in the dashboard. Open a project, open the project canvas and select Code. A directory, file or symbol that has lessons shows how many, as 3 memories.

Your coding agent can use these reads too: opvs memory install <runtime> connects codex, claude-code, cursor, opencode or cline to OPVS memory. To call them from your own code, use the routes under Lessons near the code.

Powered by OPVS