Oblien Docs

Snapshot Archive

Archive entire Git repositories for long-term storage and restoration.

What is Snapshot Archive?

While Snapshots create temporary checkpoints, Snapshot Archives provide:

  • Long-term storage of complete repository states
  • Full repository backup with all history
  • Cross-session restoration - restore archives in new sandboxes
  • Permanent storage that persists beyond sandbox lifecycle

Create Archive

Archive the current Git repository.

// Using SDK
const archive = await sandbox.snapshots.archive({
  id: 'my-project-v1',
  options: {
    includeNodeModules: false,
    compress: true
  }
});

console.log('Archive ID:', archive.id);
POST /snapshots/archive HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "id": "my-project-v1",
  "options": {
    "includeNodeModules": false,
    "compress": true
  }
}

Response:

{
  "success": true,
  "id": "my-project-v1",
  "newRepoCreated": true,
  "message": "Git repository archived successfully with ID: my-project-v1 and new repository initialized"
}

Parameters:

ParameterTypeRequiredDescription
idstringYesUnique archive identifier
options.includeNodeModulesbooleanNoInclude node_modules (default: false)
options.compressbooleanNoCompress archive (default: true)

ℹ️ Info: After archiving, a new empty Git repository is automatically initialized in your sandbox.


Restore Archive

Restore a previously archived repository.

// Using SDK
await sandbox.snapshots.restoreArchive({
  id: 'my-project-v1',
  override: false
});
POST /snapshots/restore-archive HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "id": "my-project-v1",
  "override": false
}

Response:

{
  "success": true,
  "id": "my-project-v1",
  "overridden": false,
  "message": "Repository restored successfully from archive: my-project-v1"
}

Parameters:

ParameterTypeRequiredDescription
idstringYesArchive ID to restore
overridebooleanNoOverride existing repository (default: false)

⚠️ Warning: Setting override: true will replace the current repository. Create a snapshot first if you want to keep current state.


List Archives

Get all available archives.

// Using SDK
const archives = await sandbox.snapshots.listArchives();

archives.archives.forEach(archive => {
  console.log(`${archive.id} - ${archive.size} - ${archive.created}`);
});
GET /snapshots/archives HTTP/1.1
Authorization: Bearer YOUR_TOKEN

Response:

{
  "success": true,
  "archives": [
    {
      "id": "my-project-v1",
      "size": 15728640,
      "created": "2025-10-16T10:00:00Z",
      "compressed": true,
      "files": 142
    },
    {
      "id": "backup-before-deploy",
      "size": 8388608,
      "created": "2025-10-15T18:30:00Z",
      "compressed": true,
      "files": 98
    }
  ],
  "count": 2
}

Get Archive Info

Get detailed information about an archive.

// Using SDK
const info = await sandbox.snapshots.getArchiveInfo({
  id: 'my-project-v1'
});
GET /snapshots/archive/my-project-v1 HTTP/1.1
Authorization: Bearer YOUR_TOKEN

Response:

{
  "success": true,
  "archive": {
    "id": "my-project-v1",
    "size": 15728640,
    "sizeFormatted": "15.0 MB",
    "created": "2025-10-16T10:00:00Z",
    "compressed": true,
    "files": 142,
    "branches": ["main", "develop"],
    "commits": 87,
    "lastCommit": "a1b2c3d4"
  }
}

Delete Archive

Permanently delete an archive.

// Using SDK
await sandbox.snapshots.deleteArchive({
  id: 'old-archive'
});
DELETE /snapshots/archive/old-archive HTTP/1.1
Authorization: Bearer YOUR_TOKEN

Response:

{
  "success": true,
  "message": "Archive old-archive deleted successfully",
  "deletedArchiveId": "old-archive"
}

Cleanup Archives

Clean up multiple archives with filters.

// Using SDK
const cleanup = await sandbox.snapshots.cleanupArchives({
  olderThan: 30, // days
  keepLatest: 5,
  sizeLimit: 1073741824 // 1 GB total
});

