The install path
Seven steps from nothing to a memory that answers you.
Do them in order. Each one gives you something you can check before moving on, so you never get three steps deep before finding out something went wrong.
Before you start
You need two things installed, and a terminal open. On Windows that is PowerShell, on macOS and Linux it is Terminal. Everything below is typed there.
| What | Why RE-call needs it | Where |
|---|---|---|
| Python 3.11 or newer | RE-call is a Python package. 3.11 is the floor, and 3.12 to 3.14 are supported. | python.org |
| Docker Desktop | Your memory is stored in PostgreSQL with the pgvector extension. Docker gives you both, correctly configured, in one command. | docker.com |
On Windows, install Python from python.org
Not from the Microsoft Store. The Store build sandboxes file paths in ways that break indexing a folder on disk.
Check both are ready. Two commands, two version numbers back.
python --versiondocker --version
python3 --versiondocker --version
python3 --versiondocker --version
You should see
Python 3.12.7 Docker version 27.3.1, build ce12230
One convention for the whole page
Windows uses python, macOS and Linux use python3. Pick your tab once at the top of any command block and every other block on the site switches with it.
Version number missing or too old? Fixing Python and Docker.
Start the database
RE-call keeps your memory in PostgreSQL and searches it with pgvector. This one command downloads a PostgreSQL 18 image that already has pgvector built in, and starts it on your machine.
docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 pgvector/pgvector:pg18docker run -d --name recall-db -e POSTGRES_USER=recall -e POSTGRES_PASSWORD=recall -e POSTGRES_DB=recall -p 5432:5432 pgvector/pgvector:pg18The first run downloads the image, which takes a minute or two. After that it starts instantly.
Check it is running
docker psCONTAINER ID IMAGE STATUS PORTS NAMES a1b2c3d4e5f6 pgvector/pgvector:pg18 Up 4 seconds 0.0.0.0:5432->5432/tcp recall-db
Why a container instead of installing PostgreSQL properly
Because pgvector is an extension, and installing it against a native PostgreSQL means matching compiler toolchains to server versions. The container ships the pair already working. If you already run PostgreSQL and know how you want to add the vector extension, use your own instance and substitute its connection string everywhere this guide writes postgresql://recall:recall@localhost:5432/recall.
Your data lives inside the container. To keep it across a container rebuild, add -v recall_pgdata:/var/lib/postgresql to the command above.
Port already in use, or Docker not running? Database problems.
Install RE-call
One package from PyPI. The fastembed part pulls in a small embedding model that runs on your own machine, so building and searching memory never sends your text anywhere.
python -m pip install "recall-rag[fastembed]"python3 -m pip install "recall-rag[fastembed]"python3 -m pip install "recall-rag[fastembed]"The package is recall-rag, not recall
The name recall on PyPI belongs to an unrelated project. Installing both into the same environment breaks the import. You install recall-rag, and in code and commands it is spelled recall.
Check it installed
python -m recall.cli --helppython3 -m recall.cli --helppython3 -m recall.cli --helpA usage message listing commands such as setup, schema, index and search means you are ready.
What the square brackets mean, and the other options
The brackets are optional extras. Plain recall-rag installs with no embedding model at all, which leaves you with a placeholder that is only useful for testing plumbing. [fastembed] adds the local model this guide uses, roughly 130 MB, downloaded the first time you index something.
Others exist for later: [mcp] for the Claude Code server in step 7, [rerank] for a quality upgrade on results, [voyage] for a cloud embedder. You can add them at any time by re-running the install with a longer bracket list.
Command not found, or a permissions error? Install problems.
Run the setup wizard
This asks you a short series of questions, then writes your answers to a .env file in the current folder so you never have to repeat them. Run it from whichever folder you want your memory to live in.
It sets the database up for you
Once you pick an embedder the wizard creates the tables at the matching vector width, printing Prepared 'chunks' for 384 dimensions. as it goes. There is no separate schema command to run first. If it cannot reach the database it says so and tells you the command to run by hand.
python -m recall.cli setuppython3 -m recall.cli setuppython3 -m recall.cli setupIt opens by measuring your machine, then asks its questions. Here is every one of them, with the answer to give on a first install.
| It asks | Answer | Because |
|---|---|---|
| Is data security necessary for this installation? | Y | Keeps every cloud option hidden, so nothing you index can leave the machine. |
| Choose the embedder | 2, fastembed | The local model you installed in step 2. The wizard prepares the database at its 384 wide vector size for you. |
| Choose whether to enable reranking | 1, none | Reranking improves result quality but downloads another model and slows each search. Add it once the basics work. |
| Choose the sparse retrieval backend | 1, postgres fts | Uses the database you already have. The alternative needs an NVIDIA GPU. |
| Enable the entailment judge? | N | An extra check on whether a result really supports an answer. Useful later, another model download now. You may not be asked this at all. |
| Enable the optional reasoning arm? | N | Records provider settings for a reasoning arm that the shipped tools do not call yet. The default reasoning tools stay deterministic either way. Because you answered yes to security, only a local server such as Ollama is offered, and it also needs the extract extra. Say no now and add it later once you have one running. This question exists from version 0.9.5 onward: on 0.9.4 you will not see it. |
| Scaffold CLAUDE.md and a memory/ directory? | Y | Creates the folder your memory files go in, and the instructions Claude reads. Step 6 uses both. |
| Calibrate the threshold now? | N | Calibration measures how confident a result must be before RE-call will answer from it. It needs example questions you have not written yet. Come back to it once you have real memory. |
You should see, at the end
Calibration skipped. Run recall calibrate later with a labeled query file when you have one. Wrote .env Updated CLAUDE.md Wrote memory\MEMORY.md Indexed 1 chunks from 1 files in memory
What you now have on disk
.env holds your choices. memory/ is where your memory files go. memory/MEMORY.md is a starter index explaining the file format. CLAUDE.md tells Claude to search memory before it answers, which matters in step 7.
What happens if you answer differently
Answering n to the security question unlocks cloud embedders and offers to store API keys. Those send your text to a third party, which is a decision worth making deliberately rather than during a first install.
Choosing a different embedder changes the vector width. On a fresh database the wizard simply prepares the tables at whatever width you picked. On a database that already holds memory at another width it will not silently rebuild it: rather than failing later, it refuses and stops. It does not re-ask, and it names no command. Choose an embedder matching the existing schema, or point setup at a fresh table name or database.
You can re-run setup at any time. It rewrites only its own block in .env, so anything you added yourself survives.
Wizard exited early, or looped on the embedder question? Setup wizard problems.
Let it answer you
One line to add to .env. Skip it and your first search will fail with a Python error rather than a useful message, so do it now.
Add-Content .env "RECALL_TRUST_MODE=development"echo "RECALL_TRUST_MODE=development" >> .envecho "RECALL_TRUST_MODE=development" >> .envThis is the step people miss
Out of the box RE-call refuses to answer from a corpus whose confidence threshold has never been measured. That is deliberate: it is the whole point of the product. But you have not measured one yet, so without this line every search stops. Development mode says "I know this threshold is a placeholder, show me the results anyway", and every result you get back will be stamped as uncertified so you cannot forget.
What you are trading away, and how to get it back
In development mode RE-call falls back to a demonstration threshold that is bound to no tenant, no generation and no corpus. It is a placeholder chosen to let you see the machinery work, not a measurement of your data. Every search prints a warning saying exactly that, and every result is tagged DEGRADED with the reason. On a fresh install the reason is INDEX_NOT_READY, because no immutable generation has been built yet; CALIBRATION_MISSING is the related code you see once that part is in place but the threshold still has not been measured.
Measuring a threshold against your own corpus is the calibration page, and it is worth doing once your memory holds something you care about being right. Read that page before you remove this line: leaving development mode needs more than running the calibration command once.
Give it a memory
A memory is a markdown file. Save this one as memory/rate-limits.md, in the memory/ folder the wizard created.
--- name: api-rate-limit description: The request ceiling we agreed for the public API. metadata: type: project --- Clients may issue 100 requests per minute against the public API. We agreed this on 12 August 2026, after the load test showed the gateway degrading above 140. Bursts up to 150 are tolerated for 10 seconds before throttling starts.
Then load it into the database.
python -m recall.cli index memory/python3 -m recall.cli index memory/python3 -m recall.cli index memory/You should see
indexed 1 chunks from 1 files, 1 unchangedWhat "1 unchanged" means
The wizard already indexed memory/MEMORY.md when it created the folder, and that file has not changed since, so this run skips it. The one new chunk is your rate-limit note. Re-running index only does work for files that actually changed, which is why it is safe to run again whenever you edit something.
What indexing actually does to your file
RE-call reads the markdown, splits it into chunks of a few sentences, converts each chunk into a vector using the local model, and stores the text and the vector together. Searching later compares your question against those vectors to find text that means something similar, which is why it can answer a question phrased quite differently from the note.
The block at the top between the dashes is frontmatter. name and description help you find the file again, and type records what kind of memory it is. Re-running index after editing a file updates it rather than duplicating it.
Dimension mismatch, or nothing indexed? Indexing problems.
Ask, and watch it refuse
Two questions. The first is answerable from what you just indexed. The second is not, and what RE-call does with it is the reason the project exists.
python -m recall.cli search "how many requests per minute can a client make?"python3 -m recall.cli search "how many requests per minute can a client make?"python3 -m recall.cli search "how many requests per minute can a client make?"You should see something like
[development] using an UNCERTIFIED demonstration threshold of 0.5. This is not a calibration: it is bound to no tenant, generation or corpus, and production refuses rather than assuming it. [DEGRADED:INDEX_NOT_READY] query='how many requests per minute can a client make?' index: embedding=bge-small-symmetric-v1 retrieval=legacy generation=legacy ok conf=1.00 cos=0.802 rate-limits.md 'Clients may issue 100 requests per minute against th' chunk_id='cdf9da4656aa6aef8b0af6a739d63fe2' ordinal=0 valid_from=-
Notice that you asked about "requests per minute" and the note says "issue 100 requests per minute". It matched on meaning, not on the words. The DEGRADED tag is expected here and is not an error: it is RE-call recording that it is running on a placeholder threshold rather than one measured on your corpus.
Now ask something your memory has no answer to at all.
python -m recall.cli search "how do we handle penguins on Mars?"python3 -m recall.cli search "how do we handle penguins on Mars?"python3 -m recall.cli search "how do we handle penguins on Mars?"You should see an abstention
[ABSTAIN GAP DEGRADED:INDEX_NOT_READY] query='how do we handle penguins on Mars?' index: embedding=bge-small-symmetric-v1 retrieval=legacy generation=legacy reason: no hit above the calibrated confidence threshold (probable corpus gap) low_confidence conf=0.30 cos=0.458 rate-limits.md 'Clients may issue 100 requests per minute against th' chunk_id='cdf9da4656aa6aef8b0af6a739d63fe2' ordinal=0 valid_from=-
That refusal is the feature
Your rate-limit note is still the closest thing in the corpus to that question, and an ordinary vector search would have handed it back as the answer. Closest is not the same as correct. RE-call scored it, found nothing clearing the threshold, and abstained instead. Note that the note is still listed, marked low_confidence: you are told what was found and why it was not good enough, rather than being given a bare refusal.
Try a harder question, and watch this get less impressive
Ask what is our refund policy? instead and you will probably not get an abstention. On a corpus this small that question scores about 0.58 against the rate-limit note, which clears the placeholder threshold of 0.5, so RE-call answers with a note that has nothing to do with refunds.
That is not a bug, and it is worth understanding before you trust this on real material. The threshold in use was not measured on your corpus; it is a demonstration value. Deciding where that line actually belongs, for your data and your embedder, is what calibration does. Until then, expect the boundary between answering and abstaining to be approximate.
Your install works. What follows is optional, and this is a reasonable place to stop and go fill your memory with real material.
Connect Claude Code
This turns your memory into a tool Claude can call by itself, so it checks what you have already decided before it answers, instead of you pasting context into a chat.
First add the server component.
python -m pip install "recall-rag[fastembed,mcp]"python3 -m pip install "recall-rag[fastembed,mcp]"python3 -m pip install "recall-rag[fastembed,mcp]"Then save this as .mcp.json, in the same folder as your .env.
{
"mcpServers": {
"recall": {
"command": "python",
"args": ["-m", "recall_mcp.server"],
"env": {
"RECALL_SERVING_DSN": "postgresql://recall:recall@localhost:5432/recall",
"RECALL_TENANT": "default",
"RECALL_TRUST_MODE": "development"
}
}
}
}The settings have to be repeated here
The MCP server does not read your .env file. That is why the connection string and the development mode appear again inside this JSON. On macOS and Linux, change "command": "python" to "python3".
Confirm Claude can see it
Start Claude Code in that folder and ask it to list its tools, or run /mcp. You are looking for a server named recall offering recall_search, recall_index and recall_stats among others.
What Claude will now do differently
The CLAUDE.md the wizard wrote tells Claude to call recall_search before answering questions about your project, to respect an abstention rather than guessing around it, and to write durable facts into memory/ as it learns them. That last part is what makes the memory grow without you maintaining it by hand.
There is more to this than one step can hold: what each tool returns, how to make Claude cite its evidence, and how to stop it writing junk into your corpus. That is the Claude Code page.
Server not appearing in Claude? Claude Code problems.
Where to go from here
- Fill your memory What makes a good memory file, how to organise a corpus that grows, and what not to put in it. →
- Work with Claude Every tool the server exposes, and how to get Claude checking memory before it acts. →
- Measure your threshold Replace the placeholder confidence number with one measured on your own corpus, and drop development mode. →
- Something broke The errors this install produces most often, and what each one actually means. →