Configuration reference
Configure mounts, secrets, browser integration, clipboard access, host UI, and update behavior.
View source MarkdownThis document explains the ags config schema, field by field.
Use config/config.example.toml as your starting template.
Where config lives#
Base config path:
~/.config/ags/config.toml
Optional repo-local overlay path:
PROJECT_ROOT/.ags/config.toml
You can override the base config at runtime:
ags --agent pi --config /path/to/config.tomlIf the base config path does not exist, ags creates a minimal default file on first run.
Precedence and merge behavior#
When AGS is launched inside a git repo, it resolves PROJECT_ROOT from the active repository/worktree root (git rev-parse --show-toplevel) and then loads config in this order:
- base config (
~/.config/ags/config.toml, or--config <path>if provided) - repo-local overlay (
PROJECT_ROOT/.ags/config.toml) if present
Merge rules:
- scalar fields: repo-local value overrides base value
- table/object fields: merged recursively; repo-local keys win
- repeatable top-level sections are additive:
[[mount]][[agent_mount]][[tool]][[secret]]
- other arrays are replaced by the repo-local value
This lets a project add mounts, tools, and non-command secrets locally without copying your full personal config. For host security, repo-local overlays cannot define command secret sources, including under [[tool.secret]].
Path and env expansion behavior#
For path-like fields, including the executable element (command[0]) of command secret sources, ags supports:
~expansion (home directory)- environment variable expansion:
$VAR${VAR}
Then paths are resolved to absolute paths.
If an env var is undefined during expansion, the reference is left as-is.
Top-level sections#
[sandbox](required)[[agent_mount]](optional, repeatable, recommended)[[mount]](optional, repeatable)[[tool]](optional, repeatable)[[secret]](optional, repeatable)[browser](optional)[host_ui](optional)[update](optional)
[sandbox]#
Core runtime settings.
[sandbox]
image = "localhost/agent-sandbox:latest"
containerfile = "~/.config/ags/Containerfile"
cache_dir = "~/.cache/ags"
gitconfig_path = "~/.config/ags/gitconfig-agent"
auth_key = "~/.ssh/ags-agent-auth"
sign_key = "~/.ssh/ags-agent-signing"
bootstrap_files = ["auth.json", "models.json"]
container_boot_dirs = ["/home/dev/.ssh"]
passthrough_env = ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"]Fields#
image(string, required)- Podman image tag used for runs.
containerfile(path, required)- Containerfile path used by
ags update-imageand auto-build fallback.
- Containerfile path used by
cache_dir(path, required)- Host cache dir for ssh-agent env/socket and tool caches.
gitconfig_path(path, required)- Host path for generated git signing config used in container.
auth_key(path, required)- SSH key for git auth.
sign_key(path, required)- SSH key for commit signing.
bootstrap_files(string array, optional)- Reserved bootstrap file list.
container_boot_dirs(string array, optional)- Directories created in container before launching agent.
passthrough_env(string array, optional)- Host env vars to pass into container if set and not already resolved from secrets.
[[agent_mount]]#
Dedicated, explicit mounts for agent home-state paths (no implicit runtime mounts).
[[agent_mount]]
host = "~/.pi"
container = "/home/dev/.pi"
[[agent_mount]]
host = "~/.claude"
container = "/home/dev/.claude"
[[agent_mount]]
host = "~/.claude.json"
container = "/home/dev/.claude.json"
kind = "file"Fields#
host(path, required)container(string, required)kind("dir" | "file", optional, default"dir")
Behavior:
- mode is always
rw whenis alwaysalways- mount is always required (
optional=false,create=false)
[[mount]]#
Extra host bind mounts.
[[mount]]
host = "~/.ssh/known_hosts"
container = "/home/dev/.ssh/known_hosts"
mode = "ro"
kind = "file"
when = "always"
create = false
optional = true
source = "config"Fields#
host(path, required)container(string, required)mode("ro" | "rw", required)kind("dir" | "file", optional, default"dir")when("always" | "browser", optional, default"always")create(bool, optional, defaultfalse)- If host path missing, create it automatically.
optional(bool, optional, defaultfalse)- If host path missing and
create=false, skip instead of failing.
- If host path missing and
source(string, optional, default"config")- Label used in diagnostics/errors.
Missing-path behavior#
If host path is missing:
create=true→ path is created- else if
optional=true→ mount is skipped - else → run fails (
required mount source missing)
Recommended optional mounts for dcg#
If you want sandboxed dcg to use host-managed global config and persist its own user-level state, add mounts like:
[[mount]]
host = "$HOME/.config/dcg"
container = "/home/dev/.config/dcg"
mode = "rw"
kind = "dir"
optional = true
[[mount]]
host = "$HOME/.local/share/dcg"
container = "/home/dev/.local/share/dcg"
mode = "rw"
kind = "dir"
optional = true
create = trueNotes:
- project-local
.dcg.tomlis picked up automatically from the workspace mount ~/.config/dcgcovers global config, allowlists, and allow-once state~/.local/share/dcgcovers dcg history storage- if you do not mount these, sandbox dcg still works with built-in defaults plus project-local config
Recommended host-side dcg starting point:
# ~/.config/dcg/config.toml
[packs]
enabled = [
"database.postgresql",
"containers.docker",
]This keeps dcg core protections on (implicit) and adds common AGS-adjacent packs without inventing AGS-specific policy syntax.
[[tool]]#
Declares a tool binary mount, optional directories, optional secrets.
[[tool]]
name = "qwk"
path = "~/.local/bin/qwk"
container_path = "/usr/local/bin/qwk"
mode = "ro"
when = "always"
optional = true
[[tool.directory]]
host = "~/.config/qwk"
container = "/home/dev/.config/qwk"
mode = "rw"
kind = "dir"
create = true
[[tool.secret]]
env = "QWK_LINEAR_API_KEY"
from_env = "QWK_LINEAR_API_KEY"[[tool]] fields#
name(string, required)path(path, required)container_path(string, required)mode(ro|rw, optional, defaultro)when(always|browser, optional, defaultalways)optional(bool, optional)
[[tool.directory]]#
Same schema/behavior as [[mount]].
[[tool.secret]]#
Same schema as [[secret]], but tagged to that tool for diagnostics.
[[secret]]#
Maps target env var names to one or more sources.
[[secret]]
env = "GH_TOKEN"
from_env = "GH_TOKEN"
[[secret]]
env = "GH_TOKEN"
command = [
"$HOME/.local/bin/credential-store-adapter",
"lookup",
"--service",
"github",
]
[[secret]]
env = "GH_TOKEN"
secret_store = { service = "github-cli-login-switcher", username = "general" }Recommended modern fields#
env(required): target env var name inside containerfrom_env(optional): source env var from host process environmentsecret_store(optional): key/value attributes forsecret-tool lookupcommand(optional): non-empty argv string array for a trusted host credential helper
A single entry can include multiple source types. For command, the first element must resolve to an absolute executable path; remaining elements are passed as literal argv entries. AGS expands ~, $VAR, and ${VAR} only in the executable. It invokes the executable directly without a shell, so arguments receive no shell parsing or interpolation.
Legacy fields (still accepted)#
provider = "env" | "secret-tool"var(for env provider)attributes(for secret-tool provider)
Resolution behavior#
- Secrets are processed in config order.
- For the same target
env, first successful source wins. - Empty/unresolved sources are ignored.
- Command lookup has a five-second timeout. AGS kills and reaps a timed-out helper, then tries the next source.
- Helpers run from the host user's home directory rather than the repository working directory. AGS terminates the helper's process group on timeout or malformed/unbounded output.
- Command success requires exit status
0and one non-empty UTF-8 value on stdout. One trailing\nor\r\nis removed. Empty, multiline, NUL-containing, invalid UTF-8, missing, timed-out, and non-zero results are unresolved. - Command helpers receive only allowlisted host variables when present:
PATH,HOME,USER,LOGNAME,DBUS_SESSION_BUS_ADDRESS, andXDG_RUNTIME_DIR. They do not receive previously resolved secrets. - Helper stdout and stderr are never included in normal diagnostics.
ags doctorreports executable availability and lookup success or a structural failure without displaying the value or helper output. --lockdowndisables all configured secret resolution, including command execution.
Command source security and delivery#
command intentionally executes trusted user configuration on the host before the container starts. It is accepted only from the user/global base config (including an explicitly selected --config file). AGS rejects command sources from repo-local .ags/config.toml overlays, including nested [[tool.secret]] declarations.
The resolved value is inserted into AGS's existing secret environment map and delivered through the existing environment-file/container-environment mechanism. A sandboxed process can inspect the resulting environment variable. Command sources expand host-side credential-store support; they do not provide process-scoped delivery or keep the resolved value outside the sandbox.
1Password Secure Note sets are run-only#
1Password injection has no config.toml key. Do not add an entry, mapping, preset, or allowlist to this file. It is activated only for a single run with repeatable --op-secret-set VAULT/ITEM (or -1 VAULT/ITEM), for example:
ags --agent pi -1 'ExampleVault/readonly-database'The referenced host item must be a SECURE_NOTE; its present string-valued fields are injected by their exact labels into only the final agent process tree. See the README's “1Password Secure Note environment sets” section for ordering, security limits, local-Podman requirement, and a no-value-output smoke test.
[browser]#
Controls optional browser sidecar used with --browser.
[browser]
enabled = true
command = "google-chrome"
profile_dir = "~/.cache/ags/chrome-profile"
debug_port = 9222
pi_skill_path = "/home/dev/browser-tools"
command_args = []Fields#
enabled(bool, defaultfalse)command(string)- Required when enabled.
- Can be a PATH command (
google-chrome) or executable path.
profile_dir(path)- Required when enabled.
debug_port(u16)- Required and non-zero when enabled.
pi_skill_path(string)- Injected for Pi runs in browser mode (
--skill <path>).
- Injected for Pi runs in browser mode (
command_args(string array)- Extra args passed to browser command.
[host_ui]#
Controls optional host-owned Glimpse windows for sandboxed code and AGS's own branded approval dialogs.
[host_ui]
enabled = true
binary = "/path/to/glimpse_host_ui"
renderer = "process"
renderer_bin = "/path/to/glimpse"
idle_timeout_ms = 0
log_level = "info"Fields#
enabled(bool, defaultfalse)- Starts the AGS host UI sidecar for each run.
binary(string, defaultglimpse-host-ui)- Path or command for the host UI service.
renderer(string, defaultstub)- Renderer backend name passed to the host UI service.
- Use
processfor normal interactive Glimpse windows. stubis mainly useful for testing.
renderer_bin(path, optional)- Required when the chosen renderer needs an external binary, such as
renderer = "process".
- Required when the chosen renderer needs an external binary, such as
idle_timeout_ms(u64, default0)- Idle timeout passed to the host UI service.
0disables idle shutdown so the sidecar stays alive for the AGS session.
log_level(string, defaultinfo)- Logging level passed to the host UI service.
Notes:
- AGS handles the sandbox wiring automatically once
[host_ui].enabled = true. - Auth-proxy and clipboard approval prompts use the same host UI sidecar for branded, dark/light-aware dialogs; if disabled, they fall back to zenity/kdialog.
- Users normally should not set Glimpse transport env vars manually.
- For end-user setup and troubleshooting, see
docs/GLIMPSE.md.
[clipboard]#
Controls the narrow AGS clipboard bridge. The bridge lets sandboxed wl-paste/wl-copy calls talk to a session-scoped host service instead of mounting the real Wayland compositor socket.
[clipboard]
enabled = true
mode = "readwrite" # off | read | readwrite
max_bytes = 33554432
approval_required = true
approval_seconds = 300
approve_writes = falseFields#
enabled(bool, defaulttrue)- Starts the AGS clipboard sidecar for normal runs.
- Lockdown mode disables it regardless of config.
mode(string, defaultreadwrite)off: no clipboard bridge.read: host → sandbox reads only, enough for Pi Ctrl-V image paste.readwrite: also allows sandbox → host writes for copy flows.
max_bytes(usize, default33554432)- Maximum clipboard payload size for reads and writes.
approval_required(bool, defaulttrue)- Prompts on the host before sandboxed code can read clipboard contents.
- Set to
falseto restore session-wide read access while[clipboard]is enabled.
approval_seconds(u64, default300)- Adds an Allow for N seconds choice to the approval dialog.
- Set to
0to only offer one-shot approval.
approve_writes(bool, defaultfalse)- Also require approval before sandboxed
wl-copywrites to the host clipboard.
- Also require approval before sandboxed
Security note: this is narrower than compositor passthrough. Clipboard reads are host-approved by default, but MIME type listing remains available so Pi can decide whether Ctrl-V image paste is possible.
[desktop_passthrough]#
Controls broad desktop/session primitive passthroughs. These should stay disabled unless explicitly needed for debugging GUI clients inside the sandbox.
[desktop_passthrough]
wayland = falseFields#
wayland(bool, defaultfalse)- Mounts the real Wayland compositor socket and injects
WAYLAND_DISPLAY/XDG_RUNTIME_DIR. - This lets arbitrary Wayland-capable sandbox processes open host windows.
- Can also be enabled per run with
--wayland-compositor-passthrough.
- Mounts the real Wayland compositor socket and injects
[update]#
Controls ags update-agents behavior.
[update]
pi_spec = "@earendil-works/pi-coding-agent"
minimum_release_age = 1440Fields#
pi_spec(string, default@earendil-works/pi-coding-agent)- Package spec used for Pi install/update.
- Older configs with the exact legacy value
@mariozechner/pi-coding-agentshould be updated;ags update-agentstreats that value as the current default during migration.
minimum_release_age(u32, default1440)- Written to pnpm config (
minimum-release-age) inside update container.
- Written to pnpm config (
Validation tips#
- Run
ags doctorafter config changes. - Keep required mounts minimal and explicit.
- Prefer
optional=truefor machine-specific paths. - Prefer
mode="ro"unless writes are necessary. - Keep browser section disabled unless you actively use it.
Improve this page where the source lives.