Skip to content
45 changes: 33 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Store your thoughts. Save your images and links. Ask anything, anytime.
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![Anthropic API](https://img.shields.io/badge/Anthropic-API-blueviolet.svg)](https://docs.anthropic.com/)
[![Telegram Bot](https://img.shields.io/badge/Telegram-Bot-26A5E4.svg)](https://core.telegram.org/bots)
[![WhatsApp](https://img.shields.io/badge/WhatsApp-coming_soon-lightgrey.svg)]()
[![WhatsApp](https://img.shields.io/badge/WhatsApp-Bot-25D366.svg)](https://github.com/krypton-byte/neonize)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)

</div>
Expand Down Expand Up @@ -46,32 +46,54 @@ memclaw

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`.

## Telegram Bot
## Messaging Platforms

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.

> **WhatsApp support is coming soon.** Telegram is the only supported messaging platform for now.
Both platforms share the same agent, memories, and search index — your data is unified regardless of how you interact.

The bot shows a **typing indicator** while processing so you know it's working on your request.
### Telegram Bot

### Setup
The Telegram bot shows a **typing indicator** while processing so you know it's working on your request.

#### Setup

1. Create a bot via [@BotFather](https://t.me/BotFather) and copy the token.
2. Get your Telegram user ID (e.g. via [@userinfobot](https://t.me/userinfobot)).
3. Start the bot — on first run you'll be prompted for all keys:

```bash
memclaw bot
memclaw telegram
```

### WhatsApp Bot

Uses your **personal WhatsApp account** via WhatsApp Web pairing — no Meta Business account, no webhooks, no public server. Powered by [`neonize`](https://github.com/krypton-byte/neonize) (whatsmeow under the hood).

#### Prerequisite: libmagic

neonize depends on `python-magic`, which needs the `libmagic` system library:

- macOS: `brew install libmagic`
- Debian/Ubuntu: `sudo apt install libmagic1`
- Fedora/RHEL: `sudo dnf install file-libs`

#### Setup

```bash
memclaw whatsapp
```

To update keys later: `memclaw configure`.
On first run a QR code is printed to your terminal. On your phone: **Settings → Linked Devices → Link a Device**, and scan it. The session persists under `~/.memclaw/whatsapp/` so you only pair once.

Only messages you send to yourself (via WhatsApp's "Message Yourself" chat) are processed. DMs from other people and group messages are ignored.

### What it handles

| Message type | What happens |
|-------------|-------------|
| **Text** | Agent decides: store as memory, search existing memories, or both. Links are extracted, fetched, and summarized automatically. |
| **Photo** | AI-described via vision model, stored and indexed. Agent acknowledges and responds. File ID saved for later retrieval. |
| **Photo** | AI-described via vision model, stored and indexed. Agent acknowledges and responds. Saved for later retrieval. |
| **Voice** | Transcribed via Whisper, stored as text. Agent responds to the content. Links extracted. |

### Examples
Expand All @@ -93,7 +115,8 @@ Here's the sprint planning whiteboard you saved last week.

```mermaid
flowchart LR
You -->|text / images / links| Agent[Memclaw Agent]
TG[Telegram] <-->|text / images / links<br>response + images| Agent[Memclaw Agent]
WA[WhatsApp] <-->|text / images / links<br>response + images| Agent

subgraph sandbox ["~/.memclaw/"]
Agent -->|save| Tools1["memory_save<br>image_save<br>file_write"]
Expand All @@ -102,8 +125,6 @@ flowchart LR
DB --> Tools2["memory_search<br>image_search"]
Tools2 -->|results| Agent
end

Agent -->|response + images| You
```

Memclaw draws inspiration from [OpenClaw](https://github.com/openclaw/openclaw)'s memory architecture and uses the [Anthropic API](https://docs.anthropic.com/) directly with a lightweight agentic loop.
Expand Down Expand Up @@ -196,7 +217,7 @@ The image is described by an AI vision model and the description is stored and i

## Configuration

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.
On first run, `memclaw`, `memclaw telegram`, or `memclaw whatsapp` will launch an interactive setup wizard that saves your keys to `~/.memclaw/.env`. The wizard only prompts for keys relevant to the command you ran — run `memclaw configure` anytime to update all keys.

You can also set keys via environment variables or a `.env` in the current directory — these take the usual precedence over the saved config.

Expand Down
4 changes: 3 additions & 1 deletion memclaw/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ class MemclawAgent:
Uses the raw Anthropic Messages API with a hand-rolled agentic loop.
"""

def __init__(self, config: MemclawConfig):
def __init__(self, config: MemclawConfig, platform: str | None = None):
self.config = config
self.platform = platform
self.store = MemoryStore(config)
self.index = MemoryIndex(config)
self.search = HybridSearch(config, self.index)
Expand All @@ -103,6 +104,7 @@ def __init__(self, config: MemclawConfig):
index=self.index,
search=self.search,
found_images=self._found_images,
platform=platform,
)

# ── Startup / sync ───────────────────────────────────────────────
Expand Down
4 changes: 2 additions & 2 deletions memclaw/bot/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MessageHandlers:
def __init__(self, config: MemclawConfig, openai_client: AsyncOpenAI):
self.config = config
self.openai_client = openai_client
self.agent = MemclawAgent(config)
self.agent = MemclawAgent(config, platform="telegram")
self.link_processor = LinkProcessor(openai_client)

def _check_user(self, user_id: int) -> bool:
Expand Down Expand Up @@ -151,7 +151,7 @@ async def handle_photo(self, update: Update, context: ContextTypes.DEFAULT_TYPE)
"\nThis summary has NOT been saved yet. Save it if the content is worth remembering."
)

prompt_text = f"User sent a photo. file_id={photo.file_id}"
prompt_text = f"User sent a photo. media_ref={photo.file_id}"
if caption:
prompt_text += f"\nCaption: {caption}"
if link_info:
Expand Down
Loading
Loading