On this page

On this page

Gateway

Workspace access

What workspaceAccess exposes to the sandbox, how a role-required sandbox caps it, and how skills are mirrored into the sandbox workspace.

Workspace access

agents.defaults.sandbox.workspaceAccess controls what the sandbox can see:

Value Behavior
none (default) Tools can read and write an isolated sandbox workspace under ~/.openclaw/sandboxes; the agent workspace is not exposed.
ro Mounts the agent workspace read-only at /agent (disables write/edit/apply_patch).
rw Mounts the agent workspace read/write at /workspace.

For a role-required sandbox, OpenClaw caps configured rw workspace access at ro and logs an agent/sandbox warning. The guest keeps a separate sandbox workspace, while the shared agent workspace is available only as a read-only mount. This prevents guests from sharing the writable agent workspace; none and ro remain unchanged. Sessions without a role-required sandbox retain their configured workspace access.

The session Files browser follows this workspace boundary. With local Docker or Podman and workspaceAccess: "none", listings, searches, previews, and downloads use the session's private sandbox workspace, including files created during ordinary noncoding chats. An unavailable private workspace never falls back to the shared agent workspace. Explicit ro access and managed project workspaces retain their existing admitted source access. Viewing a shared session uses that session's workspace; it does not switch to the viewer's own sandbox. Session visibility alone does not let a sandbox-required reader browse an unsandboxed shared host workspace. Ordinary nonsandbox-required read-only readers keep their existing in-root access.

Recognized file references in chat can also use absolute paths under the local sandbox's workspace mount, including a custom container workdir. Previews and downloads resolve them through the sending conversation's admitted workspace and verify that its existing Docker or Podman runtime exposes the same file backing. A nested bind, container-only mount, or unrelated host path does not grant additional access. With ro access, /agent names the admitted agent workspace; the private container workdir is a different source and does not alias that workspace. Managed project references read the live private checkout without pausing the sandbox or publishing a checkpoint. Reads use verified file descriptors and may observe an in-progress write, just like another reader inside the sandbox. If the original runtime or its namespace mapping is unavailable, an absolute alias can fail even when the saved file remains readable through an admitted workspace-relative reference. Reading never creates a sandbox or reconstructs an unavailable historical mapping.

The Changes view requires an admitted project checkout. An unmanaged private sandbox remains available in Files, but Changes returns the existing not_git notice instead of running host Git against private sandbox metadata. Managed project and admitted host checkouts retain their existing diff behavior.

Managed project workspaces

A sandboxed session with a session-owned managed worktree uses a private Git checkout on Docker and Podman. A registered project may be outside the agent's configured workspace when it is selected with worktree: true. This authorizes source preparation, not direct access to that host directory. Arbitrary external cwd values and direct project bindings remain restricted.

On copy-on-write filesystems, managed Docker and Podman workspaces can clone a prepared pnpm dependency tree. The builder and runtime use the same pnpm store path outside the checkout, so a subsequent install can reuse those dependencies instead of replacing them because the store moved. The default store lives in the container's disposable /tmp/openclaw-deps tmpfs; its bytes are private to that container and are not included in the projection snapshot. An explicit PNPM_CONFIG_STORE_DIR environment setting (or the older npm_config_store_dir spelling) or command-line store selection still takes precedence. Changed dependencies still need installation, and package lifecycle scripts still run.

Visible child sessions keep their managed worktree as the sandbox workspace on later turns, including sessions created before an update.

Rewind and branch switching keep that managed workspace and its accepted edits. OpenClaw settles pending sandbox edits and retires the old runtime before changing the conversation history. The next turn reuses the same private checkout under the new conversation incarnation. Conflicting edits remain saved and block the history change until the conflict is resolved.

