375 lines
7.7 KiB
Markdown
375 lines
7.7 KiB
Markdown
# Configuration Reference
|
|
|
|
Sandcage uses a layered configuration system. Each layer overrides the previous one:
|
|
|
|
1. **Compiled defaults** — all fields unset
|
|
2. **Global config** (`~/.sandcage/config.toml`) — user-wide preferences (TOML format)
|
|
3. **Project config** (`.sandcage.yml`) — per-project settings, checked into version control (YAML format)
|
|
4. **Local config** (`.sandcage.local.yml`) — personal overrides, gitignored (YAML format)
|
|
|
|
Later layers win. Fields not set in a layer are inherited from the layer below.
|
|
|
|
---
|
|
|
|
## Fields
|
|
|
|
### env
|
|
|
|
Environment variables passed into the container at runtime.
|
|
|
|
- **Type:** Map of string keys to string values
|
|
- **Valid in:** Global, Project, Local
|
|
- **Behavior:** Passed as `-e KEY=VALUE` flags to `docker compose run`
|
|
|
|
```yaml
|
|
# .sandcage.yml
|
|
env:
|
|
RUST_LOG: debug
|
|
DATABASE_URL: "postgres://localhost:5432/dev"
|
|
```
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
[env]
|
|
EDITOR = "vim"
|
|
```
|
|
|
|
---
|
|
|
|
### packages
|
|
|
|
System packages to install in the container image (apt packages).
|
|
|
|
- **Type:** List of strings
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
packages:
|
|
- ripgrep
|
|
- fd-find
|
|
- postgresql-client
|
|
```
|
|
|
|
---
|
|
|
|
### toolchains
|
|
|
|
Language toolchains to install, keyed by language name and version.
|
|
|
|
- **Type:** Map of string keys to string values
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
toolchains:
|
|
rust: "1.78"
|
|
node: "20"
|
|
python: "3.12"
|
|
```
|
|
|
|
---
|
|
|
|
### mounts
|
|
|
|
Additional volume mounts passed to the container. Each entry must contain a `:` separator.
|
|
|
|
- **Type:** List of strings in Docker mount format (`<source>:<target>[:<options>]`)
|
|
- **Valid in:** Global, Project, Local
|
|
- **Behavior:** Tilde (`~`) in the source path is expanded to the host home directory. Entries without `:` are skipped with a warning.
|
|
|
|
```yaml
|
|
mounts:
|
|
- /data/models:/models:ro
|
|
- ~/.gitconfig:/home/agent/.gitconfig:ro
|
|
- /tmp/cache:/cache
|
|
```
|
|
|
|
---
|
|
|
|
### shell
|
|
|
|
Default shell inside the container.
|
|
|
|
- **Type:** String
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
shell: zsh
|
|
```
|
|
|
|
---
|
|
|
|
### justfile
|
|
|
|
Path to a justfile to make available in the container.
|
|
|
|
- **Type:** File path (string)
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
justfile: ./project.justfile
|
|
```
|
|
|
|
---
|
|
|
|
### dockerfiles
|
|
|
|
Custom Dockerfile overrides for image builds. Keyed by image short name. Values can be a path to a Dockerfile or a directory containing one.
|
|
|
|
- **Type:** Map of string keys to file paths
|
|
- **Valid in:** Global, Project (project overrides require the project to be in `trusted_projects`)
|
|
- **Behavior:** Project-level Dockerfile overrides are ignored unless the project directory is listed in `trusted_projects` in the global config.
|
|
|
|
```yaml
|
|
# .sandcage.yml (only applied if project is trusted)
|
|
dockerfiles:
|
|
sandcage: ./docker/Dockerfile.custom
|
|
```
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
[dockerfiles]
|
|
sandcage = "/home/user/my-dockerfiles/sandcage/"
|
|
```
|
|
|
|
---
|
|
|
|
### trusted_projects
|
|
|
|
List of project directories allowed to use Dockerfile overrides.
|
|
|
|
- **Type:** List of file paths
|
|
- **Valid in:** Global only (a project cannot self-trust)
|
|
- **Behavior:** Read exclusively from `~/.sandcage/config.toml`. Projects with `dockerfiles` set are ignored unless their path (or a parent) appears here.
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
trusted_projects = [
|
|
"/home/user/projects/my-trusted-project",
|
|
"/home/user/work",
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### container_workspace
|
|
|
|
Override the workspace path inside the container. Must be an absolute path (starting with `/`). Relative paths are ignored with a warning.
|
|
|
|
- **Type:** String (absolute path)
|
|
- **Valid in:** Global, Project, Local
|
|
- **Default:** `/workspace/<project-directory-name>` (derived from the host workspace folder name)
|
|
|
|
```yaml
|
|
container_workspace: /workspace/my-app
|
|
```
|
|
|
|
---
|
|
|
|
### agent_args
|
|
|
|
Default arguments passed to agents on every invocation. Keyed by service name. These are appended after the service name but before any extra CLI arguments.
|
|
|
|
- **Type:** Map of service name to list of strings
|
|
- **Valid in:** Global, Project, Local
|
|
- **Behavior:** Only the args for the invoked service are used. When running with `--shell`, agent_args are skipped entirely.
|
|
|
|
```yaml
|
|
agent_args:
|
|
claude:
|
|
- "--dangerously-skip-permissions"
|
|
codex:
|
|
- "--full-auto"
|
|
```
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
[agent_args]
|
|
claude = ["--dangerously-skip-permissions"]
|
|
```
|
|
|
|
---
|
|
|
|
### ssh_mode
|
|
|
|
Controls how SSH keys are made available inside the container.
|
|
|
|
- **Type:** String — one of `"volume"`, `"bind"`, or `"none"`
|
|
- **Valid in:** Global, Project, Local
|
|
- **Default:** No SSH mount (equivalent to `"none"`)
|
|
|
|
| Value | Behavior |
|
|
|----------|----------|
|
|
| `volume` | Mounts a named Docker volume (`sandcage-ssh`) at `/home/agent/.ssh` (read-only). Populate it with `sandcage setup ssh`. |
|
|
| `bind` | Bind-mounts `~/.ssh` from the host at `/home/agent/.ssh` (read-only). |
|
|
| `none` | No SSH directory is mounted. |
|
|
|
|
```yaml
|
|
ssh_mode: volume
|
|
```
|
|
|
|
When using `volume` mode, run `sandcage setup ssh --refresh` after changing keys on the host.
|
|
|
|
---
|
|
|
|
### ssh_keys
|
|
|
|
Declares which SSH keys to copy into the volume when using `sandcage setup ssh`. Each entry specifies a host and identity file.
|
|
|
|
- **Type:** List of objects with `host` (string) and `identity_file` (string) fields
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
ssh_keys:
|
|
- host: github.com
|
|
identity_file: ~/.ssh/id_ed25519
|
|
- host: gitea.internal
|
|
identity_file: ~/.ssh/work_gitea
|
|
```
|
|
|
|
---
|
|
|
|
### services
|
|
|
|
Override the enabled state of built-in services. Keyed by service name.
|
|
|
|
- **Type:** Map of service name to object with optional `enabled` (boolean) field
|
|
- **Valid in:** Global, Project, Local
|
|
- **Behavior:** Disabled services cannot be started with `sandcage <service>` and are excluded from generated compose files.
|
|
|
|
```yaml
|
|
services:
|
|
gemini:
|
|
enabled: false
|
|
codex:
|
|
enabled: false
|
|
```
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
[services.codex]
|
|
enabled = false
|
|
```
|
|
|
|
---
|
|
|
|
### default_services
|
|
|
|
Controls which services `sandcage build` prepares by default (when no service names are given on the CLI).
|
|
|
|
- **Type:** List of strings (service names)
|
|
- **Valid in:** Global, Project, Local
|
|
|
|
```yaml
|
|
default_services:
|
|
- claude
|
|
- shell
|
|
```
|
|
|
|
---
|
|
|
|
## Services
|
|
|
|
Sandcage ships with four built-in services, all enabled by default:
|
|
|
|
| Service | Description | Config directory |
|
|
|----------|-----------------------|------------------|
|
|
| `claude` | Claude Code agent | `.claude` |
|
|
| `codex` | Codex agent | `.codex` |
|
|
| `gemini` | Gemini CLI agent | `.gemini` |
|
|
| `shell` | Interactive zsh shell | (none) |
|
|
|
|
Agent services are installed on first run into the persistent home directory (`~/.sandcage/`). They auto-update on subsequent runs.
|
|
|
|
To disable a service you do not use:
|
|
|
|
```yaml
|
|
services:
|
|
codex:
|
|
enabled: false
|
|
gemini:
|
|
enabled: false
|
|
```
|
|
|
|
Disabled services are excluded from Docker compose generation and cannot be invoked.
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
### Minimal project config
|
|
|
|
```yaml
|
|
# .sandcage.yml
|
|
toolchains:
|
|
node: "20"
|
|
packages:
|
|
- ripgrep
|
|
```
|
|
|
|
### Full-featured project config
|
|
|
|
```yaml
|
|
# .sandcage.yml
|
|
env:
|
|
RUST_LOG: debug
|
|
NODE_ENV: development
|
|
|
|
packages:
|
|
- ripgrep
|
|
- fd-find
|
|
- postgresql-client
|
|
|
|
toolchains:
|
|
rust: stable
|
|
node: "20"
|
|
|
|
mounts:
|
|
- /data/models:/models:ro
|
|
|
|
shell: zsh
|
|
|
|
agent_args:
|
|
claude:
|
|
- "--dangerously-skip-permissions"
|
|
|
|
services:
|
|
gemini:
|
|
enabled: false
|
|
```
|
|
|
|
### Local overrides (gitignored)
|
|
|
|
```yaml
|
|
# .sandcage.local.yml
|
|
ssh_mode: volume
|
|
ssh_keys:
|
|
- host: github.com
|
|
identity_file: ~/.ssh/id_ed25519
|
|
|
|
env:
|
|
SECRET_API_KEY: "sk-local-dev-key"
|
|
|
|
mounts:
|
|
- ~/.aws:/home/agent/.aws:ro
|
|
```
|
|
|
|
### Global config
|
|
|
|
```toml
|
|
# ~/.sandcage/config.toml
|
|
shell = "zsh"
|
|
|
|
[env]
|
|
EDITOR = "vim"
|
|
|
|
[agent_args]
|
|
claude = ["--dangerously-skip-permissions"]
|
|
|
|
[services.codex]
|
|
enabled = false
|
|
|
|
trusted_projects = [
|
|
"/home/user/work/trusted-project",
|
|
]
|
|
```
|