memclaw 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memclaw-0.1.0/.env.example +9 -0
- memclaw-0.1.0/.github/workflows/ci.yml +28 -0
- memclaw-0.1.0/.github/workflows/publish.yml +19 -0
- memclaw-0.1.0/.gitignore +35 -0
- memclaw-0.1.0/CODE_OF_CONDUCT.md +38 -0
- memclaw-0.1.0/CONTRIBUTING.md +76 -0
- memclaw-0.1.0/LICENSE +21 -0
- memclaw-0.1.0/PKG-INFO +324 -0
- memclaw-0.1.0/README.md +288 -0
- memclaw-0.1.0/docs/memory-architecture.md +262 -0
- memclaw-0.1.0/memclaw/__init__.py +3 -0
- memclaw-0.1.0/memclaw/agent.py +739 -0
- memclaw-0.1.0/memclaw/bot/__init__.py +0 -0
- memclaw-0.1.0/memclaw/bot/handlers.py +202 -0
- memclaw-0.1.0/memclaw/bot/link_processor.py +106 -0
- memclaw-0.1.0/memclaw/cli.py +351 -0
- memclaw-0.1.0/memclaw/config.py +96 -0
- memclaw-0.1.0/memclaw/defaults/AGENTS.md +46 -0
- memclaw-0.1.0/memclaw/defaults/__init__.py +0 -0
- memclaw-0.1.0/memclaw/index.py +371 -0
- memclaw-0.1.0/memclaw/search.py +288 -0
- memclaw-0.1.0/memclaw/setup.py +114 -0
- memclaw-0.1.0/memclaw/store.py +104 -0
- memclaw-0.1.0/pyproject.toml +55 -0
- memclaw-0.1.0/tests/__init__.py +0 -0
- memclaw-0.1.0/tests/conftest.py +66 -0
- memclaw-0.1.0/tests/test_agent.py +564 -0
- memclaw-0.1.0/tests/test_config.py +40 -0
- memclaw-0.1.0/tests/test_handlers.py +148 -0
- memclaw-0.1.0/tests/test_index.py +163 -0
- memclaw-0.1.0/tests/test_search.py +275 -0
- memclaw-0.1.0/tests/test_store.py +96 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Required for embeddings and image descriptions
|
|
2
|
+
OPENAI_API_KEY=your-openai-key
|
|
3
|
+
|
|
4
|
+
# Required for the Claude agent (interactive mode + /ask command)
|
|
5
|
+
ANTHROPIC_API_KEY=your-anthropic-key
|
|
6
|
+
|
|
7
|
+
# Telegram bot settings
|
|
8
|
+
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
|
9
|
+
ALLOWED_USER_IDS=123456789,987654321
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: pytest
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- run: pip install build
|
|
18
|
+
- run: python -m build
|
|
19
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
memclaw-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
*.egg-info/
|
|
11
|
+
*.egg
|
|
12
|
+
|
|
13
|
+
# Virtual environments
|
|
14
|
+
.env
|
|
15
|
+
.envrc
|
|
16
|
+
.venv
|
|
17
|
+
venv/
|
|
18
|
+
|
|
19
|
+
# Testing
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# IDEs
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
.cursorignore
|
|
28
|
+
.cursorindexingignore
|
|
29
|
+
|
|
30
|
+
# Type checkers / linters
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
.ruff_cache/
|
|
33
|
+
|
|
34
|
+
# Memclaw local data
|
|
35
|
+
.memclaw/
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Using welcoming and inclusive language
|
|
17
|
+
- Being respectful of differing viewpoints and experiences
|
|
18
|
+
- Gracefully accepting constructive criticism
|
|
19
|
+
- Focusing on what is best for the community
|
|
20
|
+
- Showing empathy towards other community members
|
|
21
|
+
|
|
22
|
+
Examples of unacceptable behavior:
|
|
23
|
+
|
|
24
|
+
- The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
25
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
26
|
+
- Public or private harassment
|
|
27
|
+
- Publishing others' private information without explicit permission
|
|
28
|
+
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
29
|
+
|
|
30
|
+
## Enforcement
|
|
31
|
+
|
|
32
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
33
|
+
reported to the project maintainers at emanuilo.jovanovic@hotmail.com. All
|
|
34
|
+
complaints will be reviewed and investigated promptly and fairly.
|
|
35
|
+
|
|
36
|
+
## Attribution
|
|
37
|
+
|
|
38
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Contributing to Memclaw
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Here's how to get started.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/emanuilo/memclaw.git
|
|
9
|
+
cd memclaw
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
source .venv/bin/activate
|
|
12
|
+
pip install -e ".[dev]"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Copy the environment template and fill in your keys:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cp .env.example .env
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Running Tests
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pytest
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
All tests should pass before submitting a PR. The test suite mocks external API calls, so no API keys are needed to run tests.
|
|
28
|
+
|
|
29
|
+
## Code Style
|
|
30
|
+
|
|
31
|
+
- Follow PEP 8 conventions
|
|
32
|
+
- Use type hints for function signatures
|
|
33
|
+
- Keep functions focused and small
|
|
34
|
+
- Run `ruff check .` before committing
|
|
35
|
+
|
|
36
|
+
## Making Changes
|
|
37
|
+
|
|
38
|
+
1. Fork the repository
|
|
39
|
+
2. Create a feature branch (`git checkout -b feature/my-feature`)
|
|
40
|
+
3. Make your changes
|
|
41
|
+
4. Add or update tests as needed
|
|
42
|
+
5. Run the test suite (`pytest`)
|
|
43
|
+
6. Run the linter (`ruff check .`)
|
|
44
|
+
7. Commit with a clear message (`git commit -m 'feat: add my feature'`)
|
|
45
|
+
8. Push to your fork (`git push origin feature/my-feature`)
|
|
46
|
+
9. Open a Pull Request
|
|
47
|
+
|
|
48
|
+
## Commit Messages
|
|
49
|
+
|
|
50
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/) style:
|
|
51
|
+
|
|
52
|
+
- `feat:` new feature
|
|
53
|
+
- `fix:` bug fix
|
|
54
|
+
- `docs:` documentation only
|
|
55
|
+
- `test:` adding or updating tests
|
|
56
|
+
- `chore:` maintenance, dependencies, CI
|
|
57
|
+
|
|
58
|
+
## Pull Requests
|
|
59
|
+
|
|
60
|
+
- Keep PRs focused on a single change
|
|
61
|
+
- Include tests for new functionality
|
|
62
|
+
- Update documentation if behavior changes
|
|
63
|
+
- Link related issues in the PR description
|
|
64
|
+
|
|
65
|
+
## Reporting Bugs
|
|
66
|
+
|
|
67
|
+
Open an issue with:
|
|
68
|
+
|
|
69
|
+
- Steps to reproduce
|
|
70
|
+
- Expected vs actual behavior
|
|
71
|
+
- Python version and OS
|
|
72
|
+
- Relevant logs or error messages
|
|
73
|
+
|
|
74
|
+
## Questions?
|
|
75
|
+
|
|
76
|
+
Open a [discussion](https://github.com/emanuilo/memclaw/issues) or reach out in an issue.
|
memclaw-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Memclaw Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
memclaw-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memclaw
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight, local-first personal memory assistant powered by AI
|
|
5
|
+
Project-URL: Repository, https://github.com/emanuilo/memclaw
|
|
6
|
+
Project-URL: Issues, https://github.com/emanuilo/memclaw/issues
|
|
7
|
+
Author-email: Emanuilo Jovanovic <emanuilo.jovanovic@hotmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,assistant,memory,personal-knowledge,second-brain,vector-search
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: anthropic>=0.40.0
|
|
22
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
23
|
+
Requires-Dist: claude-agent-sdk>=0.1.0
|
|
24
|
+
Requires-Dist: click>=8.0.0
|
|
25
|
+
Requires-Dist: httpx>=0.27.0
|
|
26
|
+
Requires-Dist: loguru>=0.7.0
|
|
27
|
+
Requires-Dist: numpy>=1.24.0
|
|
28
|
+
Requires-Dist: openai>=1.0.0
|
|
29
|
+
Requires-Dist: python-telegram-bot>=21.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=9.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.9.0; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<div align="center">
|
|
38
|
+
|
|
39
|
+
# Memclaw
|
|
40
|
+
|
|
41
|
+
**Your personal memory vault, powered by AI.**
|
|
42
|
+
|
|
43
|
+
Store your thoughts. Save your images and links. Ask anything, anytime.
|
|
44
|
+
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
[](https://www.python.org/downloads/)
|
|
47
|
+
[](https://platform.claude.com/docs/en/agent-sdk/overview)
|
|
48
|
+
[](https://core.telegram.org/bots)
|
|
49
|
+
[](CONTRIBUTING.md)
|
|
50
|
+
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
Memclaw is a lightweight, local-first personal memory assistant. It stores your thoughts, notes, images, and links as **plain Markdown files** and makes them instantly searchable through **hybrid vector + keyword search**.
|
|
56
|
+
|
|
57
|
+
Think of it as your second brain — one that actually remembers.
|
|
58
|
+
|
|
59
|
+
## Why Memclaw?
|
|
60
|
+
|
|
61
|
+
[OpenClaw](https://github.com/openclaw/openclaw) is great — but it connects to dozens of tools, reads your filesystem, runs shell commands, and does a hundred things you didn't ask for. That makes it slow, expensive, and a security surface you have to think about every time you use it.
|
|
62
|
+
|
|
63
|
+
Memclaw takes one slice of what OpenClaw does — **memory** — and does it really well, without the rest.
|
|
64
|
+
|
|
65
|
+
**Total recall.** Save a thought today, retrieve it six months later with a vague description. *"What was that restaurant Alex told me about?"* — Memclaw finds it. Hybrid vector + keyword search means you don't need to remember exact words.
|
|
66
|
+
|
|
67
|
+
**Visual memory.** Send an image and Memclaw generates an AI caption, indexes it, and stores it. Later, just ask *"that food recipe photo"* or *"the whiteboard from last sprint"* and it comes right back.
|
|
68
|
+
|
|
69
|
+
**Link memory.** Drop a link and Memclaw fetches the page, summarizes it, and indexes the content. Months later, ask *"that article about distributed databases"* and it surfaces the link with context — no bookmarking app needed.
|
|
70
|
+
|
|
71
|
+
**Sandboxed by design.** Memclaw only touches `~/.memclaw/`. No filesystem access, no shell commands, no path traversal. You don't need to trust it with your whole computer — it can't see it.
|
|
72
|
+
|
|
73
|
+
**Lightweight and cheap.** No Docker. No Postgres. No sprawling tool graph burning tokens. Just Python, SQLite, and two API keys. Fast responses, minimal cost.
|
|
74
|
+
|
|
75
|
+
## Quick Start
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install memclaw
|
|
79
|
+
memclaw
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
On first run, Memclaw will prompt you for your API keys and save them to `~/.memclaw/.env`. You can update them anytime with `memclaw configure`.
|
|
83
|
+
|
|
84
|
+
## Telegram Bot
|
|
85
|
+
|
|
86
|
+
The main way to use Memclaw. Just talk to it naturally — no commands needed. Send text, photos, voice messages, or links. The agent figures out what to do: store it, search your memories, retrieve images, or just chat.
|
|
87
|
+
|
|
88
|
+
The bot shows a **typing indicator** while processing so you know it's working on your request.
|
|
89
|
+
|
|
90
|
+
### Setup
|
|
91
|
+
|
|
92
|
+
1. Create a bot via [@BotFather](https://t.me/BotFather) and copy the token.
|
|
93
|
+
2. Get your Telegram user ID (e.g. via [@userinfobot](https://t.me/userinfobot)).
|
|
94
|
+
3. Start the bot — on first run you'll be prompted for all keys:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
memclaw bot
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To update keys later: `memclaw configure`.
|
|
101
|
+
|
|
102
|
+
### What it handles
|
|
103
|
+
|
|
104
|
+
| Message type | What happens |
|
|
105
|
+
|-------------|-------------|
|
|
106
|
+
| **Text** | Agent decides: store as memory, search existing memories, or both. Links are extracted, fetched, and summarized automatically. |
|
|
107
|
+
| **Photo** | AI-described via vision model, stored and indexed. Agent acknowledges and responds. File ID saved for later retrieval. |
|
|
108
|
+
| **Voice** | Transcribed via Whisper, stored as text. Agent responds to the content. Links extracted. |
|
|
109
|
+
|
|
110
|
+
### Examples
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
> Just had coffee with Alex. She's moving to Berlin for a role at Stripe.
|
|
114
|
+
Got it! I've saved that Alex is moving to Berlin for a new role at Stripe.
|
|
115
|
+
|
|
116
|
+
> Who is Alex?
|
|
117
|
+
Based on your memories, Alex is someone you had coffee with recently.
|
|
118
|
+
She's moving to Berlin for a new role at Stripe.
|
|
119
|
+
|
|
120
|
+
> Show me the whiteboard photo from last week
|
|
121
|
+
[sends the matching photo]
|
|
122
|
+
Here's the sprint planning whiteboard you saved last week.
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## How It Works
|
|
126
|
+
|
|
127
|
+
```mermaid
|
|
128
|
+
flowchart LR
|
|
129
|
+
You -->|text / images / links| Agent[Memclaw Agent]
|
|
130
|
+
|
|
131
|
+
subgraph sandbox ["~/.memclaw/"]
|
|
132
|
+
Agent -->|save| Tools1["memory_save<br>image_save<br>file_write"]
|
|
133
|
+
Tools1 --> Files["MEMORY.md<br>daily/*.md<br>AGENTS.md"]
|
|
134
|
+
Files --> DB[("SQLite<br>FTS5 + Vectors")]
|
|
135
|
+
DB --> Tools2["memory_search<br>image_search"]
|
|
136
|
+
Tools2 -->|results| Agent
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
Agent -->|response + images| You
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Memclaw draws inspiration from [OpenClaw](https://github.com/openclaw/openclaw)'s memory architecture and is built with the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview).
|
|
143
|
+
|
|
144
|
+
### Storage Layer
|
|
145
|
+
|
|
146
|
+
All memories are plain Markdown — human-readable, editable, and git-friendly.
|
|
147
|
+
|
|
148
|
+
| File | Purpose |
|
|
149
|
+
|------|---------|
|
|
150
|
+
| `~/.memclaw/MEMORY.md` | Curated long-term facts and preferences |
|
|
151
|
+
| `~/.memclaw/AGENTS.md` | Customizable agent instructions and user preferences |
|
|
152
|
+
| `~/.memclaw/memory/YYYY-MM-DD.md` | Timestamped daily entries |
|
|
153
|
+
| `~/.memclaw/memclaw.db` | SQLite index (vector embeddings + FTS5) |
|
|
154
|
+
|
|
155
|
+
### Search Layer
|
|
156
|
+
|
|
157
|
+
Every memory is chunked, embedded, and indexed in SQLite. Retrieval combines two signals:
|
|
158
|
+
|
|
159
|
+
- **Vector search** (70% weight) — cosine similarity via OpenAI embeddings finds semantically related memories even when wording differs
|
|
160
|
+
- **Keyword search** (30% weight) — BM25 via SQLite FTS5 catches exact tokens, names, and identifiers
|
|
161
|
+
- **Temporal decay** — recent memories score higher (30-day half-life), MEMORY.md entries are evergreen
|
|
162
|
+
- **MMR deduplication** — removes near-duplicate results to keep search diverse
|
|
163
|
+
|
|
164
|
+
### Agent Layer
|
|
165
|
+
|
|
166
|
+
Powered by Claude via the [Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview). The agent maintains a rolling 10-message-pair conversation history and decides when to **store** vs **search** based on your intent.
|
|
167
|
+
|
|
168
|
+
| Tool | What it does |
|
|
169
|
+
|------|-------------|
|
|
170
|
+
| `memory_save` | Writes a new entry to today's daily file or MEMORY.md |
|
|
171
|
+
| `memory_search` | Hybrid search across all indexed memories |
|
|
172
|
+
| `image_save` | Generates an AI description of an image and stores it |
|
|
173
|
+
| `image_search` | Retrieves previously stored images by description |
|
|
174
|
+
| `file_write` / `file_read` | Sandboxed file operations within `~/.memclaw/` |
|
|
175
|
+
| `update_instructions` | Appends user preferences to AGENTS.md |
|
|
176
|
+
|
|
177
|
+
## Usage
|
|
178
|
+
|
|
179
|
+
### Interactive Mode (default)
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
memclaw
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Chat naturally:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
> Just had coffee with Alex. She's moving to Berlin next month for a new role at Stripe.
|
|
189
|
+
✓ Memory saved
|
|
190
|
+
|
|
191
|
+
> Who is Alex?
|
|
192
|
+
Based on your memories, Alex is someone you had coffee with recently.
|
|
193
|
+
She's moving to Berlin for a new role at Stripe.
|
|
194
|
+
|
|
195
|
+
> /quit
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Direct Commands
|
|
199
|
+
|
|
200
|
+
These work without the Claude agent — only the OpenAI key is needed for embeddings.
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Save a quick note
|
|
204
|
+
memclaw save "Meeting at 3pm with the design team about the rebrand"
|
|
205
|
+
|
|
206
|
+
# Search your memories
|
|
207
|
+
memclaw search "design team meetings"
|
|
208
|
+
|
|
209
|
+
# Consolidate daily files into MEMORY.md
|
|
210
|
+
memclaw consolidate
|
|
211
|
+
|
|
212
|
+
# Rebuild the search index
|
|
213
|
+
memclaw index
|
|
214
|
+
|
|
215
|
+
# Check your memory vault
|
|
216
|
+
memclaw status
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Saving Images
|
|
220
|
+
|
|
221
|
+
In interactive mode, tell the agent to save an image:
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
> Save the image at ~/photos/whiteboard.jpg — it's our sprint planning board
|
|
225
|
+
✓ Image saved: A whiteboard showing a sprint planning layout with colorful sticky notes...
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The image is described by an AI vision model and the description is stored and indexed like any other memory.
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
On first run, `memclaw` or `memclaw bot` will launch an interactive setup wizard that saves your keys to `~/.memclaw/.env`. Run `memclaw configure` anytime to update them.
|
|
233
|
+
|
|
234
|
+
You can also set keys via environment variables or a `.env` in the current directory — these take the usual precedence over the saved config.
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
memclaw --memory-dir ~/my-vault # override storage location
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### API Keys
|
|
241
|
+
|
|
242
|
+
| Variable | Required | Description |
|
|
243
|
+
|----------|----------|-------------|
|
|
244
|
+
| `OPENAI_API_KEY` | Yes | Embeddings + image descriptions |
|
|
245
|
+
| `ANTHROPIC_API_KEY` | Yes | Powers the Claude agent |
|
|
246
|
+
| `TELEGRAM_BOT_TOKEN` | For Telegram bot | Your Telegram bot token |
|
|
247
|
+
| `ALLOWED_USER_IDS` | For Telegram bot | Comma-separated Telegram user IDs |
|
|
248
|
+
|
|
249
|
+
### Directory Structure
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
~/.memclaw/
|
|
253
|
+
├── MEMORY.md # Permanent / curated memories
|
|
254
|
+
├── AGENTS.md # Agent instructions + user preferences
|
|
255
|
+
├── memclaw.db # SQLite index (embeddings + FTS5)
|
|
256
|
+
└── memory/
|
|
257
|
+
├── 2025-06-15.md # Daily notes
|
|
258
|
+
├── 2025-06-16.md
|
|
259
|
+
└── ...
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Architecture
|
|
263
|
+
|
|
264
|
+
Inspired by [OpenClaw](https://github.com/openclaw/openclaw)'s approach to AI memory:
|
|
265
|
+
|
|
266
|
+
- **Markdown as source of truth** — all memories live as plain text you can read, edit, and version-control
|
|
267
|
+
- **SQLite for indexing** — zero-config database with FTS5 for keyword search and BLOBs for embeddings
|
|
268
|
+
- **NumPy for vectors** — cosine similarity computed in-memory, no native extensions required
|
|
269
|
+
- **Claude Agent SDK** — intelligent agent loop that autonomously decides how to handle your input
|
|
270
|
+
- **Chunking with overlap** — ~300-word chunks with 60-word overlap preserve context across boundaries
|
|
271
|
+
- **Auto-consolidation** — daily files are periodically distilled into MEMORY.md
|
|
272
|
+
- **Filesystem guardrail** — SDK-level callback blocks all file access outside `~/.memclaw/`
|
|
273
|
+
- **Embedding cache** — SHA-256 content hashing skips redundant API calls
|
|
274
|
+
|
|
275
|
+
For a deep dive into how memory storage, search, consolidation, and context injection work, see the [Memory Architecture](docs/memory-architecture.md) doc.
|
|
276
|
+
|
|
277
|
+
## Using as a Library
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
import asyncio
|
|
281
|
+
from memclaw.config import MemclawConfig
|
|
282
|
+
from memclaw.store import MemoryStore
|
|
283
|
+
from memclaw.index import MemoryIndex
|
|
284
|
+
from memclaw.search import HybridSearch
|
|
285
|
+
|
|
286
|
+
async def main():
|
|
287
|
+
config = MemclawConfig()
|
|
288
|
+
store = MemoryStore(config)
|
|
289
|
+
index = MemoryIndex(config)
|
|
290
|
+
search = HybridSearch(config, index)
|
|
291
|
+
|
|
292
|
+
# Save a memory
|
|
293
|
+
path = store.save("The best pizza in town is at Mario's on 5th Ave")
|
|
294
|
+
await index.index_file(path)
|
|
295
|
+
|
|
296
|
+
# Search
|
|
297
|
+
results = await search.search("pizza recommendations")
|
|
298
|
+
for r in results:
|
|
299
|
+
print(f"{r.score:.2f}: {r.content[:80]}")
|
|
300
|
+
|
|
301
|
+
index.close()
|
|
302
|
+
|
|
303
|
+
asyncio.run(main())
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Contributing
|
|
307
|
+
|
|
308
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
309
|
+
|
|
310
|
+
1. Fork the repository
|
|
311
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
312
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
313
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
314
|
+
5. Open a Pull Request
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
319
|
+
|
|
320
|
+
## Acknowledgments
|
|
321
|
+
|
|
322
|
+
- [OpenClaw](https://github.com/openclaw/openclaw) for the memory architecture inspiration
|
|
323
|
+
- [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) for the agent framework
|
|
324
|
+
- [SQLite FTS5](https://www.sqlite.org/fts5.html) for full-text search
|