"use bun not npm", "be terse").
What gets stored
Four kinds:
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.
Scopes
Two databases:
Read scope controls which DBs the agent sees:
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
Config
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. Foropenai/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 SDKprovider/model id. Verified routes:
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.
