javascript debugging features tutorial

Memory Snapshot Feature (JavaScript)

Learn how to snapshot and restore AI memory states for debugging, testing, and rollback scenarios. A practical guide with JavaScript examples.

CodeMem Team

The Problem: Memory Drift

You've been building memories with your AI assistant for weeks. Your project conventions, coding preferences, architectural decisions—all carefully stored. Then something goes wrong. Maybe a corrupted memory entry, conflicting preferences, or you just want to test a new approach without losing your current setup.

This is where Memory Snapshots come in. Think of them as git commits for your AI's brain—a way to save, restore, and debug your agent's memory state.

What Are Memory Snapshots?

A memory snapshot captures the complete state of your CodeMem memories at a specific point in time. It includes:

  • All stored memories and their content
  • Tags and metadata
  • Timestamps and version information
  • Project associations

Snapshots are immutable—once created, they're a perfect freeze-frame of your memory state that you can always return to.

Creating a Snapshot

Using the CodeMem JavaScript SDK, creating a snapshot is straightforward:

import { CodeMem } from '@codemem/sdk';

const mem = new CodeMem({ apiKey: process.env.CODEMEM_API_KEY });

// Create a snapshot with a descriptive name
const snapshot = await mem.snapshot.create({
  name: 'pre-refactor-v2',
  description: 'Before major architecture changes',
  project: 'my-app'  // Optional: scope to specific project
});

console.log(`Snapshot created: ${snapshot.id}`);
// Snapshot created: snap_a1b2c3d4

Pro tip: Name your snapshots like git branches. pre-migration, stable-v1.2, or experiment-new-patterns make it easy to find them later.

Restoring from a Snapshot

When you need to roll back—whether due to an issue or just wanting to try something different—restoring is equally simple:

// List available snapshots
const snapshots = await mem.snapshot.list();
snapshots.forEach(s => {
  console.log(`${s.name} - ${s.createdAt} (${s.memoryCount} memories)`);
});

// Restore a specific snapshot
await mem.snapshot.restore('snap_a1b2c3d4');

// Or restore by name
await mem.snapshot.restore({ name: 'pre-refactor-v2' });

Important: Restoring creates a new snapshot of your current state automatically, so you never lose data. It's non-destructive by default.

Debugging with Snapshots

Snapshots aren't just for backup—they're a powerful debugging tool. Here's how to diagnose memory issues:

1. Compare Snapshots

Find out exactly what changed between two points in time:

const diff = await mem.snapshot.diff({
  from: 'snap_old123',
  to: 'snap_new456'
});

console.log('Added memories:', diff.added.length);
console.log('Removed memories:', diff.removed.length);
console.log('Modified memories:', diff.modified.length);

// Inspect specific changes
diff.modified.forEach(change => {
  console.log(`Memory ${change.id}:`);
  console.log(`  Before: ${change.before.content}`);
  console.log(`  After: ${change.after.content}`);
});

2. Inspect Snapshot Contents

Dive into a snapshot without restoring it:

const contents = await mem.snapshot.inspect('snap_a1b2c3d4');

// Search within the snapshot
const matches = contents.memories.filter(m => 
  m.tags.includes('architecture')
);

console.log('Architecture decisions in snapshot:');
matches.forEach(m => console.log(`- ${m.content}`));

3. Selective Restore

Sometimes you only want to restore specific memories, not the entire state:

// Restore only memories with specific tags
await mem.snapshot.restore('snap_a1b2c3d4', {
  filter: { tags: ['testing', 'config'] }
});

// Or restore everything except certain memories
await mem.snapshot.restore('snap_a1b2c3d4', {
  exclude: { tags: ['deprecated'] }
});

Real-World Debugging Scenario

Let's walk through a common debugging workflow. Your AI assistant suddenly starts generating code that doesn't match your conventions:

// Step 1: Check recent memory activity
const recentMemories = await mem.list({ 
  limit: 20, 
  orderBy: 'updatedAt' 
});

// Step 2: Find suspicious entries
const suspect = recentMemories.find(m => 
  m.content.includes('use var instead')  // Aha!
);

// Step 3: Check when this was added
console.log(`Added: ${suspect.createdAt}`);

// Step 4: Find a snapshot from before this
const snapshots = await mem.snapshot.list({
  before: suspect.createdAt
});

// Step 5: Restore the clean state
await mem.snapshot.restore(snapshots[0].id);

// Step 6: Verify the fix
const verification = await mem.search({ 
  query: 'variable declaration style' 
});
console.log(verification);  // Should show your correct preference

Best Practices

  • Snapshot before major changes: Starting a new feature? Refactoring? Take a snapshot first.
  • Use descriptive names: working-auth-flow beats backup-2
  • Automate regular snapshots: Set up weekly auto-snapshots for long-running projects
  • Clean up old snapshots: Keep the last 10-20 meaningful snapshots, archive or delete the rest
  • Document snapshot purposes: Use the description field—future you will thank present you

Automated Snapshots

For critical projects, set up automated snapshots in your CI/CD:

// In your deployment script
import { CodeMem } from '@codemem/sdk';

async function preDeploySnapshot() {
  const mem = new CodeMem({ apiKey: process.env.CODEMEM_API_KEY });
  
  await mem.snapshot.create({
    name: `pre-deploy-${process.env.VERSION}`,
    description: `Automatic snapshot before deploying v${process.env.VERSION}`,
    tags: ['auto', 'deploy']
  });
}

preDeploySnapshot();

Ready to try it? Memory Snapshots are available on all CodeMem plans. Log into your dashboard to create your first snapshot, or install the SDK with npm install @codemem/sdk to get started programmatically.