Metadata-Version: 2.4
Name: elesync
Version: 1.6.0
Summary: Local-first, MCP-native unified memory vault — your AI memory as files you own, shared across every model.
Author: Alphanymous
License: MIT
Project-URL: Homepage, https://github.com/darknodebros/EleSync
Project-URL: Repository, https://github.com/darknodebros/EleSync
Project-URL: Issues, https://github.com/darknodebros/EleSync/issues
Keywords: mcp,ai-memory,local-first,claude,chatgpt,gemini,grok,deepseek,memory,elesync
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: mcp
Requires-Dist: mcp[cli]>=1.2.0; extra == "mcp"
Provides-Extra: semantic
Requires-Dist: fastembed>=0.3.0; extra == "semantic"
Provides-Extra: encryption
Requires-Dist: pynacl>=1.5; extra == "encryption"
Provides-Extra: watch
Requires-Dist: watchdog>=4.0; extra == "watch"
Provides-Extra: dev
Requires-Dist: mcp[cli]>=1.2.0; extra == "dev"
Requires-Dist: fastembed>=0.3.0; extra == "dev"
Requires-Dist: pynacl>=1.5; extra == "dev"
Requires-Dist: watchdog>=4.0; extra == "dev"
Dynamic: license-file

<!--
README for EleSync v1.5.x
Audience: technical readers landing from HN / r/LocalLLaMA / GitHub search.
Goal: explain what it is in 3 sentences, prove it's real, get them to try it.
Non-developer audience is served by SETUP.md (linked below), not this file.
-->

# 🐘 EleSync

**A local memory vault that every AI can read and write to over MCP. One folder of markdown files on your machine. Claude, ChatGPT, Gemini, and any other MCP-aware client share it live — no service, no API key, no cloud.**

```bash
pip install elesync
ele onboard
```

