> ## Documentation Index
> Fetch the complete documentation index at: https://soulforge.proxysoul.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory

> Cross-session memory — preferences, decisions, and gotchas that follow you between sessions.

Memory is SoulForge's long-term store. It remembers your preferences, your project's decisions, and the sharp edges you've hit before — and surfaces them automatically when they're relevant. You don't have to ask.

Memory is **per-project by default**, with an opt-in **global** scope for cross-project preferences (`"use bun not npm"`, `"be terse"`).

## What gets stored

Four kinds:

| Category   | Example                                                |
| ---------- | ------------------------------------------------------ |
| `pref`     | "use bun not npm", "be terse"                          |
| `decision` | "switched to zustand — redux was too much boilerplate" |
| `gotcha`   | "JWT expiry uses container clock, drifts in prod"      |
| `context`  | "legacy/ deletes next sprint — don't touch"            |

The agent writes these proactively when you share a preference, make a choice with a reason, or hit a non-obvious bug. You can also browse and edit them yourself.

## How recall works

Before each turn, SoulForge looks at your prompt and which files you've been editing, then injects up to **3 relevant memories** silently. The agent sees them and adjusts. You don't have to type `/memory` or remember what's stored.

If nothing's relevant, nothing's injected — memory earns its prompt slot every turn or it doesn't take one.

## Browser — `/memory`

Type `/memory` to open the browser. Five tabs:

* **All** — every memory across project + global. Pin, soft-delete, or supersede per row.
* **Hidden** — soft-deleted entries, restorable forever.
* **Cleanup** — *Quick* (dupes + dead file refs) and *Stale* (low-signal candidates) for manual review.
* **SIM** — clusters of related memories.
* **Settings** — read & write scopes.

Nothing is ever truly deleted. Soft-delete only, restorable forever.

## Scopes

Two databases:

| Scope   | Location                 | Use for                                      |
| ------- | ------------------------ | -------------------------------------------- |
| Project | `.soulforge/memory.db`   | code-specific decisions, file-scoped gotchas |
| Global  | `~/.soulforge/memory.db` | cross-project preferences, your style        |

Read scope controls which DBs the agent sees:

```
all      project + global (default)
project  only this repo
global   only your preferences
none     turn recall off
```

## Pinning

Pin a memory to keep it from being surfaced in cleanup suggestions and to lift its ranking in recall. Useful for non-obvious rules you want to keep close.

## Languages

Memory works in any script — English, CJK, Arabic, Cyrillic, mixed-script identifiers. Searches use a word index plus a character n-gram index together, so paraphrases and non-Latin queries both hit.

## Commands

| Command   | Description      |
| --------- | ---------------- |
| `/memory` | Open the browser |

## Config

```json theme={null}
{
  "memory": {
    "embeddingModel": "openai/text-embedding-3-small"
  }
}
```

Optional. Sets a real embedding provider for semantic recall. Default is a built-in offline embedder (hashbag-v2) that works without any API calls, good enough for word-overlap paraphrases.

### Do I need an API key?

Yes, if you set a provider model. The embedder runs through the AI SDK, so it needs that provider's key. For `openai/text-embedding-3-small` that is your OpenAI key. Without a valid key the embedder fails its startup probe and silently falls back to the offline embedder. Memory keeps working either way.

### Which models can I use?

Any AI SDK `provider/model` id. Verified routes:

| Provider       | Model                                                            |
| -------------- | ---------------------------------------------------------------- |
| OpenAI         | `openai/text-embedding-3-small`, `openai/text-embedding-3-large` |
| Google         | `google/text-embedding-004`                                      |
| Vercel Gateway | `vercel_gateway/openai/text-embedding-3-small`                   |
| LLM Gateway    | `llmgateway/openai/text-embedding-3-small`                       |
| OpenRouter     | `openrouter/openai/text-embedding-3-small`                       |

Providers with no embedding API (Anthropic, xAI, Groq, DeepSeek, Mistral, Bedrock, proxy, codex, copilot) always fall back to the offline embedder. Local providers (Ollama, LM Studio) and custom OpenAI-compatible providers work only if you set `embeddingModel` explicitly.

You do not have to set this at all. When unset, it auto-resolves in order: `taskRouter.semantic`, a default for your active chat provider, then the offline embedder.

### How do I check it is working?

Open `/memory`, go to the **Settings** tab, and read the **Embedding** row. It shows the active model and where the choice came from, or `offline (hashbag-v2)` when the offline embedder is in use. If you set a provider model but the row still says offline, the key is missing or the model was rejected.
