Schema Reference
Complete schema documentation for .shai/config.yaml.
Top-Level Keys
type
Required: Yes
Type: String
Value: shai-sandbox
Schema identifier for validation.
1type: shai-sandboxversion
Required: Yes
Type: Integer
Value: 1
Configuration schema version. Future releases may bump this.
1version: 1image
Required: Yes Type: String
Base container image to use for sandboxes.
1image: ghcr.io/colony-2/shai-megaSupports templates: Yes (${{ env.* }}, ${{ vars.* }})
Examples:
1# Official images
2image: ghcr.io/colony-2/shai-base
3image: ghcr.io/colony-2/shai-mega
4
5# Custom image
6image: ghcr.io/my-org/dev-env:latest
7
8# Using environment variable
9image: ${{ env.DEV_IMAGE }}user
Required: No
Default: shai
Type: String
Container user Shai switches to before running your command.
1user: developerSupports templates: Yes (${{ env.* }}, ${{ vars.* }})
CLI override:
1shai --user myuserworkspace
Required: No
Default: /src
Type: String
Absolute path of the repository inside the container.
1workspace: /workspaceSupports templates: Yes (${{ env.* }}, ${{ vars.* }})
/src. Only change this if you have a specific reason.resources
Required: Yes Type: Map of resource set definitions
Defines named resource sets. See Resource Sets below.
1resources:
2 base-allowlist:
3 http: [github.com]
4
5 my-tools:
6 vars: [...]
7 mounts: [...]apply
Required: Yes Type: List of apply rules
Ordered list that maps workspace paths to resource sets. See Apply Rules below.
1apply:
2 - path: ./
3 resources: [base-allowlist]
4
5 - path: frontend
6 resources: [npm-tools]Resource Sets
Resource sets are defined under the resources key:
1resources:
2 my-resource-set:
3 vars: [...]
4 mounts: [...]
5 calls: [...]
6 http: [...]
7 ports: [...]
8 root-commands: [...]
9 options: {...}vars
Type: List of environment variable mappings
Maps host environment variables to container environment variables.
Fields:
source: Name of host environment variable (required)target: Name of env var inside container (optional, defaults tosource)
Example:
1resources:
2 api-keys:
3 vars:
4 # When target is omitted, uses same name in container
5 - source: OPENAI_API_KEY
6 - source: DATABASE_URL
7
8 # Only specify target when you want a different name
9 - source: MY_HOST_API_KEY
10 target: API_KEYBehavior:
- Missing source env vars cause config loading to fail
- Values are never logged or exposed in config dumps
- If
targetis omitted, the variable keeps the same name in the container - Only specify
targetwhen you need to rename the variable
mounts
Type: List of bind mount specifications
Mounts host directories into the container.
Fields:
source: Absolute path on the host (supports templates)target: Absolute path in the container (supports templates)mode:ro(read-only) orrw(read-write)
Example:
1resources:
2 cache-mounts:
3 mounts:
4 # npm cache
5 - source: ${{ env.HOME }}/.npm
6 target: /home/${{ conf.TARGET_USER }}/.npm
7 mode: rw
8
9 # SSL certificates (read-only)
10 - source: /etc/ssl/certs
11 target: /etc/ssl/certs
12 mode: ro
13
14 # SSH keys (read-only)
15 - source: ${{ env.HOME }}/.ssh
16 target: /home/${{ conf.TARGET_USER }}/.ssh
17 mode: roBehavior:
- Non-existent source directories are skipped with a warning
- Useful for optional mounts that may not exist on all machines
- Use
${{ conf.TARGET_USER }}in target paths for user-specific directories
mode: ro for credentials and keys.calls
Type: List of remote call definitions
Defines host commands that can be invoked from inside the container.
Fields:
name: Unique identifier for the call (required)description: Human-readable description (required)command: Absolute path to host command (required)allowed-args: Regex pattern to validate arguments (optional)
Example:
1resources:
2 deployment:
3 calls:
4 - name: deploy-staging
5 description: Deploy to staging environment
6 command: /usr/local/bin/deploy.sh
7 allowed-args: '^--env=staging --region=us-\w+-\d+$'
8
9 - name: trigger-build
10 description: Trigger CI build
11 command: /usr/local/bin/trigger-build.sh
12 # No allowed-args means no arguments permittedBehavior:
- Call names must be unique within a single workspace path
- Arguments are validated against
allowed-argsregex before execution - Missing
allowed-argsmeans the call accepts no arguments - Calls are invoked with
shai-remote <name> [args]inside the container
allowed-args patterns to prevent command injection.See Selective Elevation for more details.
http
Type: List of hostnames
Defines which HTTP/HTTPS destinations are accessible from the container.
Example:
1resources:
2 web-access:
3 http:
4 - github.com
5 - api.openai.com
6 - npmjs.org
7 - pypi.orgBehavior:
- Only listed domains are accessible
- Subdomains are automatically included (e.g.,
github.comallowsapi.github.com) - All other HTTP/HTTPS traffic is blocked
- Implemented via iptables, dnsmasq, and tinyproxy
http:// or https:// prefixes. Just the hostname.ports
Type: List of host/port pairs
Allows access to specific TCP/UDP ports on specific hosts.
Fields:
host: Hostname or IP addressport: Port number
Example:
1resources:
2 ssh-access:
3 ports:
4 - host: github.com
5 port: 22
6
7 - host: gitlab.com
8 port: 22
9
10 - host: database.internal
11 port: 5432Use cases:
- SSH access to git servers
- Database connections
- Custom TCP services
root-commands
Type: List of shell commands
Commands to execute as root before switching to the target user.
Example:
1resources:
2 docker-in-docker:
3 root-commands:
4 - "systemctl start docker"
5 - "modprobe nbd"
6 options:
7 privileged: trueBehavior:
- Executed sequentially after container setup
- Run before user switch
- Any failure causes container to exit
- Only executed if container starts with root privileges
Use cases:
- Starting system services
- Loading kernel modules
- Configuring network interfaces
options
Type: Object with container-level options
Fields:
privileged: Boolean (default:false)
Example:
1resources:
2 gpu-access:
3 options:
4 privileged: trueBehavior:
privileged: trueruns the container in privileged mode- Reduces container isolation
- Required for Docker-in-Docker, GPU access, etc.
privileged: true sparingly! It significantly weakens security.Apply Rules
Apply rules are defined under the apply key:
1apply:
2 - path: <workspace-relative-path>
3 resources: [<resource-set-names>]
4 image: <optional-image-override>path
Required: Yes Type: String
Workspace-relative path that activates resource sets.
Examples:
1apply:
2 - path: ./ # Matches everything
3 - path: . # Same as ./
4 - path: frontend # Matches frontend/**/*
5 - path: backend/api # Matches backend/api/**/*Behavior:
- Paths are relative to workspace root
- Matches the path and all subdirectories
./or.matches the entire workspace
resources
Required: Yes Type: List of strings
Names of resource sets to apply when the path matches.
Example:
1apply:
2 - path: frontend
3 resources: [base-allowlist, npm-registries, playwright]Behavior:
- All listed resource sets are activated
- Resource sets must be defined in the
resourcessection - Call names within a path must be unique across all resource sets
image
Required: No Type: String
Optional container image override for this path.
Example:
1apply:
2 - path: ./
3 resources: [base-allowlist]
4 # Uses default image from top-level config
5
6 - path: infrastructure
7 resources: [deployment-tools]
8 image: ghcr.io/my-org/devops:latestBehavior:
- Overrides the top-level
imagekey for this path - More specific paths take precedence
- Root path (
.or./) cannot use image overrides - CLI
--imageflag takes ultimate precedence
Template Variables
The following template variables are available in config values:
Environment Variables
1${{ env.NAME }}References a host environment variable.
Example:
1image: ${{ env.DOCKER_IMAGE }}
2
3resources:
4 api-keys:
5 vars:
6 - source: OPENAI_API_KEYBehavior:
- Missing env vars cause config loading to fail
- Available in all string fields
User-Provided Variables
1${{ vars.NAME }}References a variable provided via --var flag.
Example:
1# Config
2image: ghcr.io/my-org/dev:${{ vars.TAG }}
3
4# CLI
5shai --var TAG=v1.2.3Behavior:
- Missing vars cause config loading to fail
- Useful for parameterizing configs
Configuration Variables
1${{ conf.TARGET_USER }}
2${{ conf.WORKSPACE }}References resolved configuration values.
Available:
TARGET_USER: The resolved target user (default:shai)WORKSPACE: The resolved workspace path (default:/src)
Example:
1resources:
2 cache:
3 mounts:
4 - source: ${{ env.HOME }}/.cache
5 target: /home/${{ conf.TARGET_USER }}/.cache
6 mode: rwLimitations:
- Cannot be used in the
userorworkspacefields themselves - Only available after those fields are resolved
Complete Schema
1type: shai-sandbox
2version: 1
3image: <image-name>
4
5# Optional
6user: <username>
7workspace: <path>
8
9resources:
10 <resource-set-name>:
11 vars:
12 - source: <VAR> # Uses same name in container
13 - source: <VAR2>
14 target: <NEW_NAME> # Renames in container
15
16 mounts:
17 - source: <host-path>
18 target: <container-path>
19 mode: ro|rw
20
21 calls:
22 - name: <call-name>
23 description: <description>
24 command: <host-command>
25 allowed-args: <regex>
26
27 http:
28 - <hostname>
29
30 ports:
31 - host: <hostname>
32 port: <port-number>
33
34 root-commands:
35 - <command>
36
37 options:
38 privileged: true|false
39
40apply:
41 - path: <workspace-path>
42 resources: [<resource-set-names>]
43 image: <optional-image-override>Validation
Shai validates the config when loading:
Checks:
- Required fields are present
typeisshai-sandboxversionis1- Resource set names are valid
- Apply rules reference existing resource sets
- Template variables are defined
- Paths are valid
Behavior:
- Invalid configs prevent Shai from starting
- Validation errors include helpful messages
- Use
shai --verboseto debug config issues
Next Steps
- See Template Expansion for more on using variables
- Browse Complete Example for an annotated full config
- Check Examples for real-world configurations