Global defaults live in ~/.config/enclave/config.json. Project overrides live
in ~/.config/enclave/projects/<hash>/config.json, keyed by project hash and
kept outside the worktree. CLI flags always take the highest precedence.
Project overrides live outside the worktree so a project cannot alter its own
isolation policy. Extension files are discovered from built-in extensions/
plus user-global ~/.config/enclave/extensions/.
Extensions installed with enclave tools|features add carry a
.enclave-source.json provenance sidecar in their user-global directory.
Editing an installed extension's files by hand blocks
enclave tools|features update for that extension until --force. See
Installing Extensions.
The ~/.config/enclave/ paths shown throughout this document are the Linux
(XDG) config root. On macOS the config root is
~/Library/Application Support/org.eclipse.enclave/config/ instead;
substitute it for ~/.config/enclave/ in every path below.
Option source precedence (highest to lowest):
- CLI flags
- Selected tool override (
tool_overrides.<tool>in config) - Project config (
~/.config/enclave/projects/<hash>/config.json) - Global config (
~/.config/enclave/config.json) - Built-in defaults
Security guardrail: project config cannot elevate guarded options. Each is
ignored with a warning naming the file; use global config or CLI flags for
explicit host opt-in. Guarded at project scope: tool, yolo,
allow_all_network=true, allow_domains, pass_env, host_config,
tool_overrides.<tool>.host_config_paths, base_image, bridge_ports,
add_dirs/add_readonly_dirs entries outside the project subtree,
project_mount="writable", and any worktree_metadata value that relaxes the
inherited mode.
Top-level host_config_paths is not part of that set: it is ignored with a
warning in any config file, global included, because passthrough paths are only
supported under tool_overrides.<tool>.
| Key | Description |
|---|---|
tool |
Default tool (e.g. claude, codex); unset means the first interactive session asks once and writes the answer here (see Tool selection) |
backend |
Isolation backend: auto (default) uses docker or podman, whichever is installed, and asks once when both are; or docker, podman, experimental qemu |
host_config |
none (default) or passthrough |
skills_validation |
Shared skill validation: strict (default) or agent; supports tool overrides |
tool_overrides.<tool>.host_config_paths |
Per-tool passthrough path directives (default, +path, -path, or explicit list) |
yolo |
Enable YOLO mode (default: true). Only consulted when the selected tool's profile leaves yoloEnabled unset; every bundled CLI agent sets it, so use --yolo/--no-yolo for those |
ephemeral |
Run without persistent auth/env stores |
auth_scope |
shared or project (default: shared) |
auth_name |
Named per-tool shared auth identity slug; unset uses the default store |
secrets_scope |
both, global, or project (default: both) |
reset_auth |
Clear auth on start |
no_api_key |
Disable API key injection |
pass_api_key |
Allow API key in ephemeral mode |
pass_env |
List of host env vars to forward |
allow_all_network |
Disable network restrictions |
allow_domains |
Extra domains added to the gateway allowlist (bare DNS names; ignored when allow_all_network=true) |
no_cache |
Disable package caches |
no_history |
Disable shell history |
no_memory |
Disable per-project agent memory; see memory controls |
session_monitor |
Run agents under the managed tmux session (enables status snapshots) |
session_tint |
Terminal background color marking a session-owned terminal, as #rrggbb (unset: no tint) |
base_image |
Docker base image override |
devcontainer |
Derive base image from devcontainer.json |
slim |
Build without features (tools only) |
cache_from |
Docker build cache source |
progress |
Docker build progress output style |
image_name |
Override default image name/tag |
features |
Feature extensions to enable |
use_remote_user |
Honor devcontainer remoteUser for agent sessions |
network_log |
Network audit mode: coarse (default, one event per TLS connection) or requests (one event per HTTP/HTTPS request, forcing MITM). See Coverage and granularity |
verbose |
Verbose logging |
ports |
Publish container ports to the host (container → host) |
add_dirs |
Additional directories to mount |
add_readonly_dirs |
Additional directories to mount read-only |
project_mount |
writable (default) or readonly for the project/worktree mount |
worktree_metadata |
Linked-worktree git metadata mounts: follow (default), readonly, or none |
playwright_mcp |
Enable Playwright MCP server (Claude only) |
bridge_ports |
Forward host ports into the container (host → container) |
Project config may set project_mount to readonly, but project_mount="writable"
is ignored at project scope so it cannot weaken a stricter global default. In
readonly mode, writable add_dirs entries inside the project subtree are
mounted read-only.
worktree_metadata controls the gitdir/commondir mounts that enclave
resolves from a linked worktree's .git file. follow ties them to the
project mount mode, readonly forces them read-only while the working copy
stays writable, and none skips them entirely. With read-only metadata the
agent can edit files and read history (git log, git diff, git status),
but every git write, including git add, fails; staging and committing happen
on the host. Project config may strengthen the inherited mode from follow to
readonly or none, or from readonly to none; settings that would weaken
the inherited mode are ignored. For a regular repository whose .git
directory sits inside the project, the project mount mode governs and this
option has no effect.
session_tint marks the terminal that owns a session, so a sandboxed session
is visually distinct from an ordinary shell. When set to an #rrggbb value,
run (including shell, continue, and resume), exec, and attach set
the terminal background on start and reset it on exit. Inside tmux 3.3 or later
only the session's pane is tinted; elsewhere the whole window is. Because only
the background changes, pick a color that keeps your foreground text readable —
enclave does not adjust it. Invalid values are reported when the config file is
read and ignored.
The tint is skipped when stdout is not a terminal and when NO_COLOR or
ENCLAVE_COLOR=never is set; ENCLAVE_COLOR=always does not enable it, as the
config key is the only switch. Because per-tool and per-project config layers
apply, tool_overrides.<tool>.session_tint gives each tool its own color and a
project config gives each project one; attach resolves the color for the tool
and project of the session it attaches to, not for the current directory.
Agents that paint their own background can cover the tint.
The reset restores the terminal's configured default background, not whatever
background was in effect before the session, so a color set at runtime (theme
switchers, base16-style scripts) is dropped when the session ends. If enclave is
killed with SIGKILL the reset never runs; clear a leftover tint with
printf '\e]111\a'.
Example:
{
"tool": "codex",
"project_mount": "readonly",
"secrets_scope": "project",
"pass_env": ["GITHUB_TOKEN"],
"allow_all_network": false
}Use + and - prefixes to modify the parent config instead of replacing it:
// Global config (~/.config/enclave/config.json):
{ "features": ["node-dev", "python-dev"] }
// Project config (~/.config/enclave/projects/<hash>/config.json):
{ "features": ["+devtools", "-python-dev"] }
// Result: ["devtools", "node-dev"]Values without prefixes replace the parent set entirely.
features defaults to implicit "default" when unset. Additive entries are
applied against the implicit default-enabled set, so ["-node-dev"] removes
that default feature and [] means "none".
host_config_paths is resolved per tool against that tool's reviewed
passthroughPaths from its spec.yaml. Use:
["default"]to start from the built-in reviewed allow-list["+commands/", "-skills/"]to modify the built-in reviewed allow-list["settings.json", "agents/"]to replace the built-in allow-list entirely
Entries are relative to the tool's host config directory, not absolute host
paths. For Claude, settings.json means ~/.claude/settings.json, and adding a
helper script should use +statusline-command.sh, not
+/home/alice/.claude/statusline-command.sh.
host_config_paths only affects host_config=passthrough. A hard safety
backstop still blocks auth files, OAuth JSON, history/session files, and common
runtime-state directories even if you add them here.
Passthrough follows symlinks: an allow-listed entry copies whatever its symlink
resolves to, even a target outside the tool config directory. This is what lets
dotfile managers (home-manager/Nix, GNU stow, chezmoi) symlink configs into
place. The auth/OAuth backstop still rejects any symlink that resolves to a known
credential file, but the history/session/state backstop is anchored at the config
root and does not re-match those names at nested paths reached through a symlinked
directory (e.g. sessions/ blocks ~/.claude/sessions but not a symlinked
commands/ that contains a sessions/ subdir). Because the config directory and
its symlinks are user-controlled, only point allow-listed entries at content you
intend to share with the container.
Override tool-native config files without rebuilding the image.
Canonical override directories:
- Global:
~/.config/enclave/tools/<tool>/ - Per-project:
~/.config/enclave/projects/<project-hash>/<tool>/config/
Each directory mirrors the tool's native config layout. For example, Claude overrides live under ~/.config/enclave/tools/claude/ with files like settings.json, commands/..., agents/..., and skills/....
At startup, enclave assembles a generated config source from:
- Built-in settings, templates, tool-extension skills, and enabled-feature skills
- Allow-listed host config when
host_config=passthrough - Global shared skills, then global tool-specific overrides and patches
- Project shared skills, then project tool-specific overrides and patches
The generated source is then copied into the writable tool config store before auth symlinks and tool-specific setup run.
A tool receives managed skills only when its extension declares sandbox.skillsDir. Shared skills use tool-neutral paths:
- Global:
~/.config/enclave/skills/<skill>/ - Per-project:
~/.config/enclave/projects/<project-hash>/skills/<skill>/
Tool-specific skills belong in the canonical native config tree. Mirror skillsDir relative to configDir:
- Global:
~/.config/enclave/tools/<tool>/<relative-skills-path>/<skill>/ - Per-project:
~/.config/enclave/projects/<project-hash>/<tool>/config/<relative-skills-path>/<skill>/
For example, Claude uses skills/, while Pi uses agent/skills/:
~/.config/enclave/tools/claude/skills/review/
~/.config/enclave/tools/pi/agent/skills/review/
Skill precedence, lowest to highest, is:
- Built-in tool-extension skills
- User-global tool-extension skills
- Skills shipped by enabled features (only features selected for the session contribute; see Extensions)
- Allow-listed native host config when passthrough is enabled
- Global shared skills
- Global tool-specific skills
- Project shared skills
- Project tool-specific skills
A higher-precedence same-named skill replaces the complete lower-precedence skill directory; files from two versions are not merged. Project scope therefore wins over global specificity: a project shared skill overrides a global tool-specific skill, while a project tool-specific skill overrides both.
With host_config=passthrough, every built-in skill-capable tool passes its native host skills directory through by default: the tool's reviewed passthroughPaths includes the skills path (skills/ for most tools, agent/skills/ for pi). Opt out under the selected tool override:
{
"tool_overrides": {
"claude": {
"host_config_paths": ["default", "-skills/"]
}
}
}For pi, use -agent/skills/. At session start the log lists exactly which allow-listed paths pass through. Shared skills do not require host passthrough; the directives above exclude host skills while retaining passthrough for other settings.
skills_validation controls validation of global and project shared skills:
strict(default):SKILL.mdmust be a regular, readable file with YAML frontmatter containing requirednameanddescriptionfields and optionallicense,compatibility, andmetadatafields. The name must match the directory and use lowercase letters, numbers, and hyphens. Other fields, includingallowed-toolsanddisable-model-invocation, cause the skill to be skipped.agent: require a regular, readableSKILL.md, then copy its bytes and supporting files unchanged. Enclave does not parse the frontmatter, enforce name matching, strip fields, or translate metadata between agents. The selected agent validates and interprets the skill; metadata accepted by one agent may be ignored or rejected by another.
In both modes, overrides are keyed by directory name. In agent mode, different directories can declare the same frontmatter name and both reach the agent; Enclave does not deduplicate them.
Enclave warns and skips invalid shared skills rather than failing the session. A skipped higher-precedence skill leaves the lower-precedence skill intact. Tool-specific overrides, host passthrough, and extension skills are unaffected by this option.
Set "skills_validation": "agent" in global or project config.json, or under tool_overrides.<tool>. The mode applies to all shared skills in the session. Values are case-insensitive and surrounding whitespace is ignored. The normal option precedence applies; --skills-validation strict|agent takes priority over config files. Project configuration may select agent because it is stored in Enclave's host-managed configuration root and does not expose additional host paths.
In both modes, symlinked skill directories and symlinks inside skills are ignored; SKILL.md itself must be a regular file.
Built-in skills remain tool-specific so extensions can carry harness-specific metadata. Skills shipped by enabled features overlay as trusted extension content and skip shared-skill validation. Tools without sandbox.skillsDir ignore all shared skill sources.
A full config override uses the file's native path in the canonical config directory:
- Global:
~/.config/enclave/tools/<tool>/<native-config-path> - Per-project:
~/.config/enclave/projects/<project-hash>/<tool>/config/<native-config-path>
A patch mirrors the same native path below a dedicated patch directory:
- Global:
~/.config/enclave/patches/<tool>/<native-config-path> - Per-project:
~/.config/enclave/projects/<project-hash>/patches/<tool>/<native-config-path>
Common settings paths:
| Tool | Native config path |
|---|---|
| claude | settings.json |
| codex | config.toml |
| mistral-vibe | config.toml |
| opencode | opencode.json |
| pi | agent/settings.json |
Patches can target any existing JSON or TOML file in the generated tool config, not only the declared settings file. The target must exist in a lower-precedence layer.
Config files are resolved from lowest to highest precedence:
- Built-in config
- Allow-listed host config when
host_config=passthrough - Global full file or patch
- Project full file or patch
A patch merges onto the complete lower-precedence result. A full file replaces the effective config at its scope. Defining both a full file and a patch for the same path at the same scope is an error.
Merge semantics:
- JSON: scalars replace, objects deep-merge, arrays replace,
nulldeletes keys - TOML: scalars replace, tables deep-merge, arrays replace (key deletion not supported)
| Variable | Description |
|---|---|
ENCLAVE_HOME |
Override asset discovery to point at a specific repo checkout |
ENCLAVE_LOG_LEVEL |
Log level: info (default) or debug |
ENCLAVE_AGENT_UPDATE_INTERVAL_HOURS |
Minimum hours after a tool's last successful automatic update before check-update.sh is eligible to probe again (0 = always) |
ENCLAVE_DEVCONTAINER_REWRITE_VARS |
Comma-separated extra env var names for devcontainer home-path normalization |
These are read by the Windows launcher on the Windows side only, and are not forwarded into the WSL2 distribution. See windows.md.
| Variable | Description |
|---|---|
ENCLAVE_WSL_DISTRO |
Distribution to use for a Windows drive working directory; ignored with a warning when the working directory already names one |
ENCLAVE_WSL_ALLOW_WINDOWS_PATH |
Set to 1 to accept a Windows drive working directory and reach it through /mnt/<letter> |
ENCLAVE_WSL_FORWARD_ENV |
Comma-separated extra variables to forward into the distribution, each optionally with a WSLENV flag suffix (/p, /l, /u, /w) |
Buildx cache and canonical build UID/GID controls are CLI-only. Use
--buildx-cache-dir, --build-uid, --build-gid, and --runtime-uid-remap
for event/offline runs.
The experimental qemu backend only runs unrestricted, slim/no-feature bundles, so selecting it implies allow_all_network=true and slim=true automatically (with a per-run notice). Requesting features or an allowlist (--allow-domain) is rejected because the backend cannot honor them.
enclave config # Show configuration values (matrix view)
enclave config --view source # Annotate each value with where it came from
enclave config --view diff # Show values overridden by higher precedence
enclave config --view effective # Show effective values only
enclave config --json # Emit JSON output| Flag | Description |
|---|---|
--view <mode> |
Output view: matrix (default), effective (effective values only), diff (values overridden by higher precedence), or source (where each value comes from: CLI, tool override, project, global, default) |
--json |
Emit JSON output |