LaufwerkLaufwerk
API reference

Workspace

Workspace creation, execution binding, copy/direct modes, access, write-back results and limitations.

A workspace is the file tree used by a run. It has no agent conversation and no exec method. Attach it to a session to run agent turns or shell commands. Import Workspace and WorkspaceError from @laufwerk/sdk.

Workspace.open(options)

PropertyTypeRequiredDefault / behavior
sourcestringYesDirectory to work on; relative paths resolve from the consumer project root
executionExecutionTargetNoOmission selects legacy Microsandbox; pass a local/Docker execution object explicitly
mode"copy" | "direct"No"copy"; "direct" requires local execution

Returns an Effect of WorkspaceReference, failing with WorkspaceError:

PropertyTypeMeaning
idstringRuntime-generated workspace identity; treat as opaque
pathstringWorking path inside the selected execution environment

For Docker/Microsandbox, path is /workspace. For local execution it is the actual host working path. Do not construct a reference by hand or reuse another run's reference: the runtime checks the stored run/workspace binding.

The current implementation has one workspace per run. Opening again is the same durable operation; it is not a way to allocate another workspace or change its source. Use separate runs for independent workspace copies.

Copy mode

The runtime copies the source into managed storage and records a baseline fingerprint. Changes remain there until write-back. Local and Docker copying skip node_modules directories; install needed dependencies in the execution environment. These modes reject sources whose .git is a file, such as an existing Git worktree. Use a standalone checkout or local direct mode.

Source must be nonempty and resolve to a directory inside the consumer project, including after resolving symlinks; absolute paths inside that root are accepted. Managed copy storage cannot sit inside the copied source. If the source changes while it is copied, creation fails rather than silently accepting an inconsistent baseline.

Direct mode

The workspace points at the source itself. Changes happen immediately, and Workspace.writeBack is unavailable. Separate runs pointing at the same direct source still share physical files; their distinct workspace IDs do not provide cross-run filesystem isolation or a common lock.

Workspace.writeBack({ workspace })

PropertyTypeRequiredMeaning
workspaceWorkspaceReferenceYesThis run's ready, copied workspace

Returns an Effect of WorkspaceWriteBackResult, failing with WorkspaceError.

Result propertyTypeMeaning
sourcestringManaged workspace tree being copied back
destinationstringOriginal source directory
changedEntriesnumberNumber of changed filesystem entries applied
executionExecutionTarget, optional in declared typeCurrently not populated by the runtime result
mode"copy" | "direct", optional in declared typeCurrently not populated by the runtime result

The last two properties exist in the published TypeScript interface but are not returned by the current runtime. Do not use them to determine how a workspace ran.

Write-back compares the current destination with the original baseline and refuses conflicts. It is not a Git merge, commit, push, or atomic filesystem transaction. It is one named durable operation per run, not a repeated sync API. The root .git directory is excluded from write-back: commits made inside the working copy do not become commits in the original repository. Local/Docker write-back also excludes node_modules, just as their initial copy does. Close writing sessions first. An interrupted write-back can need inspection and recovery before the run continues.

Access belongs to the session

WorkspaceAccess = "read-only" | "read-write" is supplied to Session.open/run, not Workspace.open. Several sessions can therefore access the same workspace with different permissions. Readers may overlap; a writer's turn or command excludes all other managed operations until that operation releases its lease. Local execution rejects read-only access because it cannot enforce it.

Example: copy, edit, approve, write back

workspace-example.ts
import { Effect } from "effect";
import { Human, Session, Workspace } from "@laufwerk/sdk";
import { createLocalExecution } from "@laufwerk/execution";
import { createCodex } from "@laufwerk/sdk/harness/codex";

const execution = createLocalExecution({ credentials: "codex-subscription" });
const agent = execution.agent({ harness: createCodex() });

export const updateDocs = () => Effect.gen(function* () {
  const workspace = yield* Workspace.open({ source: ".", execution, mode: "copy" });
  yield* Session.run({
    key: "edit-docs", agent, workspace, access: "read-write",
    prompt: "Correct spelling mistakes in README.md and describe each change.",
  });
  const approved = yield* Human.confirm({
    key: "write-back", title: "Apply the reviewed documentation changes?",
    description: "Inspect the workspace changes before approving.",
  });
  if (!approved) return { applied: false as const };
  const receipt = yield* Workspace.writeBack({ workspace });
  return { applied: true as const, receipt };
});

The human decision is a workflow choice in this example, not an implicit requirement of writeBack. Add deterministic verification appropriate to the edited project.

On this page