E2E encrypted portable AI memory — your context travels with you
Project description
vault-sync
End-to-end encrypted portable AI memory with CRDT sync
Quick Start • Installation • API Reference • Architecture • Contributing
What is vault-sync?
vault-sync is a portable, encrypted memory layer for AI applications. It lets you store, retrieve, and sync conversations, facts, and context across devices and sessions—without ever exposing your data in plaintext.
Think of it as a personal brain for your AI: it remembers what matters, keeps it private, and stays in sync across all your devices.
Key Features
- End-to-End Encryption – Your data is encrypted locally with NaCl before it ever leaves your machine
- CRDT Sync – Conflict-free replicated data types enable seamless multi-device synchronization
- Vector Clocks – Precise causality tracking for perfect merge semantics
- SQLite Storage – Lightweight, zero-config, portable database
- LangChain & Anthropic Ready – First-class integrations with popular AI frameworks
- 22 Passing Tests – Battle-tested reliability
The Problem: AI Amnesia
Every time you start a new conversation with an AI, it forgets everything. Your preferences, your context, your history—gone.
Today: "I prefer dark mode and use Python 3.12"
Tomorrow: "What's my preference?" → "I don't know you"
vault-sync solves this by giving your AI a persistent, encrypted memory that travels with you.
How It Works
Encryption Flow
Your data is encrypted client-side before storage:
┌─────────────────────────────────────────────────────────────┐
│ ENCRYPTION FLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ plaintext│───▶│ VaultCrypto │───▶│ encrypted_blob │ │
│ │ (JSON) │ │ (NaCl/box) │ │ (stored in DB) │ │
│ └──────────┘ └──────────────┘ └──────────────────┘ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Per-device │ │ │
│ │ │ key pairs │ │ │
│ │ └──────────────┘ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Encrypted SQLite Store │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ memory1 │ │ memory2 │ │ memory3 │ ... │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
CRDT Sync
Conflicts are resolved automatically using vector clocks:
┌─────────────────────────────────────────────────────────────┐
│ CRDT SYNC │
├─────────────────────────────────────────────────────────────┤
│ │
│ Device A Device B │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ VC: {A:3} │ │ VC: {A:2,B:1}│ │
│ │ memories... │ │ memories... │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ │ ┌────────────────┐ │ │
│ └───▶│ Sync Manager │◀───┘ │
│ │ │ │
│ │ 1. Merge VCs │ │
│ │ 2. Resolve │ │
│ │ conflicts │ │
│ │ 3. Replicate │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Merged VC: │ │
│ │ {A:3, B:1} │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Vector Clock Tracking
Every mutation is tracked with a vector clock for perfect causality:
┌─────────────────────────────────────────────────────────────┐
│ VECTOR CLOCKS │
├─────────────────────────────────────────────────────────────┤
│ │
│ Timeline: │
│ │
│ t1: {A:1} → Device A writes │
│ t2: {A:1, B:1} → Device B joins │
│ t3: {A:2, B:1} → Device A writes again │
│ t4: {A:2, B:2} → Device B writes │
│ t5: {A:3, B:2} → Device A writes (concurrent?) │
│ │
│ Merge at t5: │
│ ┌────────────────────────────────────────────────────┐ │
│ │ If VC(A) > VC(B): A wins │ │
│ │ If VC(B) > VC(A): B wins │ │
│ │ If concurrent: last-write-wins by timestamp │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Installation
# From PyPI (when published)
pip install vault-sync
# From source
git clone https://github.com/your-org/vault-sync.git
cd vault-sync
pip install -e ".[dev]"
Requirements
- Python 3.10+
- SQLite 3.35+
- pynacl
- langchain (optional)
- anthropic (optional)
Quick Start
from vault_sync import VaultStore, VaultCrypto
# Initialize with encryption
crypto = VaultCrypto.generate_keypair()
store = VaultStore(crypto=crypto)
# Store a memory
store.put(
key="user_preferences",
value={"theme": "dark", "language": "en", "timezone": "UTC-5"},
tags=["preferences", "ui"]
)
# Retrieve it
prefs = store.get("user_preferences")
print(prefs) # {'theme': 'dark', 'language': 'en', 'timezone': 'UTC-5'}
# Search memories
results = store.search(query="dark mode")
Python API Reference
VaultStore
class VaultStore:
def __init__(self, crypto: VaultCrypto, db_path: str = "vault.db"):
"""Initialize the vault store with encryption keys."""
def put(self, key: str, value: dict, tags: List[str] = None) -> str:
"""Store an encrypted memory. Returns the memory ID."""
def get(self, key: str) -> Optional[dict]:
"""Retrieve and decrypt a memory by key."""
def search(self, query: str = None, tags: List[str] = None) -> List[dict]:
"""Search memories by query or tags."""
def delete(self, key: str) -> bool:
"""Delete a memory by key."""
def list_all(self) -> List[dict]:
"""List all stored memories."""
def sync(self, remote: 'VaultStore') -> SyncResult:
"""Sync with another vault store using CRDT merge."""
VaultCrypto
class VaultCrypto:
@classmethod
def generate_keypair(cls) -> 'VaultCrypto':
"""Generate a new NaCl keypair for encryption."""
def encrypt(self, plaintext: bytes) -> bytes:
"""Encrypt data with the public key."""
def decrypt(self, ciphertext: bytes) -> bytes:
"""Decrypt data with the private key."""
def export_public_key(self) -> str:
"""Export the public key (safe to share)."""
VectorClock
class VectorClock:
def __init__(self, node_id: str):
"""Initialize a vector clock for a specific node."""
def increment(self) -> None:
"""Increment the local counter."""
def merge(self, other: 'VectorClock') -> 'VectorClock':
"""Merge with another vector clock (takes element-wise max)."""
def happens_before(self, other: 'VectorClock') -> bool:
"""Check if this event happened before another."""
def concurrent_with(self, other: 'VectorClock') -> bool:
"""Check if events are concurrent."""
LangChain Integration
Use vault-sync as a memory backend for LangChain:
from langchain.memory import ConversationBufferMemory
from vault_sync.integrations.langchain import VaultSyncMemory
# Initialize with vault-sync backend
vault = VaultStore(crypto=crypto)
memory = VaultSyncMemory(vault=vault, return_messages=True)
# Use in a chain
from langchain.chains import ConversationChain
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-20250514")
chain = ConversationChain(llm=llm, memory=memory)
# Conversations are automatically encrypted and stored
response = chain.predict(input="My name is Alice")
response = chain.predict(input="What's my name?") # Remembers!
Anthropic Integration
Direct integration with Anthropic's API:
from vault_sync.integrations.anthropic import AnthropicMemory
# Initialize
memory = AnthropicMemory(vault=vault)
# Store facts
memory.store_fact("User prefers concise responses", importance="high")
memory.store_fact("User is working on a Python project", importance="medium")
# Retrieve context for a prompt
context = memory.get_context(limit=10)
system_prompt = f"Previous context:\n{context}\n\nRespond to the user."
# Use with Anthropic API
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=system_prompt,
messages=[{"role": "user", "content": "Continue where we left off"}]
)
Cross-Device Sync
vault-sync uses CRDTs to sync across devices without conflicts:
from vault_sync import VaultStore, VaultCrypto, SyncManager
# Device A (laptop)
crypto_a = VaultCrypto.generate_keypair()
store_a = VaultStore(crypto=crypto_a, db_path="vault_a.db")
store_a.put("note", {"content": "Meeting at 3pm"})
# Device B (phone) - shares the same public key
crypto_b = VaultCrypto.from_public_key(crypto_a.export_public_key())
store_b = VaultStore(crypto=crypto_b, db_path="vault_b.db")
# Sync
sync_manager = SyncManager()
result = sync_manager.sync(store_a, store_b)
print(result.merged) # 1
print(result.conflicts) # 0 (CRDTs resolve automatically)
print(result.clock) # {'A': 1, 'B': 0}
Sync Modes
| Mode | Description | Use Case |
|---|---|---|
push |
Send local changes to remote | Upload from device |
pull |
Fetch remote changes | Download to device |
bidirectional |
Full two-way sync | Default sync |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Application Layer │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ LangChain │ │ Anthropic │ │ Custom │ │ │
│ │ │ Integration │ │ Integration │ │ App │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ └─────────┼────────────────┼────────────────┼───────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Core Layer │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ VaultStore │ │ │
│ │ │ • put / get / delete / search / list_all │ │ │
│ │ │ • sync (CRDT merge) │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────┼──────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ VaultCrypto │ │ VectorClock │ │ SyncManager│ │
│ │ │ │ │ │ │ │
│ │ • encrypt │ │ • merge │ │ • push │ │
│ │ • decrypt │ │ • compare │ │ • pull │ │
│ │ • keypairs │ │ • track │ │ • bidir │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Storage Layer │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ SQLite Database │ │ │
│ │ │ • memories table (encrypted blobs) │ │ │
│ │ │ • vector_clocks table (causality tracking) │ │ │
│ │ │ • sync_metadata table (sync state) │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Contributing
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Clone your fork
git clone https://github.com/your-username/vault-sync.git
cd vault-sync
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linter
ruff check .
# Run type checker
mypy .
Code Style
- Follow PEP 8
- Use type hints everywhere
- Write docstrings for all public APIs
- Keep functions focused and small
Roadmap
v1.0 (Current)
- Core VaultStore with encryption
- VectorClock causality tracking
- CRDT sync between devices
- LangChain integration
- Anthropic integration
- 22 passing tests
v1.1 (Planned)
- SQLite WAL mode for concurrent access
- Export/import vault as encrypted JSON
- Webhook notifications on sync
- CLI tool for vault management
v2.0 (Future)
- Distributed sync via libp2p
- Zero-knowledge proofs for search
- Mobile SDKs (iOS/Android)
- Browser extension for web apps
License
MIT License - see LICENSE for details.
Built with ❤️ for the AI community
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 vault_sync_ai-0.1.0.tar.gz.
File metadata
- Download URL: vault_sync_ai-0.1.0.tar.gz
- Upload date:
- Size: 25.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f92782a9ddaf7fc093c11e4a106d04001ccaed3d516236b73e9ce9b81f486c9
|
|
| MD5 |
6aa93eef18168dd6ede2a2006bf5e23b
|
|
| BLAKE2b-256 |
420c7849d02609a4568e1df6ed6857c0ebd633d0d4aaf3cbf3f81f305a59fbdc
|
File details
Details for the file vault_sync_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vault_sync_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34eea6c3b13b021e16b537e9c97035acf834cad416083f4e45c9258e145b97a9
|
|
| MD5 |
5c071186a7067f39c60f1bcb48dd42ad
|
|
| BLAKE2b-256 |
bccef733ff63b4c9dded0638e06ba1f17b74a26a2f45dd2bb9c257e6ac624e41
|