The private checkout contains the selected source commit, not the host's shared Git configuration, credential helpers, other branches, or ignored files selected by .worktreeinclude. Guest preparation does not run the repository's host setup script. Source-only checkout, snapshot, and restore operations use a command-scoped trusted Git configuration view, so repository, worktree, global, and included filter programs cannot execute on the Gateway—even if configuration changes while preparation is waiting. Private-checkout packing uses that same configuration boundary and does not lazily fetch missing Git objects. If the source is incomplete, fetch its objects through the trusted host workflow and retry preparation. Git still owns the registered worktree, index, HEAD, and snapshot refs; ordinary trusted maintainer checkouts are unchanged. The guest’s Git commands operate on private metadata. Initial non-ignored source paths are admitted before guest execution and retained in the projection binding. Later host-created paths enter an existing projection only after the host stages them in the host Git index (git add); changing an ignore rule alone does not admit host files, including newly provisioned files. Existing admitted source edits and guest-created files continue to reconcile, including ignored reports and attachments. An ignore rule alone does not make an authored file disposable. Result capture excludes new ignored build outputs only under checkout-root dist/ and .cache/openclaw-bun/, using the guest's .gitignore files and the trusted host repository's .git/info/exclude and global excludes. Tracked files and exact previously admitted or accepted paths remain protected when ignore rules change. Save durable reports and screenshots outside disposable build/cache roots; ordinary .artifacts/ outputs remain available to saved message references. Source filenames must be valid UTF-8; rename invalid Git paths before retrying preparation. Publication uses the same admission boundary.

New private checkouts are shallow snapshots. For GitHub.com projects, their credential-free HTTPS origin and the matching HTTPS repository URLs (with and without .git) default to blob:none fetches: history arrives without historical file contents, and checkout or diff fetches missing contents as needed. These defaults are reapplied when creating a checkout from a retained dependency template, including templates created before these defaults existed. Host object stores and credentials remain outside the sandbox; private repository access still requires the existing authorized publication workflow.

The agent Git wrapper also defaults GitHub fork URL fetches to blob:none in these blobless repositories. This covers HTTPS, [email protected]:owner/repo, and ssh://[email protected]/owner/repo addresses through the agent's normal git command on POSIX hosts and Docker/Podman sandboxes. Git records the fetched URL as a promisor so later checkout and diff can retrieve fork-only file contents. Explicit --filter and --no-filter choices are preserved. Outside projections, full repositories and non-GitHub URLs retain Git's normal defaults. Direct invocations of a Git binary outside the wrapper also keep native defaults.

Standalone projections also default single-remote fetches to --depth=64, including implicit origin fetches (git fetch) and explicit blob filters. The projection owner marks this Git metadata when building or reusing the checkout; shared base clones are not marked and do not receive this depth default. This bounds each fetched tip's history instead of downloading all commits and trees. Explicit --depth, --deepen, --shallow-since, --shallow-exclude, --unshallow, and --update-shallow options take precedence. --no-filter changes blob filtering, not the history limit.

Checkout and direct git diff <base> <branch> use complete file contents. History walks remain shallow: git log <base>..<branch> can omit older PR commits or include shared ancestors when the base's ancestry is missing. Fetch the base from origin and deepen the relevant tips explicitly when a complete range or merge base is required. A fixed depth is intentional: --deepen alone can still fetch an old fork's entire ancestry, and --shallow-exclude requires a remote branch or tag, not an arbitrary projection base SHA.

Use github_publish with action: "prepare_pr" for eligible PR continuation and refresh_base for base updates. For separate commit inspection, prefer git fetch --no-tags --depth=1 <url> <commit>...; deepen explicitly if the task needs ancestry, or use --filter=blob:none when history is required. Existing checkouts without blobless defaults and commands outside the wrapper need these explicit flags for fork fetches. An unbounded fetch in a shallow checkout can otherwise download the repository's entire history, including obsolete blobs. Servers must support filtering; Git warns and falls back to an unfiltered fetch when they do not.

