Local-first, MCP-native unified memory vault โ your AI memory as files you own, shared across every model.
Project description
๐ 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.
pipx install elesync
ele onboard
Install ยท Why local-first ยท Compared to other memory tools ยท Architecture ยท Privacy
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. Claude Desktop, Cursor, Windsurf, Continue, Zed, Cline, and Roo Code connect over stdio with one command. 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 โ Streamable HTTP โ 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
pipx install elesync
ele onboard # interactive: pick a vault path, wire up your AI client
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 your AI client so it picks up the new MCP server. Then ask it: "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):
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 model ("what was true when") | โ supersession history | โ | โ | โ | โ bi-temporal KG |
| Knowledge graph extraction | โ | โ | โ | โ | โ |
| Cross-AI provenance + conflict detection | โ | โ | โ | โ | โ |
| Hosted option | โ (local-only) | โ | โ | โ | โ |
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+.
Recommended โ pipx installs the CLI and MCP server into their own isolated environment, so nothing collides with your other Python tools:
pipx install elesync # CLI + MCP server + all features
Or with pip:
pip install elesync # everything included
pip install "elesync[dev]" # + development tools (ruff, mypy, pre-commit)
Everything ships in the base install: MCP server, semantic search (ONNX embeddings), encryption, auto-import, web UI auth, and mTLS. No extras needed.
Or grab a standalone executable from Releases โ no Python required.
On Windows, scoop installs that same standalone executable (CLI and MCP server, no Python required) and keeps it updated:
scoop install https://raw.githubusercontent.com/darknodebros/EleSync/master/elesync.json
On macOS, Homebrew (via a third-party tap):
brew tap darknodebros/elesync
brew install elesync
Other install options
- conda (community feedstock, when available):
conda install -c conda-forge elesync - uv:
uv tool install elesync - From source:
git clone https://github.com/darknodebros/EleSync && pip install -e ".[dev]"
After install:
ele onboard # interactive setup: vault path + MCP wiring for your AI client
ele doctor # verify everything is connected
ele doctor --fix # repair fixable issues (e.g. stale/missing MCP wiring), then re-check
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, Cursor, Windsurf, Continue, Zed, Cline, Roo Code
ele onboard writes the server entry into the client's own config file. It
backs up the existing file first, preserves other servers, and re-running is
idempotent:
ele onboard # Claude Desktop (the default target)
ele onboard --target cursor # ~/.cursor/mcp.json
ele onboard --target windsurf # ~/.codeium/windsurf/mcp_config.json
ele onboard --target continue # ~/.continue/config.json
ele onboard --target zed # Zed settings.json (context_servers)
ele onboard --target cline # VS Code settings.json (cline.mcpServers)
ele onboard --target roo-code # VS Code settings.json (roo-cline.mcpServers)
--print-only shows the block without writing anything; --config-path
overrides the auto-detected location.
For any client not listed, ele onboard --target generic --print-only
prints a portable snippet:
{
"mcpServers": {
"elesync": {
"command": "elesync",
"args": [],
"env": { "ELESYNC_DIR": "/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 -- but an
off-machine MCP endpoint exposes remember and forget, so since v1.17.0
the server refuses to start one without authentication.
Three steps:
# 1. generate a Bearer token (stored in EleSync's config.json; printed once)
ele auth generate-token
# 2. start the server, naming the public hostname that will reach it
ele serve --transport http --port 8000 --allowed-host xxxx.ngrok-free.dev
# 3. put a tunnel or a TLS reverse proxy in front (quickest: ngrok)
ngrok http 8000
--allowed-host is required for any non-localhost hostname -- the server
keeps DNS-rebinding protection on by default (CVE-2025-66416
in the underlying MCP SDK) and only widens the allow-list to hosts you
explicitly name, rather than disabling the check. It is also how EleSync
knows you are about to be public: any non-local --allowed-host (or a
non-loopback --host) with no token configured makes ele serve exit with
an error instead of starting an open vault. ele auth status and
ele auth revoke manage the token; setting ELESYNC_TOKEN overrides the
stored one for a single run.
Every request must then carry the standard header:
Authorization: Bearer <token>
Then in ChatGPT: Settings -> Connectors -> Advanced -> Developer Mode -> Add
custom connector, server URL https://xxxx.ngrok-free.dev/mcp, and supply
the token through the connector's authentication settings. If a client
genuinely cannot send an Authorization header, ele serve ... --insecure
starts anyway -- loudly, as a deliberate choice -- but treat that URL as
world-readable and world-writable and keep the tunnel alive only while
you're using it.
Verified working: recall and remember both round-trip correctly over a
tunnel, 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. One note of scope honesty:
the Bearer token is currently all-or-nothing -- one token unlocks every
tool, including forget. Per-capability scoping (e.g. a read-only recall
token for a less-trusted client) is on the roadmap.
Tools exposed via MCP
| Tool | What it does |
|---|---|
recall |
Search the vault (BM25 + optional semantic) |
remember |
Write a new memory (optionally supersedes an older one) |
forget |
Delete a memory by ID |
history |
Show a memory's supersession chain โ what a fact used to be, and when it changed |
memory_status |
Counts, sources, last-modified |
list_scopes |
Scope compartments this client can see, and how many memories each holds |
find_conflicts |
Cluster contradictions across sources |
audit_log |
Who read, wrote, or forgot what, and when (requires ELESYNC_AUDIT=1) |
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 |
| 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 |
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
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.
Memory templates
The same thing gets recorded a dozen different ways over a vault's life: one
meeting note tagged meeting, the next tagged meetings, a third untagged.
Recall degrades, and conflict detection and auto-supersession โ both of which
key on tags โ quietly stop working. A template fixes the shape once.
ele template list # five built-ins, plus your own
ele template show meeting # its fields and body
ele add --template person \
--set name=Ana --set role=PM --set detail="runs the platform team"
A template sets type, tags and scopes, and can carry a body skeleton whose
{placeholders} you fill with --set. Anything you pass explicitly wins over
the template; tags union rather than replace. Rendering is strict โ a missing or
misspelled placeholder is an error, because a template that silently produced
Met with {who} would give back the inconsistency it exists to remove.
Make your own, or start from a built-in:
ele template new standup --from meeting \
--body "Standup {date}: {done}. Next: {next}." --tags standup,daily
Templates are JSON in <vault>/templates/. A file shadows a built-in of the
same name, so ele template new person โฆ customises the shipped one and
ele template remove person restores it. They ride along in ele export and
ele backup, so a restore on a new machine brings your capture habits with it.
From an AI client: remember takes a template name and a fields JSON
object, and the memory://templates resource lists what's available โ so an
assistant can capture through the same structures you do, without a ninth tool.
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.
# save memories into compartments
ele add "preferred language: Rust" --scopes coding
# wire a second, restricted connection alongside the full one
ele onboard --target cursor --scopes coding --name elesync-coding
A client wired with --scopes sees only those compartments; --write-scope
sets where its new memories land. To write-lock a client entirely, set
ELESYNC_SCOPES=readonly:coding (or just readonly) in its server entry's
env โ the MCP server then rejects remember and forget from that
connection server-side.
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.
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:
ele usb install /Volumes/MY_DRIVE # creates encrypted vault + launcher + README
ele usb attach /Volumes/MY_DRIVE # wires your AI client 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:
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.
Dark mode toggle (persists in localStorage). Keyboard shortcuts: / to search, N for new memory, ? for help, Esc to close panels, Ctrl+K for command palette. CSV export in addition to JSON. Mobile-responsive down to 375px with touch-friendly targets.
Self-hosted mode: ele web --host 0.0.0.0 binds to all interfaces for multi-device family/team use. A security warning is shown if you expose to the network without authentication or TLS. For HTTPS, pass --tls-cert server.crt --tls-key server.key (or use a reverse proxy with TLS).
By default there's no login โ it binds to 127.0.0.1 only, so it's as private as anything else running on your machine. If you want a login anyway (shared machine, or you're the cautious type), add a user and it turns on automatically:
ele web adduser alice # prompts for a password, hashed with bcrypt
ele web adduser bob --role viewer # read-only account โ can browse/search, can't add/edit/delete
ele web listusers
ele web removeuser bob # remove the last user and login turns back off
Passwords are bcrypt-hashed, session tokens are stored as SHA-256 hashes (never plaintext) in <vault>/.web_auth/, and viewer accounts are enforced server-side, not just hidden in the UI โ a viewer session gets a real 403 on any write attempt, not just a greyed-out button. This is a local-first tool, not a hardened multi-tenant server: for anything exposed past 127.0.0.1, put a real reverse proxy with TLS in front of it.
Summarize with an LLM
ele summarize generates a digest of a vault subset using a local Ollama model or a remote API (OpenAI, Anthropic). No new dependencies โ it uses stdlib urllib.request.
ele summarize --tag work # all memories tagged "work"
ele summarize --since 30d # last 30 days
ele summarize --source chatgpt --format tldr
ele summarize --tag travel --format narrative --save-as # save as a new memory
ele summarize --dry-run # preview the prompt without calling the API
Privacy: a local Ollama server is auto-detected and used by default โ no content leaves your machine. Before sending to a remote API (OpenAI/Anthropic), EleSync prints a warning. Use --dry-run to preview exactly what would be sent.
Config (config.json):
{
"llm": {
"provider": "ollama",
"model": "llama3",
"ollama_url": "http://localhost:11434"
}
}
Or via environment: ELESYNC_LLM_PROVIDER, ELESYNC_LLM_MODEL, ELESYNC_OLLAMA_URL, OPENAI_API_KEY, ANTHROPIC_API_KEY.
Sync across devices
Because the vault is just files, you sync it however you sync files:
- git โ
git inityour 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
- Portable snapshot โ
ele backupwrites a single compressed.elebarchive (including supersession history);ele restorerebuilds losslessly on any machine, into a fresh vault or an existing one:
# machine A โ snapshot
ele backup # timestamped .eleb in <vault>/backups
ele backup --encrypt # passphrase-protected
ele backup list # what's there: date, size, memories, checksum state
ele backup list --verify # re-hash each one and flag anything that changed
# machine B โ restore (idempotent; safe to re-run)
ele restore ~/EleSyncVault/backups/elesync-backup-20260717-205632.eleb
Backups are tracked in a manifest (elesync-backups.json) beside them, recording each
archive's timestamp, size, format version, encryption state, and SHA-256. Set a
retention count to stop them piling up โ old backups are pruned only after a new one
has been written and recorded, so you are never left without a good copy:
ELESYNC_BACKUP_KEEP=7 ele backup # or "backup": {"keep": 7} in config.json
ELESYNC_BACKUP_DIR=/mnt/usb/elesync ele backup # or "backup": {"dir": "..."}
Retention only ever manages that directory. ele backup /some/path.eleb is recorded so
list can see it, but nothing you name explicitly is ever deleted.
Remote destinations โ push and pull backups to S3, B2, GCS, Drive, SFTP, and more via rclone (no cloud SDK in EleSync's dependency tree):
# configure a remote once
rclone config # set up s3:my-bucket, gdrive:, etc.
ele config set backup.destination s3:my-bucket/elesync
# push the latest local backup to the remote (applies backup.keep retention remotely)
ele backup push
# pull the newest remote backup into the local managed directory
ele backup pull
ele backup pull --name elesync-backup-20260728-120000.eleb # specific file
# 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.
Troubleshooting
First stop for any setup problem: ele doctor runs an end-to-end health check (vault present, MCP client wired, extras installed) and prints what's wrong. ele doctor --fix repairs what it can, then re-checks.
Because the markdown notes are the source of truth and the SQLite index is a rebuildable cache, most "it looks wrong" problems are fixed by rebuilding the index โ ele reindex (rebuild from notes) or ele sync (rebuild and report what changed). Neither can lose data.
Common messages and what to do:
| You see | Cause | Fix |
|---|---|---|
This vault is encrypted; install the extra |
Encryption code isn't installed | pip install elesync |
Wrong passphrase โ could not unlock the vault. |
Wrong/typo'd passphrase | Re-enter it; or set ELESYNC_PASSPHRASE for non-interactive use. There is no recovery if the passphrase is truly lost โ restore from a backup. |
Vault not found at <path> |
Command is pointed at the wrong vault | ele vault list to see registered vaults; ele vault switch <name>, or pass --vault <path> / set ELESYNC_DIR. Register a new one with ele vault add <name> <path>. |
This vault looks encrypted, but its encryption details (vault.json) are missing |
vault.json was moved/lost after the vault was encrypted |
Put vault.json back in the vault folder next to notes/. Restore it from a backup if gone โ without it the notes can't be decrypted. |
Semantic mode unavailable โฆ |
Model not downloaded yet, or first-run download failed | Run ele embed to build the vector index. Ensure you're online for the first run (downloads ~130 MB, then fully local). Keyword search still works meanwhile. |
Refusing to start: this server would be reachable off this machine with no authentication |
ele serve --transport http/sse bound public (or --allowed-host names a tunnel) without a token |
ele auth generate-token, then have clients send Authorization: Bearer <token>. Only override with --insecure if you truly intend an open endpoint. |
| Search misses notes you edited elsewhere (git pull, Obsidian, another device) | The local index is stale | ele sync (or ele reindex) โ rebuilds from the markdown and reports added/changed/removed. |
โ ๏ธ Backup written, but its manifest entry could not be saved |
The archive is on disk; only its bookkeeping entry failed | The backup is restorable (ele restore <file>). Retention won't prune on an unconfirmed record โ safe to ignore or re-run the backup. |
| Locked out of the web dashboard | Forgot which logins exist | ele web listusers; ele web adduser <name> / ele web removeuser <name>. Removing all users makes the dashboard open (no login) again. |
Still stuck? Open an issue with the exact command, the full message, and your OS โ see Links.
Performance tuning
EleSync is fast on a personal-scale vault (tens of thousands of memories) with no tuning. For large vaults or constrained hosts, the knobs that matter:
- Keyword vs. semantic search. Plain keyword search (SQLite FTS5) is the default and is effectively instant. Semantic recall (
--semantic/ELESYNC_SEMANTIC=1) adds an embedding model: higher-quality recall, but each memory carries a ~1.5 KB vector and every query embeds the text. Enable it when recall quality matters; leave it off for the lowest latency and memory use. - Let the index stay warm. The SQLite index (
index.db) is the query surface; the markdown is the source of truth. After bulk-editing notes outside EleSync, runele reindexonce rather than letting each command rediscover changes.reindex,sync, andimportnow show a progress bar for large jobs. - Encrypted vaults trade memory for privacy. A locked (encrypted) vault holds its whole index in RAM โ it can't be cached to disk without leaking plaintext โ and rebuilds it from ciphertext on every open. Budget roughly your total note text plus overhead (see the
MemoryStoredocstring). Keep a vault plaintext if it's very large and the host is memory-constrained. - Backups scale with vault size.
ele backupcompresses the whole vault including history;backup.keep(config) prunes old managed backups so the directory doesn't grow unbounded. - Auto-supersession on the write path.
rememberscans for a fact it updates. It's bounded and off the read path, but on a huge vault you can disable it withELESYNC_AUTO_SUPERSEDE=0if writes feel heavy.
Rule of thumb: plaintext + keyword search is the fastest, lightest configuration; add encryption for at-rest privacy and semantic mode for recall quality, each with the cost noted above.
Privacy
- Zero telemetry. EleSync never connects to the internet unless you tell it to (
ele importof 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 feature downloads the BAAI/bge-small-en model from HuggingFace on first use (~130 MB). After that, it runs entirely locally on CPU. The download happens automatically when you first run ele embed or use --semantic search.
Screenshots
Contributions welcome โ see #64. Record with VHS or LICEcap, target < 2 MB per GIF, use a non-personal demo vault.
| Asset | Description | Status |
|---|---|---|
web-ui-overview.png |
Full dashboard (light + dark) | Pending |
web-ui-search.gif |
Semantic search in action | Pending |
web-ui-conflict.gif |
Conflict resolution flow | Pending |
usb-workflow.gif |
Vault on USB: mount โ switch โ sync | Pending |
cli-quickstart.gif |
Install โ sync โ search in ~30s | Pending |
mcp-onboard.gif |
ele onboard for Claude/Cursor |
Pending |
Assets will live in /docs/screenshots/. To contribute, open a PR adding the file and a row to this table.
Status
EleSync is at 1.19.0 (786 tests, ~12,500 LOC). 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 โ - Auto-supersession for untagged updates โ the write-path gate deliberately requires a shared tag today, because a false positive tombstones a live memory. Direction C (shipped 1.13.0) surfaces the untagged/ambiguous cases via
ele conflictsfor a manual accept step; the open question is whether untagged updates should also auto-supersede on save, and how to keep the false-positive rate low without adding heavyweight dependencies. Predicate-anchored heuristic vs. optional semantic backend โ no decision yet. - Performance at scale โ profiling and optimization for vaults with 10K+ memories.
See CONTRIBUTING.md for how to get started. First-time contributors: look for issues tagged good first issue.
License
MIT. See LICENSE.
Troubleshooting
ele command not found โ Make sure pipx (or your venv) is on your PATH. With pipx: pipx ensurepath then restart your terminal. With a venv: activate it first.
Your AI client doesn't know about your memories โ Run ele onboard to wire the MCP server into your client's config, then restart the client. Verify with ele doctor.
ele doctor says MCP SDK not installed โ Run pip install elesync to get the complete package (the MCP SDK is included by default).
Semantic search isn't working โ Run ele embed to build the vector index. The first run downloads a model (~130 MB). Make sure you're online for the first run; after that it's fully local.
Wrong passphrase / can't unlock vault โ Passphrases can't be recovered. If you've forgotten yours, you'll need to start a fresh vault: move or rename the encrypted vault directory, then run ele commands to create a new one.
ele backup push says no destination configured โ Set one with ele config set backup.destination s3:my-bucket/elesync (requires rclone installed and configured).
ele summarize says no LLM provider โ Either install Ollama and run ollama serve, or set OPENAI_API_KEY / ANTHROPIC_API_KEY and pass --provider openai / --provider anthropic.
Web UI won't open โ Run ele web and navigate to http://127.0.0.1:7477 manually. Pass --no-browser to skip auto-opening.
For more, see SETUP.md โ "Something's not working?" section, or open an issue.
FAQ
Where is my data stored? โ In ~/EleSyncVault/ by default (change with $ELESYNC_DIR or --vault). It's plain markdown files plus a SQLite index. No cloud, no server, no account.
Can I sync my vault across machines? โ Yes. The vault is a folder, so iCloud, Dropbox, Syncthing, or Git all work. If the vault is encrypted, it's safe to sync through services you don't fully trust.
Can I use it with ChatGPT? โ Yes. Run ele serve --transport http --allowed-host your-domain and connect ChatGPT's Developer Mode MCP connector to the URL.
Can multiple AIs write at the same time? โ Yes. Each AI tags its memories with a source (chatgpt, claude, gemini, etc.). Conflict detection surfaces when two AIs disagree about the same fact.
Is my data sent to any server? โ No. Everything runs locally. The only exception is ele summarize with a remote provider (OpenAI/Anthropic), which shows a privacy warning before sending anything. Ollama runs locally.
How do I back up? โ ele backup creates a compressed archive. ele backup push sends it to cloud storage via rclone. ele export produces a portable JSON file.
How do I move my vault to another machine? โ Copy the vault folder (or restore from a backup with ele restore). Run ele onboard on the new machine to wire it into your AI clients.
Can I delete a memory? โ Yes: ele forget <id> (find the id with ele search). Deletion is permanent unless the memory was superseded (then it's in ele history).
Links
- Setup guide (non-technical readers): SETUP.md
- Contributing: CONTRIBUTING.md
- Changelog: CHANGELOG.md
- Issues: GitHub Issues
- Website: elesync.dev
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file elesync-1.20.0.tar.gz.
File metadata
- Download URL: elesync-1.20.0.tar.gz
- Upload date:
- Size: 326.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc31c9e433f5b0d82883a0955fa2d39f77398cfe464431fd9d1707dcacbd240f
|
|
| MD5 |
597ecfaa333a142cf713b6e206dfdc96
|
|
| BLAKE2b-256 |
f832ed6d95d2c0cdedb10e7b6b258092960393c9fbce28c030ac6a40793fa321
|
Provenance
The following attestation bundles were made for elesync-1.20.0.tar.gz:
Publisher:
release.yml on darknodebros/EleSync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
elesync-1.20.0.tar.gz -
Subject digest:
bc31c9e433f5b0d82883a0955fa2d39f77398cfe464431fd9d1707dcacbd240f - Sigstore transparency entry: 2272191376
- Sigstore integration time:
-
Permalink:
darknodebros/EleSync@7ddfc5822b9939f76f564c62c738f98e9a69e7e2 -
Branch / Tag:
refs/tags/v1.20.0 - Owner: https://github.com/darknodebros
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7ddfc5822b9939f76f564c62c738f98e9a69e7e2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file elesync-1.20.0-py3-none-any.whl.
File metadata
- Download URL: elesync-1.20.0-py3-none-any.whl
- Upload date:
- Size: 208.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c595349a539ccfda2c5f9e3a3256075904dd4648bd0196430e73a2663ecf4c59
|
|
| MD5 |
c251064ddc698931145ddaded81a0d13
|
|
| BLAKE2b-256 |
999afc18283485d7f014f84f4e5fb1f6de1824426e1edcd4be63975381e6c6db
|
Provenance
The following attestation bundles were made for elesync-1.20.0-py3-none-any.whl:
Publisher:
release.yml on darknodebros/EleSync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
elesync-1.20.0-py3-none-any.whl -
Subject digest:
c595349a539ccfda2c5f9e3a3256075904dd4648bd0196430e73a2663ecf4c59 - Sigstore transparency entry: 2272191565
- Sigstore integration time:
-
Permalink:
darknodebros/EleSync@7ddfc5822b9939f76f564c62c738f98e9a69e7e2 -
Branch / Tag:
refs/tags/v1.20.0 - Owner: https://github.com/darknodebros
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7ddfc5822b9939f76f564c62c738f98e9a69e7e2 -
Trigger Event:
push
-
Statement type: