Descanto Docs
Concepts

Forking

Copy a hibernated desktop into N independent desktops.

POST /v1/desktops/{id}/fork creates count new, independent desktops from a single Hibernated source desktop's memory snapshot. It's a copy-on-write clone, not a re-provision from scratch -- each fork starts from exactly the guest state the source had when it last hibernated.

Not a stub anymore

Earlier versions of this API returned 501 Not Implemented for this route. It's a real, working feature now.

Preconditions

The source desktop must be hibernated -- forking an awake desktop (or one in any other state) is a 409 Conflict. If you just finished working on a desktop and want to fork it, hibernate it first:

curl -sS -X POST "$BASE/desktops/$DESKTOP_ID/hibernate?wait=true" -H "$AUTH"
curl -sS -X POST "$BASE/desktops/$DESKTOP_ID/fork?wait=true" \
  -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"count": 3, "acknowledge_shared_state": true}'

acknowledge_shared_state is mandatory

{ "count": 3, "acknowledge_shared_state": true }

Because a fork is a memory-snapshot copy, every resulting desktop starts with the same in-guest state as the source -- including any credentials, session tokens, or SSH agent state that happened to be live in memory at hibernate time. The API can't tell a "pristine" generation (safe to duplicate) from one holding live secrets, so it refuses to guess: acknowledge_shared_state must be explicitly true, or the request is rejected 400. An omitted field is not treated as an implicit true -- it parses as false and is rejected just the same as sending false outright.

If your source desktop might hold anything you wouldn't want duplicated across N new desktops, rotate/revoke it before forking, or avoid putting it there in the first place.

Count

count must be in 1..=20 per request -- 400 outside that range. Ask for exactly as many forks as you need; there's no bulk/unlimited mode.

Ephemeral forks

{ "count": 5, "acknowledge_shared_state": true, "ephemeral": true }

Pass "ephemeral": true to make the resulting forks throwaway: each gets a forced idle_timeout_secs of 900 (15 minutes), regardless of what the source desktop's own idle_timeout_secs was, and -- per TTL and auto-hibernate's ephemeral note -- an ephemeral desktop auto-destroys (not just hibernates) once it hits that idle timeout. This is the fit for fan-out workloads: spin up N disposable copies for a batch of independent tasks, let the ones you don't explicitly destroy clean themselves up.

Without ephemeral: true (the default, false), forks inherit the source's idle_timeout_secs verbatim and behave like any other desktop -- they auto-hibernate at that timeout like normal, they don't self-destroy.

Forks come back Hibernated

A successful fork does not wake the new desktops. They're created directly in the hibernated state -- wake each one on demand (per the normal wake flow) when you're ready to use it. This keeps a large fan-out (count: 20) cheap until you actually need the compute.

Result shape

Like wake/hibernate/destroy, fork returns an operation handle. On success, the settled operation's result carries the new desktop ids:

{
  "id": "...",
  "desktop_id": "d_source...",
  "kind": "fork",
  "state": "succeeded",
  "result": { "desktop_ids": ["d_1...", "d_2...", "d_3..."] },
  "error": null
}

See API reference: Desktops -- Fork a desktop for every parameter and status code.

On this page