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

# Memory System

> NeuralCleave's 3-tier memory (Redis, Qdrant, SQLite) retrieves relevant context for every query.

NeuralCleave combines three memory tiers into one retrieval pass before generating a reply: a fast short-term session cache, a semantic vector search over past conversations, and a durable long-term SQLite store. Redis and Qdrant are both optional at runtime — the pipeline falls back to in-process storage for either one when it isn't reachable, so a bare install with no external services still works.

## How it works

1. **Write**: Each turn is stored short-term (Redis, TTL-based) and embedded for semantic search; important turns are also persisted to the SQLite long-term store.
2. **Retrieve**: At query time, `MemoryRetrievalPipeline.retrieve()` (`neuralcleave/memory/retrieval.py`) pulls from all three tiers in one pass — short-term (priority), Qdrant ANN semantic search (falls back to in-memory cosine similarity if Qdrant is unreachable), and a SQLite long-term query — then deduplicates by content hash, ranks by score, and caps the result at a `top_k` the caller passes in code (the cognitive pipeline uses 8).
3. **Inject**: The assembled results are serialized into prompt blocks and prepended to the LLM call.

```
User message
    ↓
Short-term (Redis) ─┐
Semantic (Qdrant)   ├─→ dedup → rank → cap at top_k → RetrievalContext
Long-term (SQLite)  ─┘
    ↓
[context] + [user message] → LLM
```

<Note>
  Semantic embedding uses `sentence-transformers` (`all-MiniLM-L6-v2`, downloaded automatically on first use). If it isn't importable, `neuralcleave/memory/embedder.py` logs a warning and semantic search is silently skipped for that turn — short-term and long-term retrieval still work normally.
</Note>

## Configuration

```toml theme={null}
[memory]
short_term_ttl = 3600                        # seconds a Redis entry stays hot
long_term_days = 90                          # SQLite retention window
redis_url = "redis://localhost:6379"
qdrant_url = "http://localhost:6333"
sqlite_path = "~/.neuralcleave/memory.db"
```

There is no `backend`/`embedding_model`/`chunk_size`/`top_k` config — the embedding model and chunking strategy aren't configurable today; `top_k` is a call-site parameter, not a config field.

## API

<Note>
  The REST routes below only reach the SQLite long-term tier — `/memory/search` is a plain `content LIKE '%...%'` query (`neuralcleave/memory/long_term.py`'s `search()`), not the semantic/Qdrant search. Semantic retrieval only happens internally, inside `MemoryRetrievalPipeline.retrieve()` as part of the chat pipeline — there's no REST route that exposes it directly today.
</Note>

### Search long-term memory (SQLite substring match)

```bash theme={null}
curl "http://localhost:7432/api/v1/memory/search?q=what+did+we+discuss+yesterday&limit=10"
```

```json theme={null}
{
  "query": "what did we discuss yesterday",
  "results": [
    {"id": 1, "content": "We discussed the project timeline...", "importance_score": 0.87}
  ],
  "count": 1
}
```

Pass `session_id` to scope the search to one session (omit for all sessions).

### List recent entries

```bash theme={null}
curl "http://localhost:7432/api/v1/memory/entries?limit=20"
```

### Edit an entry

```bash theme={null}
curl -X PATCH "http://localhost:7432/api/v1/memory/entries/1" \
  -H "Content-Type: application/json" -d '{"content": "corrected text", "importance": 0.5}'
```

### Delete an entry

```bash theme={null}
curl -X DELETE "http://localhost:7432/api/v1/memory/entries/1"
```

### Prune

```bash theme={null}
curl -X POST "http://localhost:7432/api/v1/memory/prune" \
  -H "Content-Type: application/json" -d '{"days": 90, "threshold": 0.1}'
```

There is no REST route to clear an entire session or wipe all memory — use the CLI (`neuralcleave memory clear`) for that.

## Auto-compaction

Once a session's estimated token usage crosses 50% of the context window, the pipeline automatically summarizes the conversation (via `ConversationCompactor`), replaces the in-memory history with that summary, and persists it to long-term SQLite — the same mechanism the manual `/compact` chat command uses, just triggered automatically instead of on request. Compaction runs fire-and-forget after a turn's reply is already sent, so it never adds latency to the current response; a failure is logged and swallowed rather than surfaced.

A separate `memory_archival` job runs daily (03:00) via the heartbeat scheduler, condensing sessions inactive for 30+ days the same way `neuralcleave memory archive` does manually.

## CLI

```bash theme={null}
neuralcleave memory search "project timeline" --session default
neuralcleave memory prune --threshold 0.2                  # low-importance entries + Qdrant near-duplicates
neuralcleave memory clear --session default                # or omit --session to clear everything
neuralcleave memory edit <entry-id> --content "..." --importance 0.6
neuralcleave memory archive --days 30                       # condense inactive sessions into a searchable summary
```

## Privacy note

With `privacy_mode = true`, all LLM calls are forced to local Ollama — see [Privacy Mode](/privacy-mode). The embedding model already runs locally regardless of that setting (no embeddings are ever sent to an external API); only the long-term SQLite store and Qdrant's own storage location are affected by where you point `sqlite_path`/`qdrant_url`.
