---
title: "Thread workspace lifecycle"
description: "Run coding tasks in isolated cloud workspaces that persist across follow-up runs."
canonical_url: "https://hoplite.sh/docs/sandboxes"
markdown_url: "https://hoplite.sh/docs/sandboxes.md"
---

# Thread workspace lifecycle
URL: /docs/sandboxes
LLM index: /llms.txt
Description: Run coding tasks in isolated cloud workspaces that persist across follow-up runs.
Related: /docs/sandboxes/scripts, /docs/sandboxes/previews, /docs/sandboxes/environment-variables, /docs/sandboxes/resources

# Thread workspace lifecycle

Give each cloud [thread](/docs/threads) its own development environment. Hoplite clones the repository, injects [environment variables](/docs/sandboxes/environment-variables), and applies your [setup script](/docs/sandboxes/scripts) in an isolated sandbox runtime. The agent can install dependencies, run tests, start your dev server, and drive a browser against it.

This **thread workspace** holds the task's files and processes across follow-up runs. The [team workspace](/docs/workspace) owns membership, billing, and projects.

## Execution boundary

The workspace contains the checked-out repository, dependencies, project environment variables, and runtime tools. Repository CLI authentication can also place a short-lived repository-scoped GitHub credential in private configuration there. See [Security](/docs/workspace/security#repository-credentials) for credential placement and access controls.

Separate cloud threads have separate workspaces. Follow-up runs within one thread use the same workspace identity. A workspace is not recreated for every message.

## Resume and recover work

| Situation | What to do | What carries over |
| --- | --- | --- |
| Continue a thread | Send a follow-up in that thread | Its existing worktree and history |
| Return to an archived thread | Open **Archived** in the thread list, unarchive the thread, then continue | Retained files; previews and other processes may need restarting |
| Runtime fails | Inspect the recovery result before continuing; Hoplite restores a retained snapshot when available | Files in that snapshot; newer unpushed changes may be lost |
| Restart the runtime | Request a restart through the agent's workspace controls, then restart any preview | Persisted workspace files; running processes are interrupted |

[Manage threads](/docs/threads/manage#thread-list-groups) explains where to find archived work. Runtime archive and thread archive are separate: an idle runtime can stop while its thread remains in your active list.

## Provider persistence

The thread keeps its workspace identity when the underlying runtime is replaced. Depending on the provider, archiving may suspend the runtime or save a filesystem artifact before terminating it, and the next thread operation resumes or restores it behind the same thread. Modal snapshot-replace workspaces (the default for new workspaces) archive after the organization's idle policy and before the provider's maximum runtime, then transparently restore the worktree for the next thread operation. Native suspension remains an alternate provider behavior.

Modal keeps a baseline recovery snapshot and refreshes missing or stale snapshots after setup settles, including during active runs. Captures still defer while setup or an exclusive workspace operation is in progress. If Hoplite confirms that the runtime died or the worktree became invalid, it restores the latest retained snapshot automatically rather than requiring a destructive reset. Work done since the last successful capture may not be in that snapshot.

<Callout type="warning" title="Recovery can lose recent changes">
A recovery returns the workspace to its last snapshot, so unpushed changes made after that point can be lost. Normal archive and restore remains the durable path for later thread operations.
</Callout>

For a Daytona compatibility workspace, the provider may confirm during archive
that the runtime is already gone. Hoplite then retires the stale resource as
archived and records that no fresh persistence artifact could be captured.
Git-pushed work is unaffected, but unpushed work that was not present in an
earlier artifact may be unrecoverable.

A restart interrupts running processes. Use the agent's workspace controls to request it and inspect the result before starting previews again.

## Docker Compose workspaces

The autoscaling standard runtime remains the default. You can explicitly select **Docker Compose** under **Settings → Project → Sandbox**, and that setting always wins. When no runtime profile is selected, Hoplite inspects the repository at the exact revision being provisioned and selects an isolated VM runtime with a private Docker daemon when it finds decisive evidence:

- setup, run, or archive commands that run local Docker, Docker Compose, Supabase, or LocalStack;
- a root `compose.yaml` or `docker-compose.yml` that defines services;
- a Supabase CLI project (`supabase/config.toml`, at the root or nested, such as `web/supabase/config.toml`);
- Testcontainers dependencies in `package.json`, `pom.xml`, `build.gradle(.kts)`, `go.mod`, `requirements*.txt`, or `pyproject.toml`;
- Laravel Sail (`laravel/sail` in `composer.json`), a `.devcontainer/devcontainer.json` with `dockerComposeFile`, or LocalStack configuration (`.lstk/config.toml`, the `localstack` Python package);
- `package.json` scripts or Makefile recipes that run local containers (`docker compose`, `docker run`). Image builds alone don't count, because they're usually a publish step.

Repositories whose commands target a remote Docker host stay on the standard runtime, and so does everything else. See [Using Supabase with Hoplite](/docs/sandboxes/supabase) for the Supabase workflow.

If setup or managed Preview recovery later exposes a requirement that the bounded initial inspection missed, Hoplite can replace the runtime behind the same thread. It preserves the repository worktree, including uncommitted and ignored files, but machine-global state and running processes do not carry across. For a task-specific Docker rehearsal, the agent can also point the reprovision tool at an existing repository-local shell script for bounded inspection, rather than relying only on the project's lifecycle commands. That evidence selects the runtime; it does not bypass Docker policy. Setup completes on the replacement before agents or managed Previews continue. The daemon is not exposed directly to agents or project commands, and Hoplite continues to provide application access through its authenticated preview.

Commands in a Docker Compose workspace run as an unprivileged user without `sudo`. Docker requests go through a policy proxy, so the same rules apply to Compose files, `docker` commands, and containers that mount the Docker socket:

- Privileged containers, host network, PID, or IPC namespaces, devices, added capabilities, security profile overrides, and non-bridge networks are rejected. The privilege-reducing `security_opt: ["no-new-privileges:true"]` is allowed (as are the bare and `=true` forms). Supabase's vector log collector needs `label:disable`, which remains blocked, so run `supabase start -x vector`.
- Bind mounts work for paths inside the repository checkout, including single files such as `./init.sql`, as long as the path contains no symlinks. Other host paths are rejected; named volumes are allowed. After the containers using a bind stop, files they wrote as root are handed back to the workspace user so the agent can edit or delete them.
- Published ports are bound to loopback, so `-p 8080:80` and Compose's `"5432:5432"` become `127.0.0.1` bindings. Other explicit host IPs are rejected; share the app through the Preview instead.
- `docker build`, `docker buildx` with the default driver, and Compose builds use BuildKit. The buildx `docker-container` driver needs a privileged container, so it stays rejected.
- Containers share half of the VM's memory and process capacity, with up to 64 containers. Containers reach workspace services through `host.docker.internal` when those services listen on `0.0.0.0`.

### Kubernetes-in-Docker and elevated setup commands

Kind clusters cannot run in the Docker Compose runtime. Kind node containers require privileged mode, unconfined security profiles, and host mounts that the sandbox rejects. Bridge options for NAT masquerading and a validated MTU are supported. Other custom bridge options may fail first at network creation; removing forbidden options does not make kind's nodes compatible. Reprovisioning to Docker Compose or resizing the sandbox does not grant elevated privileges.

Setup scripts also cannot use `sudo` in this runtime. Install tools in repository-local or user-writable directories rather than attempting system-wide installation. Ordinary unprivileged Compose services remain supported.

Workspace commands write files readable by other users, so services that run as a different uid, such as Postgres reading a mounted `init.sql`, can read them.

## In this section

- **[Setup and run scripts](/docs/sandboxes/scripts)** — `.hoplite/settings.json`: setup, run, and archive scripts, ports, and how overrides resolve
- **[Environment variables and secrets](/docs/sandboxes/environment-variables)** — encrypted per-project secrets, injected into every command
- **[Resources and scaling](/docs/sandboxes/resources)** — CPU, memory, and disk, and how the agent scales them
- **[Preview your app](/docs/sandboxes/previews)** — live preview URLs, plus the in-thread Preview and Terminal panels

## Sitemap

Sitemap discovery is not enabled for this deployment.