A newly created filename containing a literal backslash cannot pass workspace checkpoint validation. Its bytes and the pending checkpoint remain preserved. The same authorized session can continue using its retained sandbox workspace to inspect and explicitly correct that filename with its ordinary permitted tools. This workspace can still contain an older view of canonical files; newer canonical edits are not imported over the pending changes. File reads remain available from the live checkout; command finalization and file saves continue to report the checkpoint failure until correction allows normal reconciliation. Existing conflict checks protect concurrent canonical edits, and subsequent preparation imports those accepted changes. This continuation does not bypass staged conflicts, journal recovery, or the session's current permissions, and OpenClaw does not rename or omit the file.

Host recovery snapshots retain host data under their existing rules, but restoration does not admit that data to the guest. Use the session's managed GitHub publication action to publish accepted changes; host credentials are not copied into the sandbox. The runtime-owned .openclaw/sandbox-skills subtree is excluded from workspace reconciliation and publication, as are the scratch directory and dependency cache described below. Other project content under .openclaw is retained. Its empty mount targets are created by the host workspace owner before container allocation, while the skill mounts remain read-only. This also keeps normal retention cleanup independent of container user-namespace ownership.

Git metadata at the checkout root or in nested repositories (.git path components) stays local to its runtime and is excluded from synchronization and recovery, including previously retained inputs. Similarly named source files such as .gitignore, .gitmodules, and .git-notes still reconcile normally.

At the checkout root, .cache/vitest/, .cache/bun-transpiler/, .cache/openclaw/bun/, .cache/ms-playwright/, .local/share/pnpm/store/, artifacts/task-environment/local/share/pnpm/store/, .openclaw/.pnpm-store/, and .openclaw/tools/ caches stay with the runtime that produced them, along with .artifacts/vitest-workers/ compiler outputs, .artifacts/vitest-worker-cache/ retained compiler outputs, .artifacts/vitest-shard-timings.json scheduling samples, and .artifacts/dist-artifacts.lock/ ownership files. The root .openclaw/tmp/ scratch directory also stays local, including downloaded toolchains and browsers. Scratch remains available to later commands in the same runtime, but is not synchronized or restored onto another runtime. Save durable outputs outside it; other .openclaw/ content and nested project fixtures still reconcile. Synchronization and recovery of older pending results exclude these exact paths, so dependency and test-tool downloads do not count as authored workspace results. Other guest-created files under .cache/, .local/, and .artifacts/ still reconcile, including ignored paths and explicit staged inputs. Only the declared disposable build/cache roots are excluded before hashing and result-size accounting; their local bytes remain available to the sandbox. Source changes cannot remove a runtime-owned lock subtree by replacing its parent directory.

Use .openclaw/tmp/ for disposable output files that workspace file tools need to read or write later. Keep TMPDIR, TMP, and TEMP at their inherited system paths: native tools such as Chromium need short temporary paths for Unix sockets, and a deeply nested checkout can exceed that limit.

pnpm can select .openclaw/.pnpm-store/ when installing beneath a protected .openclaw mount and its home store cannot hard-link into that project. Managed binary installers use .openclaw/tools/ for re-downloadable tools such as Crabbox.

Changed user files remain limited to 64 MiB each. If one exceeds the limit, reduce it or move it outside synchronization before retrying; repeated messages cannot resolve the size violation. For a newly created local sandbox file, openclaw sandbox recover preserves the file outside synchronization so the next turn can settle the remaining edits.

Local managed guest workspaces also exclude disposable .artifacts/build-all-cache/ build snapshots and .artifacts/build-cache-inputs/ temporary receipts. Original inputs admitted from the host source or its Git index remain protected even within those roots. Guest Git metadata cannot admit generated files as original inputs. The same input custody applies during capture, synchronization and recovery without changing saved manifest bytes. Older archives can lack the original index membership of saved files. Exact cache-root paths in the owned archive remain restored inputs; new generated paths under the same directories are still excluded. An ambiguous older cache file may therefore remain preserved.

