Skip to content

Latest commit

 

History

History
342 lines (263 loc) · 18.6 KB

File metadata and controls

342 lines (263 loc) · 18.6 KB

Configuration

Config Files

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):

  1. CLI flags
  2. Selected tool override (tool_overrides.<tool> in config)
  3. Project config (~/.config/enclave/projects/<hash>/config.json)
  4. Global config (~/.config/enclave/config.json)
  5. 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>.

Config Keys

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
}

Additive Syntax for features and host_config_paths

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.

Tool Config Overrides

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:

  1. Built-in settings, templates, tool-extension skills, and enabled-feature skills
  2. Allow-listed host config when host_config=passthrough
  3. Global shared skills, then global tool-specific overrides and patches
  4. 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.

Managed Skills

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:

  1. Built-in tool-extension skills
  2. User-global tool-extension skills
  3. Skills shipped by enabled features (only features selected for the session contribute; see Extensions)
  4. Allow-listed native host config when passthrough is enabled
  5. Global shared skills
  6. Global tool-specific skills
  7. Project shared skills
  8. 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.md must be a regular, readable file with YAML frontmatter containing required name and description fields and optional license, compatibility, and metadata fields. The name must match the directory and use lowercase letters, numbers, and hyphens. Other fields, including allowed-tools and disable-model-invocation, cause the skill to be skipped.
  • agent: require a regular, readable SKILL.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.

Tool Config Patches

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:

  1. Built-in config
  2. Allow-listed host config when host_config=passthrough
  3. Global full file or patch
  4. 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, null deletes keys
  • TOML: scalars replace, tables deep-merge, arrays replace (key deletion not supported)

Environment Variables

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.

Inspecting Resolved Config

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