Execution providers
All local, Docker and legacy Microsandbox options, resource units and image preparation helpers.
An execution provider controls where commands and agent processes run. Constructors define configuration; allocation happens when a session uses it.
Local and Docker return values
Import constructors from @laufwerk/execution (also available through /local
and /docker). Both return an object with:
| Property | Type / meaning |
|---|---|
kind | "local" | "docker" |
sandbox | HarnessV1SandboxProvider |
agent(settings) | Constructs a workspace-compatible Harness agent; all settings |
The public ExecutionTarget type from @laufwerk/sdk contains only kind and
sandbox. Keep the constructor's inferred type if you need .agent(); annotating
it as ExecutionTarget hides the factory method from TypeScript.
createLocalExecution(options = {})
| Property | Type | Default / meaning |
|---|---|---|
storageDirectory | Optional string | ~/.laufwerk/execution; session records are stored below local/ |
credentials | Optional "codex-subscription" | "claude-subscription" | Agent bootstrap defaults to Codex subscription credentials |
cwd | Optional string | Fallback workspace for an unbound native session; explicit workspace binding takes precedence |
shell | Optional string | /bin/bash on Unix; discovered Git for Windows Bash on Windows |
Local execution uses the host user's permissions. It rejects read-only workspace
access and injected skills; it is not a security sandbox. Agent bootstrap requires
Node.js 22+ on PATH and suitable subscription credentials. Local resume checks
the recorded host/platform and requires retained session state.
createDockerExecution(options = {})
| Property | Type | Default / meaning |
|---|---|---|
codexBootstrap | Optional "prepared" | "install" | Standard Codex with no explicit image defaults to a managed prepared image; "install" opts into session bootstrap |
imageCacheDirectory | Optional string | ~/.laufwerk/images/codex; shared prepared-image cache, separate from session storage |
resources | Optional DockerResources | No explicit limits added when omitted |
image | Optional string | Custom image; otherwise uses the standard base and, for Codex, its managed prepared image |
storageDirectory | Optional string | ~/.laufwerk/execution; records below docker/ |
credentials | Optional "codex-subscription" | "claude-subscription" | Agent bootstrap defaults to Codex subscription credentials |
Requires a local Docker engine/Desktop in Linux-container mode. Remote Docker
contexts are rejected. Custom images must contain Node, pnpm, Git, Bash and
setsid. Docker supports copy workspaces and enforced read-only mounts; it does
not support direct workspaces. Each session has its own container even when
several sessions mount the same workspace.
Standard Codex agents require a prepared image in alpha.13. init --execution docker prepares it; for existing consumers run laufwerk prepare docker before starting workflows and again after recipe-changing upgrades. Session startup reports a missing/stale image rather than preparing it. Explicit image keeps its own bootstrap behavior unless codexBootstrap: "prepared" is selected. Claude uses its normal bootstrap path.
DockerResources
| Property | Type | Units and validation |
|---|---|---|
cpus | Optional number | CPU quota; finite, from 0.001 through 1000000 |
memoryBytes | Optional number | Positive safe integer bytes, at least 6 MiB |
swapBytes | Optional number | Additional swap beyond RAM; nonnegative safe integer, requires memoryBytes; sum must be a safe integer |
pids | Optional number | Positive safe integer process limit |
swapBytes: 0 requests no additional swap. Omitted limits leave Docker/host
defaults; they do not mean zero resource consumption. Invalid values throw
synchronously during provider construction.
import { createDockerExecution, createLocalExecution } from "@laufwerk/execution";
export const docker = createDockerExecution({
credentials: "codex-subscription",
resources: {
cpus: 2,
memoryBytes: 4 * 1024 ** 3,
swapBytes: 0,
pids: 512,
},
});
export const local = createLocalExecution({ credentials: "codex-subscription" });These limits are example configuration, not a guarantee every task fits within them. See Execution choices for operational setup.
Prepared Codex images
prepareDockerCodex(options) is exported from @laufwerk/execution/docker
(not the package root). It manages the standard Codex image cache and returns
Promise<{ image: string; manifestPath: string; reused: boolean }>.
| Property | Required | Meaning |
|---|---|---|
resources: DockerResources | Yes | Explicit memoryBytes required |
image: string | No | Existing base image; defaults to the standard toolchain image |
cacheDirectory: string | No | Defaults to ~/.laufwerk/images/codex; match execution's imageCacheDirectory |
signal: AbortSignal | No | Cancellation signal |
Preparation uses a cache lock and validates the pinned bootstrap recipe and image
identity before reusing a receipt. The CLI's prepare docker is the setup path
for most consumers. The following lower-level helpers manage explicit receipts.
prepareCodexImage(options): Promise<string> prepares a reusable Docker image
using the pinned adapter bootstrap. Run it during setup, outside a workflow.
| Property | Type | Required | Meaning |
|---|---|---|---|
image | string | Yes | Existing compatible base Docker image |
manifestPath | string | Yes | Where to store the prepared-image receipt |
resources | DockerResources | Yes | Must include explicit memoryBytes; other validation above applies |
signal | AbortSignal | No | Cancellation signal |
loadPreparedCodexImage(manifestPath: string, expectedBaseId?: string, signal?: AbortSignal): Promise<string> validates the
manifest against the adapter recipe, user/group and Docker image identities, then
returns the usable image identity. Stale/mismatched manifests fail; prepare again
when the recipe changes. Neither helper attaches customer workspaces or runtime
credentials to the reusable image.
import { createDockerExecution, loadPreparedCodexImage, prepareCodexImage } from "@laufwerk/execution";
export async function prepare(baseImage: string, manifestPath: string) {
await prepareCodexImage({
image: baseImage, manifestPath,
resources: { memoryBytes: 4 * 1024 ** 3, cpus: 2 },
});
return createDockerExecution({
image: await loadPreparedCodexImage(manifestPath),
credentials: "codex-subscription",
});
}Legacy createMicrosandbox(options)
Import from @laufwerk/sandbox. Returns HarnessV1SandboxProvider, not the
local/Docker object with .agent(). Construct a HarnessAgent directly and
omit execution in Workspace.open for this legacy path.
| Property | Type | Required | Default / meaning |
|---|---|---|---|
credentials | "codex-subscription" | "claude-subscription" | Yes | Subscription credentials to load |
image | string | No | Pinned Node 22 Bookworm slim image |
cpus | number | No | 2 |
memoryMiB | number | No | 3072 MiB; unlike Docker this is not bytes |
workdir | string | No | /root for an unbound environment |
bridgePort | number | No | 43121 inside the environment |
bootstrapCommands | readonly string[] | No | Install certificates/Git and pnpm 10.28.1 |
This integration also exports low-level workspace-volume, credential and provider
helpers plus Microsandbox's upstream exports. They are infrastructure APIs;
workflow authors should use Workspace for managed files and Session for
lifecycle. Do not mix a Microsandbox agent with a local/Docker workspace.