If local workspace preparation reports that it expired during cleanup, retry the session. Both workspaces remain intact. Older missing baseline records repair automatically when either workspace still matches the saved baseline, or when an intact pending-checkpoint result reconstructs that exact baseline. Repair retains accepted path membership from surviving saved records. If needed, it also checks a canonical candidate containing paths observed by a complete sandbox scan, so accepted guest-created files need not be in the host Git index. These paths are only recovery candidates: their current content must reproduce the exact saved baseline before replacement metadata is accepted. Recovery keeps other live edits and pending receipts. Repair can read .openclaw/.pnpm-store/ when verifying an older saved baseline; subsequent synchronization still keeps new cache contents local. If neither can be verified, the error names both preserved paths and a command to compare them. That command only inspects differences; it does not restore the missing baseline. Keep both directories and ask a Gateway administrator to recover the saved baseline inventory before retrying. Recreating a sandbox does not repair missing baseline records.

For Git-backed native-node and SSH workspaces, captures use Git eligibility: tracked and non-ignored files, marker-authenticated staged inputs, ignored files explicitly selected by .worktreeinclude, and exact paths recorded in prior captures. Unselected ignored project files stay private, including directories that resemble staged inputs but lack a valid ownership marker. Result captures also retain ordinary .artifacts/ reports and screenshots, even when ignored; initial source admission and prepared-project verification keep Git eligibility. The declared disposable runtime and build-cache roots remain excluded, while tracked or previously admitted build-cache inputs remain protected. Unreadable eligible files fail capture. Plain workspaces keep their filesystem capture policy even when staging creates Git metadata. Older remote manifests can contain cache files whose origin is unknown; those exact paths remain preserved. This does not change the initial Gateway-source snapshot policy.

If you are a guest, you can ask the agent:

Bring this workspace up to date with the latest project changes, keeping my edits. Resolve any conflicts, rerun the relevant checks and Auto Review, and update the same PR. Do not merge it.

Use github_publish with action: "refresh_base" to explicitly integrate the current target branch of a prepared or published PR, or the selected repository base when no PR is associated, into this session's existing local managed workspace. This action is offered only in sessions with a writable managed sandbox; sessions running directly on the host merge the base with git in their workspace, then publish. The Gateway fetches with its host identity and prepares any missing file contents from the selected repository before offline merge and snapshot operations, including the ancestor versions needed to merge diverged branches. This also works when a partial clone already knows the base commit. A content-fetch failure leaves saved work available for retry. Refresh preserves saved guest files, ignored guest data, and empty directories. The operation returns the exact baseCommit, changed paths, and conflicting paths; it does not publish or change the GitHub pull request. It accepts no repository, URL, arbitrary ref, other session, or pull-request selector.

For prepared PRs, commit distinct staged changes before refreshing a file that also has unstaged edits. The action preserves both versions and refuses until that staged work is saved. Finish any pending prepare_pr operation first.

Resolve any reported conflicts in the same workspace, then repeat refresh_base with conflictsResolved: true and the returned baseCommit. This acknowledges that exact pending integration, including a deliberate choice to keep an unchanged binary file. Without acknowledgment, a retry keeps reporting conflicts. Remaining text conflict markers block completion. On completion, the calling sandbox imports only the selected base commit and source tree through bounded stdin, reusing available objects from host-selected snapshots when possible, then stages its current source. Guest HEAD, branches, and commit history remain unchanged. The result includes review: { mode: "local", base: "<commit>" }. Run tests and normal Auto Review with that exact target after refresh or conflict resolution, then publish to update the same PR, preserving its current draft or open state. Reviewing against the old guest HEAD would also include upstream-only changes. The operation requires the prepared sandbox of the current agent; a direct RPC cannot supply another runtime. Publication refuses a pending integration and never silently merges new base changes into reviewed files. A retry, restart, or later turn resumes the existing retained source result from the files it already applied instead of rolling them back, so a large refresh interrupted by a turn deadline still finishes; host merge ancestry remains outside guest Git metadata. Worktree removal is deferred while the host integration is pending; finish refresh before retrying archive cleanup. Existing privileged PR actions still require full operator write access.

