An open API service indexing awesome lists of open source software.

https://github.com/zilliztech/memsearch

A Markdown-first memory system, a standalone library for any AI agent. Inspired by OpenClaw.
https://github.com/zilliztech/memsearch

agent agent-memory claude-code claude-code-plugin clawdbot embeddings memory milvus openclaw progressive-disclosure rag semantic-search

Last synced: 1 day ago
JSON representation

A Markdown-first memory system, a standalone library for any AI agent. Inspired by OpenClaw.

Awesome Lists containing this project

README

          



Β 
memsearch


OpenClaw's memory, everywhere.


PyPI
Python
License
Docs
Stars
Discord
X (Twitter)

https://github.com/user-attachments/assets/31de76cc-81a8-4462-a47d-bd9c394d33e3

> πŸ’‘ Give your AI agents persistent memory in a few lines of code. Write memories as markdown, search them semantically. Inspired by [OpenClaw](https://github.com/openclaw/openclaw)'s markdown-first memory architecture. Pluggable into any agent framework.

### ✨ Why memsearch?

- πŸ“ **Markdown is the source of truth** β€” human-readable, `git`-friendly, zero vendor lock-in. Your memories are just `.md` files
- ⚑ **Smart dedup** β€” SHA-256 content hashing means unchanged content is never re-embedded
- πŸ”„ **Live sync** β€” File watcher auto-indexes changes to the vector DB, deletes stale chunks when files are removed
- 🧩 **[Ready-made Claude Code plugin](ccplugin/README.md)** β€” a drop-in example of agent memory built on memsearch

## πŸ“¦ Installation

```bash
pip install memsearch
```

Optional embedding providers

```bash
pip install "memsearch[google]" # Google Gemini
pip install "memsearch[voyage]" # Voyage AI
pip install "memsearch[ollama]" # Ollama (local)
pip install "memsearch[local]" # sentence-transformers (local, no API key)
pip install "memsearch[all]" # Everything
```

## 🐍 Python API β€” Give Your Agent Memory

```python
from memsearch import MemSearch

mem = MemSearch(paths=["./memory"])

await mem.index() # index markdown files
results = await mem.search("Redis config", top_k=3) # semantic search
print(results[0]["content"], results[0]["score"]) # content + similarity
```

πŸš€ Full example β€” agent with memory (OpenAI) β€” click to expand

```python
import asyncio
from datetime import date
from pathlib import Path
from openai import OpenAI
from memsearch import MemSearch

MEMORY_DIR = "./memory"
llm = OpenAI() # your LLM client
mem = MemSearch(paths=[MEMORY_DIR]) # memsearch handles the rest

def save_memory(content: str):
"""Append a note to today's memory log (OpenClaw-style daily markdown)."""
p = Path(MEMORY_DIR) / f"{date.today()}.md"
p.parent.mkdir(parents=True, exist_ok=True)
with open(p, "a") as f:
f.write(f"\n{content}\n")

async def agent_chat(user_input: str) -> str:
# 1. Recall β€” search past memories for relevant context
memories = await mem.search(user_input, top_k=3)
context = "\n".join(f"- {m['content'][:200]}" for m in memories)

# 2. Think β€” call LLM with memory context
resp = llm.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": f"You have these memories:\n{context}"},
{"role": "user", "content": user_input},
],
)
answer = resp.choices[0].message.content

# 3. Remember β€” save this exchange and index it
save_memory(f"## {user_input}\n{answer}")
await mem.index()

return answer

async def main():
# Seed some knowledge
save_memory("## Team\n- Alice: frontend lead\n- Bob: backend lead")
save_memory("## Decision\nWe chose Redis for caching over Memcached.")
await mem.index() # or mem.watch() to auto-index in the background

# Agent can now recall those memories
print(await agent_chat("Who is our frontend lead?"))
print(await agent_chat("What caching solution did we pick?"))

asyncio.run(main())
```

πŸ’œ Anthropic Claude example β€” click to expand

```bash
pip install memsearch anthropic
```

```python
import asyncio
from datetime import date
from pathlib import Path
from anthropic import Anthropic
from memsearch import MemSearch

MEMORY_DIR = "./memory"
llm = Anthropic()
mem = MemSearch(paths=[MEMORY_DIR])

def save_memory(content: str):
p = Path(MEMORY_DIR) / f"{date.today()}.md"
p.parent.mkdir(parents=True, exist_ok=True)
with open(p, "a") as f:
f.write(f"\n{content}\n")

async def agent_chat(user_input: str) -> str:
# 1. Recall
memories = await mem.search(user_input, top_k=3)
context = "\n".join(f"- {m['content'][:200]}" for m in memories)

# 2. Think β€” call Claude with memory context
resp = llm.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1024,
system=f"You have these memories:\n{context}",
messages=[{"role": "user", "content": user_input}],
)
answer = resp.content[0].text

# 3. Remember
save_memory(f"## {user_input}\n{answer}")
await mem.index()
return answer

async def main():
save_memory("## Team\n- Alice: frontend lead\n- Bob: backend lead")
await mem.index()
print(await agent_chat("Who is our frontend lead?"))

asyncio.run(main())
```

πŸ¦™ Ollama (fully local, no API key) β€” click to expand

```bash
pip install "memsearch[ollama]"
ollama pull nomic-embed-text # embedding model
ollama pull llama3.2 # chat model
```

```python
import asyncio
from datetime import date
from pathlib import Path
from ollama import chat
from memsearch import MemSearch

MEMORY_DIR = "./memory"
mem = MemSearch(paths=[MEMORY_DIR], embedding_provider="ollama")

def save_memory(content: str):
p = Path(MEMORY_DIR) / f"{date.today()}.md"
p.parent.mkdir(parents=True, exist_ok=True)
with open(p, "a") as f:
f.write(f"\n{content}\n")

async def agent_chat(user_input: str) -> str:
# 1. Recall
memories = await mem.search(user_input, top_k=3)
context = "\n".join(f"- {m['content'][:200]}" for m in memories)

# 2. Think β€” call Ollama locally
resp = chat(
model="llama3.2",
messages=[
{"role": "system", "content": f"You have these memories:\n{context}"},
{"role": "user", "content": user_input},
],
)
answer = resp.message.content

# 3. Remember
save_memory(f"## {user_input}\n{answer}")
await mem.index()
return answer

async def main():
save_memory("## Team\n- Alice: frontend lead\n- Bob: backend lead")
await mem.index()
print(await agent_chat("Who is our frontend lead?"))

asyncio.run(main())
```

## πŸ–₯️ CLI Usage

```bash
memsearch index ./memory/ # index markdown files
memsearch search "how to configure Redis caching" # semantic search
memsearch watch ./memory/ # auto-index on file changes
memsearch compact # LLM-powered memory summarization
memsearch config init # interactive config wizard
memsearch stats # show index statistics
```

> πŸ“– Full command reference with all flags and examples β†’ [CLI Reference](https://zilliztech.github.io/memsearch/cli/)

## πŸ” How It Works

**Markdown is the source of truth** β€” the vector store is just a derived index, rebuildable anytime.

```
β”Œβ”€β”€β”€ Search ─────────────────────────────────────────────────────────┐
β”‚ β”‚
β”‚ "how to configure Redis?" β”‚
β”‚ β”‚ β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Embed │────▢│ Cosine similarity│────▢│ Top-K results β”‚ β”‚
β”‚ β”‚ query β”‚ β”‚ (Milvus) β”‚ β”‚ with source info β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€ Ingest ─────────────────────────────────────────────────────────┐
β”‚ β”‚
β”‚ MEMORY.md β”‚
β”‚ memory/2026-02-09.md β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ memory/2026-02-08.md ───▢│ Chunker │────▢│ Dedup β”‚ β”‚
β”‚ β”‚(heading, β”‚ β”‚(chunk_hash PK) β”‚ β”‚
β”‚ β”‚paragraph)β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ new chunks only β”‚
β”‚ β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Embed & β”‚ β”‚
β”‚ β”‚ Milvus upsertβ”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€ Watch ──────────────────────────────────────────────────────────┐
β”‚ File watcher (1500ms debounce) ──▢ auto re-index / delete stale β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€ Compact ─────────────────────────────────────────────────────────┐
β”‚ Retrieve chunks ──▢ LLM summarize ──▢ write memory/YYYY-MM-DD.md β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

πŸ”’ The entire pipeline runs locally by default β€” your data never leaves your machine unless you choose a remote backend or a cloud embedding provider.

## 🧩 Claude Code Plugin

memsearch ships with a **[Claude Code plugin](ccplugin/README.md)** β€” a real-world example of agent memory in action. It gives Claude **automatic persistent memory** across sessions: every session is summarized to markdown, every prompt triggers a semantic search, and a background watcher keeps the index in sync. No commands to learn, no manual saving β€” just install and go.

```bash
# 1. Install the memsearch CLI
pip install memsearch

# 2. Set your embedding API key (OpenAI is the default provider)
export OPENAI_API_KEY="sk-..."

# 3. In Claude Code, add the marketplace and install the plugin
/plugin marketplace add zilliztech/memsearch
/plugin install memsearch

# 4. Restart Claude Code for the plugin to take effect, then start chatting!
claude
```

> πŸ“– Architecture, hook details, and development mode β†’ [Claude Code Plugin docs](https://zilliztech.github.io/memsearch/claude-plugin/)

## βš™οΈ Configuration

Settings are resolved in priority order (lowest β†’ highest):

1. **Built-in defaults** β†’ 2. **Global** `~/.memsearch/config.toml` β†’ 3. **Project** `.memsearch.toml` β†’ 4. **CLI flags**

API keys for embedding/LLM providers are read from standard environment variables (`OPENAI_API_KEY`, `GOOGLE_API_KEY`, `VOYAGE_API_KEY`, `ANTHROPIC_API_KEY`, etc.).

> πŸ“– Config wizard, TOML examples, and all settings β†’ [Getting Started β€” Configuration](https://zilliztech.github.io/memsearch/getting-started/#configuration)

## πŸ”Œ Embedding Providers

| Provider | Install | Default Model |
|----------|---------|---------------|
| OpenAI | `memsearch` (included) | `text-embedding-3-small` |
| Google | `memsearch[google]` | `gemini-embedding-001` |
| Voyage | `memsearch[voyage]` | `voyage-3-lite` |
| Ollama | `memsearch[ollama]` | `nomic-embed-text` |
| Local | `memsearch[local]` | `all-MiniLM-L6-v2` |

> πŸ“– Provider setup and env vars β†’ [CLI Reference β€” Embedding Provider Reference](https://zilliztech.github.io/memsearch/cli/#embedding-provider-reference)

## πŸ—„οΈ Milvus Backend

memsearch supports three deployment modes β€” just change `milvus_uri`:

| Mode | `milvus_uri` | Best for |
|------|-------------|----------|
| **Milvus Lite** (default) | `~/.memsearch/milvus.db` | Personal use, dev β€” zero config |
| **Milvus Server** | `http://localhost:19530` | Multi-agent, team environments |
| **Zilliz Cloud** | `https://in03-xxx.api.gcp-us-west1.zillizcloud.com` | Production, fully managed |

> πŸ“– Code examples and setup details β†’ [Getting Started β€” Milvus Backends](https://zilliztech.github.io/memsearch/getting-started/#milvus-backends)

## πŸ“š Links

- [Documentation](https://zilliztech.github.io/memsearch/) β€” Getting Started, CLI Reference, Architecture
- [Claude Code Plugin](ccplugin/README.md) β€” hook details, progressive disclosure, comparison with claude-mem
- [OpenClaw](https://github.com/openclaw/openclaw) β€” the memory architecture that inspired memsearch
- [Milvus](https://milvus.io/) β€” the vector database powering memsearch
- [Changelog](https://github.com/zilliztech/memsearch/releases) β€” release history

## Contributing

Bug reports, feature requests, and pull requests are welcome on [GitHub](https://github.com/zilliztech/memsearch). For questions and discussions, join us on [Discord](https://discord.com/invite/FG6hMJStWu).

## πŸ“„ License

[MIT](LICENSE)