一键导入
tigris-snapshots-forking
Use when needing point-in-time recovery, version control for object storage, or creating isolated bucket copies for testing/experimentation
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when needing point-in-time recovery, version control for object storage, or creating isolated bucket copies for testing/experimentation
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Back up and restore the OpenClaw state directory (config, workspace, sessions, skills) to a Tigris bucket. Scheduled backups, safe SQLite handling, point-in-time rollback via bucket snapshots, and zero-copy clones via forks. Use when the user wants their assistant's state to survive machine loss, move to a new machine, or roll back to before a bad update.
Use when migrating from AWS S3, Google Cloud Storage, or Azure Blob to Tigris — shadow buckets via `tigris buckets set-migration`, active drain via `tigris buckets migrate`, bulk copy, SDK endpoint swap, zero-downtime migration
Use when working with Tigris file storage - uploading, downloading, deleting, listing files, presigned URLs, client uploads, or setting up Tigris CLI and SDK. Covers Next.js, Remix, Express, Rails, and Laravel. For Python/Django, see the tigris-python-sdk skill.
Use when backing up databases to Tigris, scheduling exports, archiving data, or setting up automated backup pipelines — covers Next.js, Remix, Rails, Django, Laravel, Express
Use when working with Tigris from Python — boto3 setup, Django uploads via django-storages, snapshots, bucket forking, in-place object rename, conditional writes (IfMatch/IfNoneMatch), and the Bundle API for batch ML data fetches. Covers the tigris-boto3-ext extension library (context managers, decorators, helpers) plus framework integration.
Use when choosing between Tigris-native SDKs and AWS S3-compatible SDKs — covers which SDK to use per language, CLI preference, and when AWS SDKs are the only option
| name | tigris-snapshots-forking |
| description | Use when needing point-in-time recovery, version control for object storage, or creating isolated bucket copies for testing/experimentation |
Before doing anything else, install the Tigris CLI if it's not already available:
tigris help || npm install -g @tigrisdata/cli
If you need to install it, tell the user: "I'm installing the Tigris CLI (@tigrisdata/cli) so we can work with Tigris object storage."
Snapshots capture your entire bucket at a point in time. Forking creates instant, isolated copies from snapshots using copy-on-write.
Core principle: Snapshots and forks protect your data from deletion. Even if you delete everything in a fork, the source bucket data remains intact.
Object storage serves as the primary data store for many systems. It needs safety features:
Traditional object versioning only works per-object. To restore a bucket to a point in time, you must check and restore each object individually. Tigris snapshots capture the entire bucket state instantly.
Forking creates isolated bucket copies instantly - even for terabytes of data:
How it works: Tigris uses immutable objects with backwards-ordered timestamps. Forks read from the parent snapshot until new data overwrites. This makes forking essentially free - no data copying required.
| Operation | Function | Key Parameters |
|---|---|---|
| Create snapshot | createBucketSnapshot(options) | name, sourceBucketName |
| List snapshots | listBucketSnapshots(sourceBucketName) | sourceBucketName |
| Create fork | createBucket(name, options) | sourceBucketName, sourceBucketSnapshot |
import { createBucketSnapshot } from "@tigrisdata/storage";
// Snapshot default bucket
const result = await createBucketSnapshot();
if (result.error) {
console.error("Error:", result.error);
} else {
console.log("Snapshot version:", result.data?.snapshotVersion);
// Output: { snapshotVersion: "1751631910169675092" }
}
// Named snapshot for specific bucket
const result = await createBucketSnapshot("my-bucket", {
name: "backup-before-migration",
});
if (result.error) {
console.error("Error:", result.error);
} else {
console.log("Named snapshot:", result.data?.snapshotVersion);
}
Prerequisite: Bucket must have enableSnapshot: true when created.
import { listBucketSnapshots } from "@tigrisdata/storage";
// List snapshots for default bucket
const result = await listBucketSnapshots();
if (result.error) {
console.error("Error:", result.error);
} else {
console.log("Snapshots:", result.data);
// [
// {
// name: "backup-before-migration",
// version: "1751631910169675092",
// creationDate: Date("2025-01-15T08:30:00Z")
// }
// ]
}
// List snapshots for specific bucket
const result = await listBucketSnapshots("my-bucket");
import { createBucket, createBucketSnapshot } from "@tigrisdata/storage";
// First, create a snapshot
const snapshot = await createBucketSnapshot("agent-seed", {
name: "agent-seed-v1",
});
const snapshotVersion = snapshot.data?.snapshotVersion;
// Fork from snapshot
const agentBucketName = `agent-${Date.now()}`;
const forkResult = await createBucket(agentBucketName, {
sourceBucketName: "agent-seed",
sourceBucketSnapshot: snapshotVersion,
});
if (forkResult.error) {
console.error("Error:", forkResult.error);
} else {
console.log("Forked bucket created");
// agent-${timestamp} has all data from agent-seed at snapshot time
// Can modify/delete freely - agent-seed is unaffected
}
Access historical data without forking:
import { get, list } from "@tigrisdata/storage";
// Get object as it was at snapshot
const result = await get("config.json", "string", {
snapshotVersion: "1751631910169675092",
});
// List objects as they were at snapshot
const result = await list({
snapshotVersion: "1751631910169675092",
});
import { remove, get } from "@tigrisdata/storage";
// In forked bucket, delete everything
await remove("hello.txt", { config: { bucket: "agent-fork" } });
// Fork appears empty
const forkResult = await get("hello.txt", "string", {
config: { bucket: "agent-fork" },
});
// forkResult.error === "Not found"
// But source bucket still has data
const sourceResult = await get("hello.txt", "string", {
config: { bucket: "agent-seed" },
});
// sourceResult.data === "Hello, world!"
The fork's deletion only affects the fork. Source data remains accessible in the parent bucket and all snapshots.
// Create snapshot of production data
await createBucketSnapshot("production", {
name: "dev-sandbox-seed",
});
// Fork for each developer
const devBucket = await createBucket(`dev-${developerName}`, {
sourceBucketName: "production",
sourceBucketSnapshot: "...",
});
// Developer can test and modify freely
// Store agent dependencies in seed bucket
await put("model.bin", modelData);
await put("config.json", agentConfig);
// Snapshot the seed
const snapshot = await createBucketSnapshot("agent-seed", {
name: "v1",
});
// Spin up new agent instance with fork
const agentBucket = `agent-${Date.now()}`;
await createBucket(agentBucket, {
sourceBucketName: "agent-seed",
sourceBucketSnapshot: snapshot.data?.snapshotVersion,
});
// Agent has everything and can modify freely
await startAgent(agentBucket);
// Before risky operation
await createBucketSnapshot("production", {
name: "before-migration-v2",
});
// Run migration
// If disaster strikes, fork from snapshot to recover
const rollback = await createBucket("production-restored", {
sourceBucketName: "production",
sourceBucketSnapshot: "...",
});
| Mistake | Fix |
|---|---|
| Snapshotting non-snapshot-enabled bucket | Recreate bucket with enableSnapshot: true |
| Expecting fork to affect source | Forks are isolated - source remains unchanged |
| Not naming snapshots | Names make snapshots discoverable |
| Using wrong storage tier | Snapshot buckets must use STANDARD tier |
A snapshot is a single 64-bit integer representing nanoseconds since Unix epoch. Tigris stores objects with reverse-ordered timestamps, so the most recent version sorts first. When you snapshot, Tigris records the current time. Reading from a snapshot queries for the newest object version before that timestamp.
Forking adds recursive indirection: child bucket objects override the parent, but missing objects recurse through the parent snapshot. This makes forking instant - no data copying, just metadata pointers.