Cloud Sync
Sync sessions, context, and index data across machines with encryption, delta chunking, and conflict resolution.
Nella’s Cloud Sync lets you share sessions, context, and index data across machines. Everything is encrypted, compressed, and synced with delta chunking for minimal bandwidth.
Sync Tiers
| Tier | Adapter | Description |
|---|---|---|
local | LocalSyncAdapter | JSON files on disk. No cloud. Default. |
supabase | SupabaseSyncAdapter | Auth, API keys, context sync via Supabase Realtime. |
gcp | GCPSyncAdapter | Cloud SQL with pgvector. Full workspace, file, and chunk sync with vector/text/hybrid search at scale. |
The system falls back gracefully — if the primary tier fails to connect, it drops to local automatically.
How It Works
- Files are split into fixed-size delta chunks (default: 256 KB)
- Each chunk is hashed (SHA-256) — only changed chunks are uploaded
- Chunks can be compressed (gzip) and encrypted (AES-256-GCM)
- A manifest tracks every file’s chunks, hashes, and modification times
- Conflict resolution handles simultaneous edits across machines
Delta Chunking
Small files (≤ 64 KB by default) are uploaded as a single chunk. Larger files are split into fixed-size chunks. On subsequent syncs, only chunks with changed hashes are transferred — drastically reducing bandwidth for large codebases.
Configuration
{
sync: {
tier: "supabase", // "local" | "supabase" | "gcp"
cloudSync: {
autoSyncInterval: 300, // seconds, 0 = disabled
conflictResolution: "newest-wins",
encryption: true,
encryptionKey: "your-32-byte-key",
compression: true,
compressionLevel: 6, // 0-9
bandwidthLimitKBps: 0, // 0 = unlimited
offlineQueueEnabled: true,
deltaChunkSizeKB: 256,
include: ["**/*.ts", "**/*.json"],
exclude: ["node_modules/**", "dist/**"]
}
}
}
Conflict Resolution
When the same file is modified on multiple machines, Nella detects the conflict and applies your chosen strategy:
| Strategy | Behavior |
|---|---|
local-wins | Keep local version, discard remote |
remote-wins | Accept remote version, discard local |
newest-wins | Keep whichever was modified most recently |
manual | Flag the conflict for manual resolution |
Conflicts include a unified diff for review:
{
id: string;
path: string;
localHash: string;
remoteHash: string;
localModified: Date;
remoteModified: Date;
unifiedDiff: string; // diff for review
resolution?: "local" | "remote";
}
Encryption
All data is encrypted using AES-256-GCM with a 12-byte IV and 16-byte authentication tag. The encryption key must be 32 bytes and is stored in the format iv:authTag:encrypted (base64-encoded).
Set encryption via config or environment variable.
Offline Queuing
When offlineQueueEnabled is true, transient errors (connection resets, timeouts, 429 rate limits, 5xx server errors) are detected automatically. Failed operations are queued with retry tracking:
- Each pending change tracks
attempts,lastError, andnextRetryAt - Operations are retried on the next sync cycle
- No data is lost during temporary outages
SyncManager API
import { initSync, getSyncStatus, disconnectSync } from '@getnella/mcp';
// Initialize with your preferred tier
await initSync({
tier: 'supabase',
supabaseUrl: process.env.SUPABASE_URL,
supabaseKey: process.env.SUPABASE_KEY,
});
// Check connection status
const status = getSyncStatus();
// { tier: "supabase", isConnected: true, lastSyncAt: Date, pendingChanges: 0 }
// Clean disconnect
await disconnectSync();
Events
Subscribe to sync events:
| Event | Description |
|---|---|
sync:connected | Connected to remote |
sync:disconnected | Disconnected from remote |
sync:upload | Chunk uploaded |
sync:download | Chunk downloaded |
sync:conflict | Conflict detected |
sync:resolved | Conflict resolved |
sync:error | Sync error (transient or permanent) |