LaufwerkLaufwerk

Docker and local execution

Run your first local workflow, then choose isolation when you need it.

alpha.7 preview — not yet on npm. This guide requires an alpha.7 source checkout. bunx laufwerk@alpha still selects alpha.6. If you only have the published package, use the alpha.6 tutorial. Native Mac Codex login and a real local workflow have passed; publication is still pending.

Choose where the work happens

LocalDocker
Agent commandsNative processes with your permissionsLinux container on your machine
Good first useNative tools, platform-specific automationCoding, builds and tests
InstallBun ≥1.4.2, Node ≥22, Git, Codex or Claude CodeBun ≥1.4.2, Git, Docker engine/Desktop, provider login
Mac / WindowsUses your OS and installed toolsUses Linux tools inside Docker Desktop
File protectionA working copy is convenient, but not a security boundaryWorkspace bind mounts; reviews can mount read-only

Windows local mode also needs Git for Windows, including its native Bash. Docker must be running in Linux-container mode, using a local engine. Remote Docker contexts are unsupported. Neither path installs Microsandbox; it remains available for existing workflows.

Choose local for the easiest native start. Choose Docker when you want the same Linux toolchain across machines. Laufwerk never silently switches from Docker to local execution.

1. Prepare the checkout

The source repository is currently private. Ask the maintainer for access and the codex/cross-platform-execution branch before following this preview. If you have not received a checkout, these commands are not an install path yet; the published alpha.6 tutorial requires Ubuntu.

Sign in to Codex or Claude Code on the same machine where Laufwerk will run. A login on a different computer is not transferred automatically. Keep credentials out of workflow files.

From your alpha.7 checkout:

bun install --frozen-lockfile
bun run check
bun run test:execution

Then create a project beside it. These commands work from macOS/Linux terminals and PowerShell when the checkout directory is named laufwerk:

mkdir ../my-laufwerk-trial
cd ../my-laufwerk-trial
bun ../laufwerk/packages/cli/src/bin.ts init --execution local
bun ../laufwerk/packages/cli/src/bin.ts doctor
bun run --cwd laufwerk check

For Docker, replace --execution local with --execution docker when initializing a new project. Its first run builds a local image; subsequent runs reuse it. Initial downloads need internet access. Generated preview dependencies reference the checkout, so keep it available.

2. Get a checked result

Save this as first-run.ts in my-laufwerk-trial. Using a script keeps the JSON and verification command identical across shell quoting rules:

first-run.ts
import { mkdir } from 'node:fs/promises';

await mkdir('sample', { recursive: true });
await Bun.write('sample/answer.txt', 'before\n');
const input = {
  executionKey: 'first-answer',
  source: 'sample',
  request: 'Write exactly 42 followed by a newline to answer.txt. Change nothing else.',
  verify: `node -e "if(require('fs').readFileSync('answer.txt','utf8')!=='42\\n')process.exit(1)"`,
};
const child = Bun.spawn([
  process.execPath, '../laufwerk/packages/cli/src/bin.ts',
  'run', 'coding', '--input', JSON.stringify(input),
], { stdout: 'inherit', stderr: 'inherit' });
if (await child.exited !== 0) process.exit(1);
if (await Bun.file('sample/answer.txt').text() !== '42\n') {
  throw new Error('The verified result was not written back');
}
console.log('Verified and written back: 42');

Run it once:

bun first-run.ts

Expect a completed, healthy run and Verified and written back: 42. The workflow checks the working copy before applying the change to sample. A failed check does not reach write-back.

An execution key identifies one durable run. Reusing it returns the recorded result; it does not perform new work. To repeat this experiment, change first-answer to a new key before rerunning the script, which resets the source file.

The generated workflow uses Codex. For Claude, edit its credential selection to claude-subscription and replace createCodex(...) with createClaudeCode() imported from @laufwerk/sdk/harness/claude-code. Keep the execution mode and the workflow's checks unchanged.

3. Make it yours

Open laufwerk/workflows/coding/workflow.ts. The important pieces are:

  1. The execution object chooses where commands run and constructs the matching agent.
  2. Workspace.open({ source, execution }) creates a working copy.
  3. The session performs agent turns and deterministic verification.
  4. Explicit write-back applies the result after verification passes.

Change the request and verification command for your own project. Verification runs in the chosen environment: use native commands in local mode and Linux commands in Docker. For an application needing Chromium or other system packages, build a custom Docker image and supply createDockerExecution({ image: 'your-image', credentials: 'codex-subscription' }). It needs Node, pnpm, Git, Bash and setsid; it must support the host UID running as a non-root user.

Managed copies exclude node_modules, so install dependencies inside the working copy. Git metadata is copied for inspection but never written back. A checkout with a .git file, such as a linked Git worktree, is currently rejected in copy mode: use a standalone clone or intentional local direct access.

Continue with workflow concepts, building workflows, and inspecting a stopped run. Examples on those pages still target alpha.6; use this preview's execution object when adapting them.

When you need host access

Local workflows may choose Workspace.open({ source, execution, mode: 'direct' }). Edits then happen immediately and write-back is rejected. A failed workflow cannot undo those edits or external application actions.

Local mode preserves your native HOME and CLI profile. It cannot enforce read-only filesystem access and rejects that request. Use Docker for a read-only workspace review. Injected agent skills are also rejected locally because the pinned harness would write them into your HOME; native installed skills remain available.

Custom HarnessAgent tools execute on the host, even with a Docker agent. Native execution does not automatically add computer-use capabilities. Verify the specific adapter/tool integration and OS screen/input permissions; a headless Linux service does not provide a desktop.

Linux local/Docker execution and native Mac Codex execution have passed, along with credential-free CI on Linux, macOS and Windows. On the tested Mac, successful live checks took roughly 4–7 minutes, mostly package setup. The harness installs dependencies into a session-local package store, so a new session is not necessarily warm. Allow time and disk space for downloads.

Mac Docker Desktop, usable Claude OAuth and a real cross-process Codex conversation resume remain unverified. The Mac resume probe stalled during package download before creating a conversation; in-process resume passed. Windows subscription execution is also unverified. Do not infer those checks from a green CI badge.

After your first checked result, follow Run your first customer pilot to define acceptance, review and recovery for a real use case.

On this page