Documentation Index
Fetch the complete documentation index at: https://mintlify.com/superfly/sprites-go/llms.txt
Use this file to discover all available pages before exploring further.
Checkpoints let you freeze the current state of a sprite and restore it at any point. Unlike a full restart, a restore brings the sprite back to exactly the filesystem and process state it was in when the checkpoint was taken — making them useful for reproducible test baselines, safe deployment gates, and reversible experiments.
The Checkpoint struct
Every checkpoint is represented as a Checkpoint value with the following fields:
type Checkpoint struct {
ID string `json:"id"`
CreateTime time.Time `json:"create_time"`
History []string `json:"history,omitempty"`
Comment string `json:"comment,omitempty"`
IsAuto bool `json:"is_auto,omitempty"`
}
| Field | Description |
|---|
ID | Unique identifier for this checkpoint. Pass it to GetCheckpoint or RestoreCheckpoint. |
CreateTime | When the checkpoint was taken. |
History | Ordered list of ancestor checkpoint IDs, oldest first. |
Comment | Optional human-readable label set at creation time. |
IsAuto | true for checkpoints created automatically by the platform. |
Creating a checkpoint
Get a sprite handle
Obtain a Sprite from your client using the sprite’s name.client := sprites.New(os.Getenv("SPRITE_TOKEN"))
sprite := client.Sprite("my-sprite")
Call CreateCheckpoint or CreateCheckpointWithComment
Both methods return a *CheckpointStream that streams progress messages while the snapshot is being taken.
Consume the stream
The checkpoint operation streams StreamMessage values until the snapshot is complete. Call ProcessAll to handle every message and automatically close the stream when done.err = stream.ProcessAll(func(msg *sprites.StreamMessage) error {
switch msg.Type {
case "info":
fmt.Println("info:", msg.Data)
case "error":
return fmt.Errorf("checkpoint error: %s", msg.Error)
}
return nil
})
if err != nil {
log.Fatal(err)
}
Streaming messages
Both CheckpointStream and RestoreStream deliver StreamMessage values:
type StreamMessage struct {
Type string `json:"type"` // "info", "stdout", "stderr", "error"
Data string `json:"data,omitempty"`
Error string `json:"error,omitempty"`
}
Type | Meaning |
|---|
"info" | Progress update from the platform. Read from Data. |
"stdout" | Standard output from an internal process. Read from Data. |
"stderr" | Standard error from an internal process. Read from Data. |
"error" | A fatal error occurred. Read from Error. |
Manual iteration with Next
Use Next when you need to control the loop yourself — for example to stop early:
defer stream.Close()
for {
msg, err := stream.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("[%s] %s\n", msg.Type, msg.Data)
}
Always close the stream when you are done. ProcessAll calls Close automatically; if you use Next directly, use defer stream.Close().
Listing checkpoints
ListCheckpoints
Returns all manually created checkpoints. Pass an empty string for historyFilter to retrieve all of them, or pass a checkpoint ID to retrieve only that checkpoint’s ancestors.
checkpoints, err := sprite.ListCheckpoints(ctx, "")
if err != nil {
log.Fatal(err)
}
for _, cp := range checkpoints {
fmt.Printf("%s %s %s\n", cp.ID, cp.CreateTime.Format(time.RFC3339), cp.Comment)
}
ListCheckpointsWithOptions
Use ListCheckpointsWithOptions when you need finer control:
opts := sprites.ListCheckpointsOptions{
HistoryFilter: "", // empty = all checkpoints
IncludeAuto: true, // also return auto-created checkpoints
}
checkpoints, err := sprite.ListCheckpointsWithOptions(ctx, opts)
if err != nil {
log.Fatal(err)
}
IncludeAuto: true includes checkpoints where IsAuto == true. These are created by the platform during certain operations and are hidden by default.
Getting a specific checkpoint
Retrieve a single checkpoint by its ID to inspect its metadata before deciding whether to restore it:
checkpoint, err := sprite.GetCheckpoint(ctx, "cp_abc123")
if err != nil {
log.Fatal(err)
}
fmt.Printf("ID: %s\n", checkpoint.ID)
fmt.Printf("Created: %s\n", checkpoint.CreateTime.Format(time.RFC3339))
fmt.Printf("Comment: %s\n", checkpoint.Comment)
fmt.Printf("IsAuto: %v\n", checkpoint.IsAuto)
Restoring a checkpoint
RestoreCheckpoint rolls the sprite back to the state captured in the given checkpoint. It returns a *RestoreStream with the same interface as CheckpointStream.
stream, err := sprite.RestoreCheckpoint(ctx, "cp_abc123")
if err != nil {
log.Fatal(err)
}
err = stream.ProcessAll(func(msg *sprites.StreamMessage) error {
if msg.Type == "error" {
return fmt.Errorf("restore failed: %s", msg.Error)
}
fmt.Println(msg.Data)
return nil
})
if err != nil {
log.Fatal(err)
}
Complete workflow example
The following example creates a checkpoint, lists it to confirm it exists, then restores it:
package main
import (
"context"
"fmt"
"log"
"os"
"time"
sprites "github.com/superfly/sprites-go"
)
func main() {
ctx := context.Background()
client := sprites.New(os.Getenv("SPRITE_TOKEN"))
sprite := client.Sprite(os.Getenv("SPRITE_NAME"))
// 1. Create a checkpoint with a label.
stream, err := sprite.CreateCheckpointWithComment(ctx, "pre-migration")
if err != nil {
log.Fatal(err)
}
err = stream.ProcessAll(func(msg *sprites.StreamMessage) error {
fmt.Println("[create]", msg.Type, msg.Data)
return nil
})
if err != nil {
log.Fatal(err)
}
// 2. List checkpoints and find the one we just created.
checkpoints, err := sprite.ListCheckpoints(ctx, "")
if err != nil {
log.Fatal(err)
}
var targetID string
for _, cp := range checkpoints {
if cp.Comment == "pre-migration" {
targetID = cp.ID
fmt.Printf("Found checkpoint %s created at %s\n",
cp.ID, cp.CreateTime.Format(time.RFC3339))
}
}
if targetID == "" {
log.Fatal("checkpoint not found")
}
// 3. Restore the sprite to that checkpoint.
restoreStream, err := sprite.RestoreCheckpoint(ctx, targetID)
if err != nil {
log.Fatal(err)
}
err = restoreStream.ProcessAll(func(msg *sprites.StreamMessage) error {
fmt.Println("[restore]", msg.Type, msg.Data)
return nil
})
if err != nil {
log.Fatal(err)
}
fmt.Println("Restore complete.")
}
Using the client directly
All methods are also available on *Client if you prefer to pass the sprite name explicitly:
// Client-level equivalents
stream, err := client.CreateCheckpoint(ctx, "my-sprite")
stream, err := client.CreateCheckpointWithComment(ctx, "my-sprite", "label")
checkpoints, err := client.ListCheckpoints(ctx, "my-sprite", "")
checkpoints, err := client.ListCheckpointsWithOptions(ctx, "my-sprite", opts)
checkpoint, err := client.GetCheckpoint(ctx, "my-sprite", checkpointID)
stream, err := client.RestoreCheckpoint(ctx, "my-sprite", checkpointID)
Use the Sprite-level methods (sprite.CreateCheckpoint, etc.) in most code — they are shorter and keep the sprite name in one place. Prefer Client-level methods when you are writing utilities that operate across multiple sprites.