Skip to content

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

TierAdapterDescription
localLocalSyncAdapterJSON files on disk. No cloud. Default.
supabaseSupabaseSyncAdapterAuth, API keys, context sync via Supabase Realtime.
gcpGCPSyncAdapterCloud 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

  1. Files are split into fixed-size delta chunks (default: 256 KB)
  2. Each chunk is hashed (SHA-256) — only changed chunks are uploaded
  3. Chunks can be compressed (gzip) and encrypted (AES-256-GCM)
  4. A manifest tracks every file’s chunks, hashes, and modification times
  5. 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:

StrategyBehavior
local-winsKeep local version, discard remote
remote-winsAccept remote version, discard local
newest-winsKeep whichever was modified most recently
manualFlag 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, and nextRetryAt
  • 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:

EventDescription
sync:connectedConnected to remote
sync:disconnectedDisconnected from remote
sync:uploadChunk uploaded
sync:downloadChunk downloaded
sync:conflictConflict detected
sync:resolvedConflict resolved
sync:errorSync error (transient or permanent)