Workspace Isolation Plugin
The Workspace Isolation plugin gives each conversation an isolated Linux sandbox (bubblewrap). Agents can edit files, run shell commands, and use git without changing other conversations or the host checkout.
If the plugin is enabled but the sandbox cannot start, all tool operations fail with a clear error. There is no silent fallback to running on the host.
Requirements
- Linux (not supported on macOS or Windows)
- bubblewrap with overlay support:
apt install bubblewrap(current distros ship 0.11.x, which has--overlay-src; only older or setuid packages need a source build) - User namespaces enabled — on Ubuntu 24.04+ the
apparmorpackage'sbwrap-userns-restrictprofile already grantsusernsto/usr/bin/bwrap. Do not add a second profile namedbwrap; it displaces that one.
Modes
mode | What the agent sees | Typical use |
|---|---|---|
overlay (default) | Configured repos at /workspace behind a copy-on-write overlay. Snapshots, project setup, and optional per-subagent isolation apply. | Development / coding |
host_readonly | The whole host filesystem read-only at identical paths, plus a discarded scratch overlay on the launch directory. Snapshots, project setup, and VCS integration are forced off; subagent_isolation is forced to shared. | Investigate flavor |
Configuration
plugins:
- module: codumentor.plugins.workspace_isolation
class: WorkspaceIsolationPlugin
priority: 5
args:
enabled: true
mode: overlay # or host_readonly
workspace_base: ~/.codumentor/workspaces
workspace_ttl: 86400 # orphaned snapshot TTL (24h)
persistent_home: true
session_tmp: true
subagent_isolation: shared # or isolated
sandbox:
unshare_net: true
seccomp: default
env_mode: minimal
integration: # used when subagent_isolation: isolated
enabled: true
auto_commit: true
ai_merge: true
snapshots:
enabled: true
shared: true
upper_dir_ttl: 2592000 # 30 days
cleanup_interval: 3600
min_free_gb: 5
project_setup:
enabled: true
timeout_s: 600
cache_budget_bytes: 5368709120 # 5 GiB
failed_ttl_s: 86400
auto_build: true
Top-level
| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable isolation |
mode | string | "overlay" | "overlay" or "host_readonly". Invalid values fall back to "overlay" |
workspace_base | path | ~/.codumentor/workspaces | Directory for session workspaces |
workspace_ttl | int | 86400 | Seconds before an orphaned snapshot (no active sessions) is deleted |
persistent_home | bool | true | Bind-mount a persistent $HOME for the session (shared by the main agent, subagents, and external agents). false = ephemeral tmpfs HOME |
session_tmp | bool | true | Bind-mount a per-session /tmp so files survive across shell calls in the same conversation (overlay only). false = fresh tmpfs per command |
subagent_isolation | string | "shared" | "shared": subagents use the parent's overlay. "isolated": each subagent gets its own overlay; changes are merged back. Invalid values (and isolated with host_readonly) fall back to "shared" |
Sandbox hardening (sandbox:)
Network isolation is on by default. Other flags default off. Unknown keys are ignored.
| Option | Type | Default | Description |
|---|---|---|---|
unshare_net | bool | true | Isolate the network namespace (no outbound/inbound networking) |
unshare_uts | bool | false | Isolate hostname. Setting hostname turns this on automatically |
unshare_cgroup | bool | false | Isolate cgroups |
hostname | string | null | Hostname inside the sandbox |
new_session | bool | false | New session ID (setsid) |
seccomp | string | "default" | Syscall filter: "default" / "log" (audit only), "enforce" (block), "off" (no filter). If a filter is requested but cannot be loaded, the sandbox fails closed (tools disabled) rather than running unfiltered — set off to run without a filter |
env_mode | string | "minimal" | "minimal": only a baseline env (PATH, HOME, LANG, TERM, …). "inherit_all": copy the host environment |
inherit_env_vars | list | [] | Extra host env vars to forward in minimal mode |
clearenv | bool | true | Legacy. clearenv: false maps to env_mode: inherit_all if env_mode is unset |
allowed_env_vars | list | [] | Deprecated alias for inherit_env_vars |
Subagent integration (integration:)
Applies only when subagent_isolation: isolated. Default shared mode does not create feature branches or merge.
| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Merge isolated-subagent changes back into the parent sandbox |
auto_commit | bool | true | Commit leftover uncommitted subagent changes before merging. Author is "Codumentor" <codumentor@local> — not the SCM Push git_commit identity |
ai_merge | bool | true | Ask the LLM to resolve merge conflicts. false reports conflicts without auto-resolution |
Git, SVN, and non-VCS trees are all supported. Isolated subagents get a private feature branch; when they finish, a diff is applied to the parent. Conflicts can be resolved automatically when ai_merge is on.
Snapshots (snapshots:)
Snapshots freeze the overlay base at session start so an ingestion pull mid-session does not change what the agent sees.
| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Snapshot repos at session start |
shared | bool | true | Sessions at the same commit share one snapshot |
upper_dir_ttl | int | 2592000 | Seconds before an idle session's writable overlay (file edits) is deleted. Default 30 days — those edits cannot be regenerated from git |
cleanup_interval | int | 3600 | How often expired workspaces and orphaned snapshots are swept. 0 disables the loop |
min_free_gb | float | 5 | When free space on the snapshots filesystem drops below this, orphaned snapshots are pruned oldest-first. 0 disables |
Approximate snapshot cost: git uses a detached worktree (cheap); SVN exports at the pinned revision (full copy); non-VCS dirs use a hardlink copy.
Project setup (project_setup:)
On first session for a repo, .codumentor/setup.sh (if present) runs inside the sandbox. Built artifacts (e.g. .venv) are cached on the host and reused.
| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Run project setup scripts |
timeout_s | float | 600 | Per-repo setup timeout (seconds) |
cache_budget_bytes | int | 5368709120 | Per-repo cap on cached setup artifacts (5 GiB) |
failed_ttl_s | int | 86400 | How long a failed setup cache is kept before retry |
auto_build | bool | true | Warm the setup cache after a webhook re-ingest so the next conversation does not pay the build cost |
Host read-only (host_readonly: — mode: host_readonly only)
| Option | Type | Default | Description |
|---|---|---|---|
scratch_overlay | bool | true | Writable overlay on the launch directory; writes are discarded with the session |
expose_host_tmp | bool | true | Host /tmp visible read-only at /tmp/host |
unshare_pid | bool | false | PID namespace isolation. Off by default so ps / /proc see host processes |
network | string | "ask" | "share" (host network), "isolate" (no network), or "ask" (prompt once per conversation; headless falls back to "isolate"). Invalid values fall back to "ask" |
In this mode the agent can read host paths (logs, configs, journalctl) but cannot write the host. systemctl and unix-socket clients fail because the root is read-only.
Overlay vs host checkout
In overlay mode the host repositories stay read-only. All writes go to a per-session upper layer under workspace_base. Branch Switching checkouts and SCM Push commits happen in that overlay, not on the host working copy.
See also
- Branch Switching — per-conversation branch checkout inside the overlay
- SCM Push —
git_commitin the overlay; host-side Push button