Finish refresh and conflict resolution before downgrading. An interrupted transfer retains a source result that earlier Gateways reject instead of applying as ordinary workspace synchronization. Once both copies accept the transfer, that result is cleaned and native merge state owns any remaining conflict resolution. Return to a version supporting refresh_base to finish either pending phase.

The private checkout is writable with none or rw workspace access; explicit ro remains read-only. This does not make the shared agent workspace writable. Other sandbox backends cannot use this local managed-project projection and fail with an explanation rather than falling back to host execution.

The managed worktree remains the source of truth for files, snapshots, and publication. OpenClaw pauses the exact execution and browser runtimes that mount this checkout while capturing or applying changes. An existing session first checks both workspaces against their accepted baseline without pausing. If both are unchanged and no recovery is pending, its runtimes keep running. Changed or interrupted checks return to paused reconciliation; file edits are never applied from the live check. Checkpoints after commands and file mutations use the same check for the guest workspace: commands that leave accepted files unchanged do not pause the sandbox. Small, fast workspaces capture directly into an immutable Git result. A probe taking at least half a second or an accepted inventory of at least 20,000 entries selects filesystem capture for private checkouts provisioned as btrfs subvolumes. These checkpoints settle pending recovery while paused, take a snapshot, then resume while the captured files are scanned and reconciled into the managed worktree. The first capture after substantial workspace growth can still use the direct path; later probes see the larger accepted inventory. Other checkouts pause until their files are stored in an immutable Git result. A snapshot that omits nested subvolumes is discarded and captured again under pause, preserving their contents. Command completion still waits for canonical acceptance, so a read after a completed command sees its saved changes. Later background writes remain in the private checkout for the next checkpoint. After acceptance and runtime resume, the workspace lease transfers the snapshot to a unique retired path for asynchronous cleanup. The next command can run while cleanup continues. Before another snapshot, capture admission waits for cleanup and retries any interrupted removal, keeping the cleanup backlog bounded. Snapshot creation may wait for dirty data to flush, so the short paused operation does not guarantee a fixed maximum pause duration. Concurrent preparations of the same workspace and session generation share queued reconciliation. Once filesystem observation begins, later preparations require a fresh check so intervening edits remain visible. Completed preparation results are not cached. Each caller retains its own cancellation and authority checks. Reuse waits for reconciliation before returning the workspace, so the next command sees imported host edits and unresolved conflicts cannot be bypassed. The managed worktree preparation log records exclusive reuse.* entries in phaseDurationsMs and reuseDominantPhase, covering both unchanged probes, capture preparation, and reconciliation phases. Custody waits remain in the existing workspaceWait field. These timings include work performed while guests run; they are not pause durations. OpenClaw records pending results and rollback journals in SQLite. Imports into the private checkout keep runtimes paused through settlement. New shell calls and command preparation wait for an active checkpoint to release the workspace before proceeding; background commands do not hold that preparation lease for their entire lifetime. Files and assistant-media reads select the current backing without acquiring checkpoint custody or pausing runtimes. Each read retains its session and workspace authority checks; sandbox aliases also verify the existing runtime mount. For local sandbox sessions, a retained private checkout remains the preview's live view; direct host edits enter that view during the next workspace preparation. File saves checkpoint guest changes, compare the editor hash, update the canonical file, and import the saved change into the private checkout under the same custody before resuming its runtimes. Capture, publication, and lifecycle operations retain their reconciliation lease and pause requirements. Ordinary reconciliation also uses the btrfs capture for guest exports. Once an immutable result owns the source bytes, staged-file materialization, Git patch preparation, and temporary-file cleanup run with the guest resumed. Imports pause again before confirming the target and applying changes; edits made during preparation cause a visible conflict and remain saved. Pending base refreshes retain their pause until both workspaces accept the transfer.

