Quickstart
Install SmartMemory and get from nothing to a working, searchable memory in about two minutes.
SmartMemory gives your AI assistant a memory that survives across sessions. You capture the decisions, preferences, and hard-won lessons from your work, and the relevant parts come back automatically next time. It runs on your machine by default, with no Docker and no database to install.
This guide takes you from install to a working memory in about two minutes, then shows you the recall patterns a flat notes file cannot do.
Install
pip install smartmemory
smartmemory setupsetup asks a couple of questions with sensible defaults and wires SmartMemory into Claude Code. Using Cursor instead? Run smartmemory setup --for cursor.
This is Lite mode, the local default: a SQLite graph plus embedded vectors, no external services, no account. If you would rather point at the managed backend, run smartmemory setup --mode remote and paste an API key from app.smartmemory.ai. Either way you can switch later by re-running setup. See Installation for the full matrix and troubleshooting.
Your first memories
Add a few things worth remembering, then ask for them back in plain language:
sm add "We chose Postgres over MongoDB because of the reporting queries"
sm add "Deploys go through GitHub Actions, never manual"
sm search "which database did we pick"sm is the short alias for smartmemory, and either name works. That last search returns the Postgres memory even though none of its words appear in the query. sm search matches by meaning, not keywords, so you can ask a question instead of guessing the exact phrase you saved.
New memories land as episodic (things that happened) unless you say otherwise. Reach for a type when it helps you filter later:
sm add --type procedural "Reset the local DB with docker compose down -v, then ./dev.sh start"
sm add --project atlas "Atlas v2 ships on the 15th"
sm search --project atlas "when do we ship"See it prove itself
Run the guided tour:
sm tourThe tour spins up an isolated local store (it never touches your real memories), opens the graph viewer in your browser, seeds a few project facts, searches them, and then shows the moment that matters: a real token receipt and cross-session recall, side by side.
Here is the idea the receipt makes concrete. A memory that you paste into context in full keeps growing as your project does. SmartMemory instead recalls only the memories relevant to what you are doing right now, so the context it feeds your assistant stays small even as your stored memory grows into thousands of items. The tour puts both counts on screen with a real tokenizer so you can see the gap yourself rather than take it on faith.
Add --no-viewer for headless runs, or --keep if you want to inspect the temporary store afterward.
What you get from here
- Your assistant remembers across sessions. Setup installs hooks that capture context while you work and recall the relevant parts when the next session starts, so you stop re-explaining your project every morning. See MCP integration.
- A knowledge graph you can see. Everything you add gets linked into a graph of the people, projects, and concepts inside your memories. Open it with
sm viewer, or read Graph viewer. - The same memory in Python. Everything the CLI does is available from code, which is where the deeper recall patterns below live.
Use it from Python
from smartmemory.tools.factory import create_lite_memory, lite_context
# Simple usage. Full LLM extraction runs if OPENAI_API_KEY is set.
memory = create_lite_memory()
item_id = memory.ingest("Alice leads Project Atlas")
results = memory.search("who leads Atlas", top_k=5)
# Preferred in scripts: cleans up globals and closes SQLite on exit.
with lite_context() as memory:
item_id = memory.ingest("Alice leads Project Atlas")
results = memory.search("who leads Atlas")SmartMemory does not just save text. It extracts the people, projects, and concepts inside each memory and links them into the graph, which is why search can answer questions and why the viewer has something to draw. See Lite mode for the local Python surface in full.
Advanced recall in practice
The steps above are capture and simple search. These are the patterns a flat memory file cannot do. Every example runs in local Lite mode with no API key. Shared setup:
from smartmemory.pipeline.config import PipelineConfig
from smartmemory.tools.factory import lite_context
from smartmemory.models.memory_item import MemoryItem
lite = dict(pipeline_profile=PipelineConfig.lite(llm_enabled=False))Decisions, including what you decided not to do. A decision is a first-class object that keeps the rejected alternatives and the reasoning attached, so you can recall the road not taken.
with lite_context(**lite) as m:
d = m.add_decision(
"Use SQLite for local lite storage",
rejected_alternatives=["Postgres sidecar", "remote-only cloud sync"],
rationale="Zero-infra installs must work offline",
)
print(m.get_decision(d.decision_id).rejected_alternatives)
# -> ['Postgres sidecar', 'remote-only cloud sync']
hits = m.search("what did we decide NOT to do for storage", expertise=True)
print([i.content for i in hits["decision"]])
# -> ['Use SQLite for local lite storage']search(expertise=True) returns a dict keyed by expertise type (decision, constraint, learned, and so on), not a flat list.
Truth maintenance: supersede a fact, and only the current one comes back.
with lite_context(**lite) as m:
old = m.add(MemoryItem(content="The incident channel is #ops-old", memory_type="semantic"))
new = m.add(MemoryItem(content="The incident channel is #ops-war-room", memory_type="semantic"))
m.supersede(old, new, reason="Team renamed the channel")
print([r.content for r in m.search("incident channel")])
# -> ['The incident channel is #ops-war-room'] (current only)
print([r.content for r in m.search("incident channel", include_superseded=True)])
# -> ['The incident channel is #ops-old', 'The incident channel is #ops-war-room'] (full history)Bi-temporal recall: what did we believe before it changed. Supersession keeps the full history, and SmartMemory also records when each fact was true, so you can ask a memory as of a past moment and get the belief you held then rather than the current one. A markdown file cannot answer this: once you edit the line, the old value is gone. The point-in-time query depends on the storage backend preserving each record's time, so see Bi-temporal versioning for how as_of_date and reference_time work and which backends resolve them.
Constraints and lessons, recalled as expertise.
with lite_context(**lite) as m:
m.add_constraint("Production deploys must use GitHub Actions", domain="release")
m.add_learning("SQLite WAL avoids writer stalls under concurrent tests")
hits = m.search("deploy and sqlite guidance", expertise=True)
print([i.content for i in hits["constraint"]])
# -> ['Production deploys must use GitHub Actions']
print([i.content for i in hits["learned"]])
# -> ['SQLite WAL avoids writer stalls under concurrent tests']Multi-hop retrieval chains results so each hop informs the next query, reaching facts a single lookup would miss. It pays off once your graph is rich (semantic_hops=True adds LLM-planned hops):
with lite_context(**lite) as m:
hits = m.search("Redis migration fallout", multi_hop=True, max_hops=3)Code intelligence: index a repo, then search it by meaning. sm code index builds an AST and call graph into memory. Recall it with search_code, which is semantic, so it finds code that shares no keywords with your query (a plain grep would miss it):
sm code index ./my-project --repo my-projectwith lite_context(**lite) as m:
# "clean up vendor billing records" matches a function actually named
# reconcile_widget_invoice (no shared keywords, found by meaning).
for hit in m.search_code("clean up vendor billing records", repo="my-project"):
print(hit["name"], hit["entity_type"], f'{hit["file_path"]}:{hit["line_number"]}')Next steps
- Basic usage - the core APIs in depth
- Configuration - customize SmartMemory behavior
- Expertise vs knowledge - when to use decisions, constraints, and lessons
- Bi-temporal versioning - how supersession and as-of recall work
- Learning assistant and Conversational AI - fuller worked examples