console.log(`Deleted ${cleanup.deletedCount} archives`);
POST /snapshots/cleanup-archives HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "olderThan": 30,
  "keepLatest": 5,
  "sizeLimit": 1073741824
}

Response:

{
  "success": true,
  "message": "Successfully cleaned up 8 archives",
  "deletedCount": 8,
  "deletedArchives": ["archive-1", "archive-2", "..."],
  "totalArchivesBefore": 13,
  "totalArchivesAfter": 5,
  "errors": []
}

Parameters:

ParameterTypeDescription
olderThannumberDelete archives older than X days
keepLatestnumberKeep N most recent archives
sizeLimitnumberTotal size limit in bytes

Common Workflows

Project Versioning

// Archive each major version
await sandbox.snapshots.archive({
  id: 'project-v1.0.0'
});

// Work on v1.1.0
// ...make changes...

await sandbox.snapshots.archive({
  id: 'project-v1.1.0'
});

// Later, restore any version
await sandbox.snapshots.restoreArchive({
  id: 'project-v1.0.0'
});

Backup Before Major Changes

// 1. Create archive backup
await sandbox.snapshots.archive({
  id: 'backup-before-migration'
});

// 2. Perform migration
await sandbox.terminal.execute({
  command: 'npm run db:migrate'
});

// 3. If migration fails, restore
try {
  await verifyMigration();
} catch (error) {
  console.log('Migration failed, restoring backup');
  await sandbox.snapshots.restoreArchive({
    id: 'backup-before-migration',
    override: true
  });
}

Multiple Environment States

// Save different configurations
await setupDevelopment();
await sandbox.snapshots.archive({ id: 'env-development' });

await setupStaging();
await sandbox.snapshots.archive({ id: 'env-staging' });

await setupProduction();
await sandbox.snapshots.archive({ id: 'env-production' });

// Switch between environments
await sandbox.snapshots.restoreArchive({ 
  id: 'env-development',
  override: true
});

Archive Naming Conventions

Use clear, descriptive archive IDs:

// ✅ Good archive IDs
'project-v1.0.0'
'backup-before-deploy-2025-10-16'
'stable-before-refactor'
'env-production'

// ❌ Bad archive IDs
'archive1'
'backup'
'test'

Storage Management

Monitor Archive Storage

const archives = await sandbox.snapshots.listArchives();

const totalSize = archives.archives.reduce((sum, a) => sum + a.size, 0);
console.log(`Total archive storage: ${(totalSize / 1024 / 1024).toFixed(2)} MB`);

if (totalSize > 500 * 1024 * 1024) { // 500 MB
  console.log('Warning: High archive storage usage');
}

Automatic Cleanup

// Cleanup policy: Keep last 10 archives, max 30 days old
await sandbox.snapshots.cleanupArchives({
  olderThan: 30,
  keepLatest: 10
});

Best Practices

1. Archive Before Destructive Operations

// Before deleting files
await sandbox.snapshots.archive({ id: 'before-cleanup' });
await sandbox.files.delete({ filePath: '/opt/app/old-folder' });

2. Use Timestamps in IDs

const timestamp = new Date().toISOString().split('T')[0];
await sandbox.snapshots.archive({
  id: `backup-${timestamp}`
});

3. Exclude Large Directories

// Don't archive node_modules
await sandbox.snapshots.archive({
  id: 'clean-archive',
  options: {
    includeNodeModules: false
  }
});

4. Regular Cleanup

// Weekly cleanup job
await sandbox.snapshots.cleanupArchives({
  olderThan: 30,
  keepLatest: 20
});

Error Handling

try {
  await sandbox.snapshots.restoreArchive({ id: 'nonexistent' });
} catch (error) {
  if (error.status === 404) {
    console.log('Archive not found');
  } else if (error.message.includes('override')) {
    console.log('Repository exists - use override: true');
  }
}

Next Steps