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

# Persist state across runs by name

> Give a sandbox an identity you can find again tomorrow.

The default create/stop/gone lifecycle works for **one-shot runs**, but a lot of real workloads want **the same environment back later** — a dev environment, a long-lived agent session, anything worth not rebuilding from scratch every time.

## The pattern

<CodeGroup>
  ```ts persist.ts theme={null}
  import { Sandbox } from "sandkiln";

  // First run: creates a fresh sandbox named "agent-session-42".
  // Every later run: resumes it if it was stopped, or returns it as-is if still live.
  const { sandbox, created } = await Sandbox.getOrCreate({ name: "agent-session-42" });

  if (created) {
    // set up whatever this environment needs once
  }

  await sandbox.runCommand("your-agent-loop", []);
  await sandbox.stop(); // preserved by default — nothing to do here
  ```

  ```python persist.py theme={null}
  from sandkiln import Sandbox

  # First run: creates a fresh sandbox named "agent-session-42".
  # Every later run: resumes it if it was stopped, or returns it as-is if still live.
  sandbox, created = Sandbox.get_or_create(name="agent-session-42")

  if created:
      pass  # set up whatever this environment needs once

  sandbox.run_command("your-agent-loop", [])
  sandbox.stop()  # preserved by default — nothing to do here
  ```

  ```bash CLI theme={null}
  kiln sandbox get-or-create --name agent-session-42
  # prints the sandbox id and whether it was freshly created

  kiln sandbox exec agent-session-42 your-agent-loop
  # preserved by default -- nothing to do here
  ```
</CodeGroup>

Next time this runs — tomorrow, next week — the exact same `getOrCreate({ name: "agent-session-42" })` call resumes the same filesystem state, **no explicit snapshot id to track or pass around yourself**.

## How it works underneath

`getOrCreate` resolves to one of three outcomes, **race-safe** under a per-name lock so two concurrent callers for a brand-new name can't both create a sandbox:

1. A **live** sandbox with this name → returned as-is.
2. A **stopped (snapshotted)** one → resumed.
3. **Neither** → created fresh, given this name.

See [Named sandboxes & persistent stop](/concepts/named-sandboxes) for the full mechanics, and [Snapshots, resume, and fork](/concepts/snapshots) for what "resumed" actually does to the sandbox's state.

## If you need it gone for good

`getOrCreate` **never deletes anything** — call `sandbox.stop({ keep: false })` explicitly (or `kiln sandbox rm --destroy`) when you're genuinely done with that identity and don't want the snapshot left behind.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.