Each successful container pause records a sandbox/quiescence info log with a bounded reason (checkpoint, preparation, publication, retirement, restore, or reconcile) and that reason's process-lifetime counter. Already-paused runtimes and stopped containers do not increment it; counters restart with the Gateway. Release records Local workspace unpause with the same reason, elapsed durationMs, dominantPhase, and dominantPhaseMs. Timing includes engine pause and resume calls. durationScope=observed means recovery found an already-paused runtime and cannot measure the earlier owner's interval; durationScope=owner covers this owner's pause. outcome distinguishes a resumed, already-running, or removed runtime. Failed resumes retain custody and do not log a successful release. Captured workspace authority is checked again after filesystem and engine preparation, immediately before filesystem commands, container creation/start/setup, and late browser restarts. Closing the owner during preparation prevents those effects rather than rejecting only afterward. Stopping a run blocks new commands and file operations while allowing its accepted workspace changes to finish checkpointing. Accepted command cleanup waits for an active checkpoint to resume the runtime before reaping its processes. Its reap budget starts after admission; the command's original exit and timeout results remain unchanged. Termination checkpoints any final writes from signal handlers before returning, including when an earlier finalization already checkpointed the command. Cleanup retains the workspace owner until termination and finalization finish, even after the parent exits. Settlement still requires the original session and worktree binding and live Gateway ownership; a replacement session or unresolved checkpoint failure cannot be reported as a clean stop. Conflicts preserve both versions and block further settlement until resolved. A retry or restart recovers the same pending result. Archive, reset, and deletion settle changes before retiring their runtimes; successful retirement clears owned pause receipts without resuming those runtimes. Failed retirement preserves guarded recovery for surviving paused runtimes. Projection cleanup follows the existing managed-worktree snapshot retention. Accepted guest-created ignored files (including symlinks) and empty directories survive archive and restore through the same pending-result recovery owner. This does not force ignored paths into Git publication or import unrelated ignored host files. Older versions leave that recovery receipt intact but do not apply it; return to a supporting version before continuing guest work.

With the OpenShell backend, mirror mode still uses the local workspace as the source of truth between exec turns, and remote mode uses the remote OpenShell workspace as the source of truth after the initial seed. The same access rules apply: none permits private workspace writes, while ro disables writes.

Inbound media is copied into the active sandbox workspace (media/inbound/*). Image facts that retain a staged path load that copy on later turns; missing copies and paths outside the active sandbox remain unavailable. Admitted native attachments recorded only as managed media://inbound/ references load their originals from the Gateway media store, including after a restart or workspace template reuse. They do not require a guessed sandbox filename. This does not grant file tools or image paths written in prompt text access to the host store. If a previously included image becomes unavailable, replay keeps a resend notice and stops retrying that image for the retained session decision. Resend the image as a new attachment to make another attempt; other attachments remain available. For a managed project session, attachments on follow-up messages use that session's private checkout, including after its worktree has been created. Attachment staging retains the managed workspace owner until the copy settles. If the worktree is removed while an attachment is being read, staging stops before creating its input directory or file; the original attachment remains available.

image_generate, video_generate, and music_generate also copy locally saved outputs into a private, Git-ignored directory under media/inbound/ in the requesting sandbox. The tool result and asynchronous completion report a Sandbox file path for follow-up reads, edits, and shell processing. Channel delivery still uses the managed original. Each copy is limited to the smaller of the configured media size limit and 50 MiB. Remote-only video URLs are not downloaded for staging. If the workspace is read-only or staging fails, the result reports that the sandbox copy is unavailable; generation and delivery still succeed. Resetting or deleting the requesting session stops further sandbox copies and prevents completion delivery to a replacement session. If a configuration reload changes sandbox policy, workspace selection, or the media size limit before a copy, staging stops with the same warning while the original remains available.

Was this useful?