> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Devbox Snapshots

> Saved diskstates from existing for devboxes for re-use & branching

export const ExampleRepoLink = props => {
  return <Info><h3><a href={props.link}>Full example on GitHub</a></h3></Info>;
};

<Tip>Start with the [Runloop Quickstart](/docs/tutorials/quickstart) to use the examples below.</Tip>

Snapshots can be used to save the current disk state of a Devbox, and to create
new Devboxes from a previously saved state. Snapshots can be used to:

* Improve build times by snapshotting a populated build cache.
* Roll back to a known good point in time.
* Perform fan-out and attempt multiple approaches to a code change.

Snapshots are assigned a random identifier upon creation and can be queried via the API. Currently only disk snapshots are supported.

{/* TODO: what is the difference between snapshot_disk and snapshot_disk_async */}

<Note>
  When should I use a Blueprint vs. a Snapshot?

  Snapshots and Blueprints both allow you to run devboxes with customizations. **Blueprints** are built programmatically and are cacheable using Docker layers, while **Snapshots** can be created quickly from an existing devbox.

  Examples:

  * **[Blueprint](/docs/devboxes/blueprints)**: You have a coding agent that is performing a task that requires installing a specific tool. Create a Blueprint with set-up steps for the tool.  All Devboxes you launch from that Blueprint will have the environment already set up, and will not incur installation or setup time.
  * **[Snapshot](/docs/devboxes/snapshots)**: You have a coding agent in a devbox considering 3 different ways to complete a task. Create a snapshot of the initial state of the devbox, create 3 parallel devboxes from that snapshot, collate the results, and then choose the best option to continue.
</Note>

<Steps>
  <Step title="Create a devbox to snapshot">
    Create a devbox with state to snapshot.

    <CodeGroup>
      ```python Python theme={null}
      devbox = await runloop.devbox.create()
      devbox.cmd.exec("echo 'Hello, World!' > hello.txt")            
      ```

      ```typescript TypeScript theme={null}
      const devbox = await runloop.devbox.create();
      await devbox.cmd.exec("echo 'Hello, World!' > hello.txt");
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a Snapshot">
    Start a Snapshot and wait for it to be ready.

    <CodeGroup>
      ```python Python theme={null}
      snapshot = await devbox.snapshot_disk()
      print(f"Snapshot operation completed with ID: {snapshot.id}")
      ```

      ```typescript TypeScript theme={null}
      const snapshot = await devbox.snapshotDisk();
      console.log(`Snapshot operation completed with ID: ${snapshot.id}`);
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a new devbox from the completed snapshot">
    Once the snapshot is complete, use the snapshot ID to launch a new devbox:

    <CodeGroup>
      ```python Python theme={null}
      devbox = await snapshot.createDevbox()
      const contents = await devbox.file.read("hello.txt")
      print(f"hello.txt contents: {contents}")
      ```

      ```typescript TypeScript theme={null}
      const devbox = await snapshot.createDevbox();
      const contents = await devbox.file.read("hello.txt");
      console.log(`hello.txt contents: ${contents}`);
      ```
    </CodeGroup>
  </Step>
</Steps>

## Asynchronous Disk Snapshots

When creating a disk snapshot you may want access to the Snapshot ID
while you are waiting for the actual snapshot operation to
complete. The asynchronous version of the snapshot operation allows
this.

<CodeGroup>
  ```python Python theme={null}
  snapshot = await devbox.snapshot_disk_async()
  print(f"Snapshot operation started with ID: {snapshot.id}")

  await snapshot.await_completion()
  print(f"Snapshot operation completed with ID: {snapshot.id}")           
  ```

  ```typescript TypeScript theme={null}
  const snapshot = await devbox.snapshotDiskAsync();
  console.log(`Snapshot operation started with ID: ${snapshot.id}`);

  await snapshot.awaitCompletion();
  console.log(`Snapshot operation completed with ID: ${snapshot.id}`);
  ```
</CodeGroup>

## Deleting Snapshots

By default, snapshots persist indefinitely and continue to incur storage costs. To optimize resource usage and costs, you can delete snapshots that are no longer needed.

### Deleting a Single Snapshot

To delete a specific snapshot simply:

<CodeGroup>
  ```python Python theme={null}
  await snapshot.delete()
  ```

  ```typescript TypeScript theme={null}
  await snapshot.delete();
  ```
</CodeGroup>

### Cleaning Up Old Snapshots for a Devbox

When you create multiple snapshots of the same devbox, you may want to delete older snapshots to reduce storage costs. Here's how to keep only the latest snapshot for a specific devbox:

<CodeGroup>
  ```python Python theme={null}
  # Create a new snapshot
  new_snapshot = await devbox.snapshot_disk(devbox.id)

  # Get all snapshots for this devbox
  snapshot_results = await runloop.snapshot.list(
    devbox_id=devbox.id
  )

  # Delete all older snapshots, keeping only the newest one
  for snapshot in snapshot_results:
      if snapshot.id != new_snapshot.id:
          await snapshot.delete()
          print(f"Deleted old snapshot: {snapshot.id}")


  ```

  ```typescript TypeScript theme={null}
  // Create a new snapshot
  const newSnapshot = await devbox.snapshotDisk(devbox.id);

  // Get all snapshots for this devbox
  const snapshotResults = await runloop.snapshot.list({
    devbox_id: devbox.id
  });
  // Delete all older snapshots, keeping only the newest one
  for (const snapshot of snapshotResults) {
    if (snapshot.id !== newSnapshot.id) {
      await snapshot.delete();
      console.log(`Deleted old snapshot: ${snapshot.id}`);
    }
  }
  ```
</CodeGroup>

<Note>
  Be careful when deleting snapshots, as this action cannot be undone. Ensure you're not deleting snapshots that you may need for rollback or recovery purposes.
</Note>
