Reuse is meet-or-exceed, not equality
Callingcreate() for a name that already exists returns the existing sandbox when its shape
still serves the request, starting it first if it had stopped.
The rule is meet-or-exceed, and the distinction is load-bearing. Under equality, a build
asking for 2 GiB and a small command asking for 256 MiB never share a sandbox, so each one
replaces the other’s and destroys whatever it had installed. That turns every dependency install
cold. A bigger sandbox runs a smaller command perfectly well; the reverse is not true, so a
raised budget still takes effect.
Ceilings run the other way
Capacities meet-or-exceed. Ceilings meet-or-undercut. A sandbox entitled to live for an hour is not handed to a caller who just asked for a minute, so it is rebuilt. The reverse is fine: one that stops sooner than asked is harmless, because the nextcreate() starts it again.
Forcing a fresh one
When the workspace itself is suspect,replace skips reuse entirely:
replace is an action, not a property. It is never recorded on the sandbox and never
influences whether a later create() reuses it — otherwise every subsequent call would keep
replacing. You should rarely need it: a sandbox whose shape no longer serves is already rebuilt
without it.
Finding what exists
list() is scoped by label to the sandboxes this runtime created, so a sweep can never touch a
container it does not own. Set prefix on the constructor to separate one fleet from another on
a shared host:
Removing
stop() is the reversible one: the next create() starts the same container again, with
everything the last command installed still in place. remove() is not reversible — it deletes
the workspace directory. Removing something that is already gone is not an error; remove()
returns whether there was anything there.