[Install · Why local-first · Compared to other memory tools · Architecture · Privacy](#install)

---

## The 60-second pitch

Every AI you talk to has its own siloed memory. Claude doesn't know what you told ChatGPT. ChatGPT doesn't know your Gemini context. You repeat yourself constantly.

EleSync turns that around: **the vault is yours, on your disk**, and every model is a client of it. It speaks the [Model Context Protocol](https://modelcontextprotocol.io). Claude Desktop, Cursor, Cline, and Continue connect over stdio with zero setup. ChatGPT's Developer Mode connector needs a remote transport (Streamable HTTP) instead of stdio -- EleSync supports that too, tunneled or deployed. Tested live: ChatGPT reading and writing to the same vault Claude uses, over a tunnel, today.

The vault itself is just a directory of markdown files with YAML frontmatter, an SQLite FTS5 index, and (optionally) ONNX embeddings for semantic recall. No server. No daemon. No account. You can `cat` your memories. You can `git push` them. You can encrypt the whole vault and carry it on a USB stick.

---

## How it works

```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Claude    │    │   ChatGPT   │    │ MCP client  │
│   Desktop   │    │  (MCP)      │    │ (Cursor…)   │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │
       │  MCP over stdio  │  MCP over stdio  │  MCP over stdio
       └──────────┬───────┴──────────┬───────┘
                  ▼                  ▼
          ┌──────────────────────────────┐
          │    ele serve                 │
          │  (MCP server, ~600 LOC)      │
          └──────────────┬───────────────┘
                         ▼
          ┌──────────────────────────────┐
          │   ~/EleSyncVault/            │
          │   ├── notes/ *.md   (truth)  │
          │   ├── index.sqlite  (FTS5)   │
          │   └── vectors/ *.npy (opt.)  │
          └──────────────────────────────┘
```

The markdown files are the source of truth. The SQLite index is a derived cache rebuilt from them on demand (`ele sync`). If the index is ever corrupt, delete it — `ele` rebuilds from the markdown.

---

## Try it in under two minutes

```bash
pip install elesync
ele onboard           # interactive: pick a vault path, wire up Claude Desktop
ele remember "I'm a Rust developer; prefer concise code reviews without preamble"
ele recall "what languages do I use"
# > I'm a Rust developer; prefer concise code reviews without preamble  (claude · fact · 2026-06-25)
```

Restart Claude Desktop. Ask Claude: *"What do you remember about me?"* — it'll see what you just stored.

For the non-CLI flow (web UI, drag-and-drop import, no terminal):

```bash
ele web
```

…opens a local dashboard at `127.0.0.1:7477`.

---

## How it compares (mid-2026 landscape)

The "AI memory" space has split into two camps. Developer infrastructure for building agents (mem0, Letta, Zep, Graphiti, LangMem) is one thing. **A memory vault you own, that the AIs you already use plug into**, is a different thing. EleSync is the second.

| | EleSync | OpenMemory MCP | mem0 | Letta | Zep / Graphiti |
|---|---|---|---|---|---|
| Storage | **Plain markdown + SQLite** | mem0 backend | Their DB | Their DB | Postgres + KG |
| What it stores | Your memories | Your memories | Memories for your agents | Tiered memory for agents | Temporal KG |
| Who it's for | **You** | You | Agent builders | Agent builders | Agent builders |
| Setup | `pip install` | mem0 install | SDK integration | SDK integration | Docker compose |
| Encryption at rest | **XSalsa20-Poly1305 + argon2id** | – | – | – | – |
| Portable USB vault | **✓** | – | – | – | – |
| Files inspectable in `$EDITOR` | **✓** | ✗ | ✗ | ✗ | ✗ |
| Temporal validity windows | – | – | – | – | ✓ |
| Knowledge graph extraction | – | – | – | – | ✓ |
| Cross-AI provenance + conflict detection | **✓** | – | – | – | – |
| Hosted option | – (local-only) | ✓ | ✓ | ✓ | ✓ |

**Where EleSync is genuinely behind**: no temporal model (Zep/Graphiti win at "what was true *when*"), no automatic entity/relationship extraction, no semantic decay. These are deliberate scope choices — files-on-disk is the constraint, and a knowledge graph in markdown stops looking like markdown fast.

**Where it's genuinely ahead**: you can grep your memory. You can `git diff` what changed last week. You can revoke your USB drive and your memory walks out the door with you, encrypted, readable on any machine with a Python install.

---

## Install

Requires Python 3.10+.

```bash
pip install elesync                  # core: CLI + MCP server
pip install "elesync[semantic]"      # + ONNX embeddings (BAAI/bge-small-en, ~30MB download on first use)
pip install "elesync[encryption]"    # + at-rest encryption via libsodium
pip install "elesync[watch]"         # + auto-import from ~/Downloads
pip install "elesync[dev]"           # everything above
```

Or grab a standalone executable from [Releases](https://github.com/darknodebros/EleSync/releases) — no Python required.

After install:

```bash
ele onboard          # interactive setup: vault path + MCP wiring for Claude Desktop
ele doctor           # verify everything is connected
```

`ele onboard` writes the MCP server entry into `claude_desktop_config.json` (or the equivalent for other clients). It backs up the existing config first. Re-running is idempotent.

---

## Use it with any MCP client

EleSync exposes itself as a standard MCP server, over either of the two
transports the MCP spec defines: **stdio** (local clients) or **Streamable
HTTP** (remote clients).

### Local clients (stdio) -- Claude Desktop, Cursor, Cline, Continue

Auto-wire for Claude Desktop:
```bash
ele onboard           # writes ~/.config/Claude/claude_desktop_config.json
```

Manual config for everything else:
```json
{
  "mcpServers": {
    "elesync": {
      "command": "elesync",
      "args": [],
      "env": { "ELESYNC_VAULT": "/Users/you/EleSyncVault" }
    }
  }
}
```

### Remote clients (Streamable HTTP) -- ChatGPT Developer Mode, and anything else off-machine

ChatGPT's MCP connector (Developer Mode, shipped Sept 2025) requires a
remote transport -- it can't launch a local stdio process the way Claude
Desktop does. EleSync's server can switch transports with a flag:

```bash
ele serve --transport http --port 8000 --allowed-host your-tunnel-host.example
```

`--allowed-host` is required for any non-localhost hostname -- the server
keeps DNS-rebinding protection on by default ([CVE-2025-66416](https://github.com/modelcontextprotocol/python-sdk/security/advisories/GHSA-9h52-p55h-vw2f)
in the underlying MCP SDK) and only widens the allow-list to hosts you
explicitly name, rather than disabling the check.

To reach it from outside your machine, put it behind a tunnel (quickest:
[ngrok](https://ngrok.com)) or a reverse proxy with TLS:

```bash
# terminal 1
ele serve --transport http --port 8000 --allowed-host xxxx.ngrok-free.dev

# terminal 2
ngrok http 8000
```

Then in ChatGPT: **Settings -> Connectors -> Advanced -> Developer Mode -> Add
custom connector**, server URL `https://xxxx.ngrok-free.dev/mcp`. Verified
working: `recall` and `remember` both round-trip correctly, including
finding memories written earlier by Claude -- the actual point of EleSync.

For a permanent remote deployment (not just testing), put a real domain +
TLS cert in front instead of a free ngrok tunnel, and add MCP-level auth
(EleSync doesn't include its own auth layer -- treat the HTTP endpoint as
unauthenticated and don't expose it without a reverse proxy that adds one).

### Tools exposed via MCP

| Tool | What it does |
|---|---|
| `recall` | Search the vault (BM25 + optional semantic) |
| `remember` | Write a new memory |
| `forget` | Delete a memory by ID |
| `memory_status` | Counts, sources, last-modified |
| `find_conflicts` | Cluster contradictions across sources |

---

## Importing existing memory from other AIs

The export landscape changed in 2026 — most providers retreated from file-based memory exports to "ask the assistant for your memories" workflows. EleSync handles both shapes.

| Source | What works today | Adapter |
|---|---|---|
| **ChatGPT conversation export** (Settings → Data Controls → Export Data) | The ZIP contains `conversations.json` — full chat history. `ele import` parses it. | ✓ verified |
| **ChatGPT memory** (the small set of explicit facts) | No file export exists in 2026. Use the in-app copy-paste prompt and save the output as text. | partial — see [SETUP.md](SETUP.md#chatgpt-memory) |
| **Claude memory** | Same copy-paste pattern as ChatGPT memory; no file export. | partial |
| **Gemini** | Via Google Takeout (export of conversation history, not memory). | ✓ verified |
| **Grok / DeepSeek / Perplexity / Copilot** | Adapter built; export availability varies by region (Grok memory is EU-blocked). | experimental |

```bash
ele import ~/Downloads/conversations.json --source chatgpt
ele import ~/Downloads/takeout-gemini.zip  --source gemini
ele watch ~/Downloads        # auto-detects and imports as exports arrive
```

The `conversations.json` from a full ChatGPT export can be **multiple gigabytes**. EleSync streams it; you don't need to unzip the full archive.

---

## Architecture

About 4,000 lines of Python. No third-party services. The dependencies you need:

| Layer | Dependency | Why |
|---|---|---|
| Core CLI + MCP | stdlib only | Zero required deps |
| Semantic recall | `fastembed` (ONNX) | BAAI/bge-small-en, runs on CPU |
| Encryption | `pynacl` | libsodium bindings, XSalsa20-Poly1305 |
| Auto-import watch | `watchdog` | File system events |

`ele serve` boots an MCP server over stdio. `ele web` boots a local HTTP server (`127.0.0.1` only) that exposes a JSON REST API and an embedded HTML/CSS/JS dashboard. The web UI has zero external dependencies — no CDN, no analytics, no fonts loaded from third parties.

**Provenance is first-class.** Every memory carries `source` (`claude`, `chatgpt`, `gemini`, `manual`, …) and `created_at`. When two sources contradict each other, `find_conflicts` surfaces the cluster so you can decide which one is true.

**Scoped sharing** lets you give one MCP client a different view of the vault than another. Useful for keeping work memories away from a coding assistant, or hiding personal context from a client you don't fully trust.

```bash
# tag memories into compartments
ele scope --grant work,coding "preferred language: Rust"

# wire a second connection with restricted view
ele onboard --client cursor --grant coding-only
```

---

## Encryption + USB portable vault

EleSync can encrypt the entire vault at rest. The encryption is real cryptography (libsodium's secretbox: XSalsa20-Poly1305 with Poly1305 MAC, keys derived via argon2id), not a base64 wrapper.

```bash
ele encrypt              # one-time: convert an existing vault to encrypted form
                         # passphrase is hashed with argon2id, never stored
ele serve                # prompts for passphrase, unlocks in memory only
```

The same vault format runs on a USB drive with a launcher script. Plug into any machine with Python, run `RUN_ME.py`, unlock with the passphrase, and Claude / ChatGPT on that machine talk to it:

```bash
ele usb install /Volumes/MY_DRIVE     # creates encrypted vault + launcher + README
ele usb attach   /Volumes/MY_DRIVE    # wires Claude Desktop on this machine
ele usb detach   /Volumes/MY_DRIVE    # cleanly unwires before unplug
ele usb status   /Volumes/MY_DRIVE    # what's on the drive?
```

---

## Web UI

`ele web` launches a local dashboard for non-CLI users:

![EleSync web UI dashboard](docs/screenshots/web-ui-dashboard.png)

Browse, search, edit, import drag-and-drop, switch between vaults (including USB), add/delete memories. The UI is one HTML file with embedded JS — no build step, no framework, no external dependencies.

---

## Sync across devices

Because the vault is just files, **you sync it however you sync files**:

- **git** — `git init` your vault, push to GitHub/GitLab/Forgejo
- **Syncthing** — peer-to-peer, no cloud
- **iCloud / Dropbox / Drive** — works fine, just point your vault at the synced folder
- **Encrypted USB** — see above

```bash
# device A
cd ~/EleSyncVault && git add . && git commit -m "memories" && git push

# device B, after pulling
ele sync            # rebuilds the SQLite index from markdown
```

The SQLite index is gitignored by default. Only the markdown is the source of truth.

---

## Privacy

- **Zero telemetry.** EleSync never connects to the internet unless you tell it to (`ele import` of a URL, semantic model download on first use).
- **Zero accounts.** There is no signup. There is no server.
- **Zero ads, zero tracking, zero data collection.** Not "we don't do that *yet*". There is no business model that depends on your data.
- **The vault is yours.** Delete it and EleSync forgets everything.

The semantic-recall extra downloads the BAAI/bge-small-en model from HuggingFace on first use (~30MB). After that, it runs entirely locally on CPU. You can skip the download by not installing `[semantic]`.

---

## Status

EleSync is on the **1.5.x** line. The 1.x line will not break compatibility — vault format, MCP tool names, and CLI commands are stable until a 2.0.

## Roadmap

What's planned or in design — contributions welcome on any of these:

- **Knowledge graph (design phase)** — lightweight entity/relation tagging where the calling AI supplies structured tags at `remember()` time. No local NLP model, no API calls. [Design discussion →](https://github.com/darknodebros/EleSync/issues)
- **Temporal validity** — "this fact was true from X to Y." Closes the gap with Zep/Graphiti without over-engineering the file format.
- **Text-based memory import** — `ele paste` or a web UI textarea for the copy-paste memory export workflow that ChatGPT/Claude/Gemini now use.
- **Remote transport auth** — API key or OAuth middleware for permanent `--transport http` deployments.
- **Performance at scale** — profiling and optimization for vaults with 10K+ memories.

See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get started. First-time contributors: look for issues tagged [`good first issue`](https://github.com/darknodebros/EleSync/labels/good%20first%20issue).

---

## License

MIT. See [LICENSE](LICENSE).

---

## Links

- **Setup guide (non-technical readers)**: [SETUP.md](SETUP.md)
- **Contributing**: [CONTRIBUTING.md](CONTRIBUTING.md)
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
- **Issues**: [GitHub Issues](https://github.com/darknodebros/EleSync/issues)
- **Website**: [elesync.dev](https://elesync.dev)
