Namespace filtering for multi-project isolation
Adds an optional namespace field to scope memories per project or context. Memories with a namespace are only returned when the search/list call passes that same namespace; unnamespaced memories stay global.
What's new
store_memoryaccepts optionalnamespace(alphanumeric, hyphens, underscores, dots; max 128 chars).retrieve_memoryaccepts optionalnamespacefilter. Unnamespaced memories are NOT returned when a namespace filter is active.list_memoriesaccepts optionalnamespacefilter. Output now shows[ns: ...]for namespaced memories.- Test infrastructure — vitest + MockAdapter runs against the shared
tools.tslayer using theRecallAdapterabstraction. No Miniflare required.
Example
```json
{ "name": "store_memory", "arguments": {
"key": "auth-flow", "content": "...", "author": "cash",
"namespace": "project-alpha"
}}
```
```json
{ "name": "retrieve_memory", "arguments": {
"query": "auth token expiry", "namespace": "project-alpha"
}}
```
Breaking changes
None. Existing callers that omit namespace continue to work — stored memories have NULL namespace and show up in all un-filtered queries, same as before.
Schema migrations
Cloudflare Workers (required):
```bash
git pull origin main
wrangler d1 execute --remote --file=migrations/0003_namespace.sql
wrangler deploy
```
Local stdio:
```bash
git pull origin main
cd local && npm install && npm run build
```
Schema is re-applied on every start (CREATE ... IF NOT EXISTS is idempotent). No manual migration needed.
Docker (existing installs):
```bash
git pull origin main
cd docker && docker compose build && docker compose up -d
Then apply the migration inside Postgres:
docker compose exec postgres psql -U recall -d recall -c "ALTER TABLE memories ADD COLUMN namespace TEXT; CREATE INDEX IF NOT EXISTS idx_memories_namespace ON memories(namespace);"
```
Fresh Docker installs: nothing to do — setup.sql already has the column.
Credits
Namespace scoping pattern adapted from MemPalace.