Skip to content

How to configure workspaces

This guide shows how to define and tune workspaces in jailoc's configuration file. For a full reference of every field and its type, see Configuration reference.

Config file location

jailoc stores its configuration at:

~/.config/jailoc/config.toml

The file is created automatically on first run with a default workspace already in place. You can edit it with any text editor.


Automatic workspace detection

Most commands accept an explicit --workspace flag. When omitted, jailoc selects the workspace automatically using this resolution order:

  1. Explicit --workspace flag — if set, use that workspace.
  2. Longest-prefix CWD match — compare the current working directory against every workspace's configured paths. The workspace whose path is the longest matching prefix wins. Equal-length matches break alphabetically.
  3. default fallback — if no path matches, the default workspace is used.

Given these two workspaces:

[workspaces.broad]
paths = ["/home/you/projects"]

[workspaces.specific]
paths = ["/home/you/projects/api"]

Running jailoc up from /home/you/projects/api/src selects specific (longer prefix match). Running from /home/you/projects/other selects broad.

jailoc add uses the path being added (not the raw CWD) for detection. If --workspace is set explicitly and the path being added is not under any of that workspace's configured paths, jailoc returns an error.


Define a workspace

Each workspace is a [workspaces.<name>] section. The only required field is paths.

[workspaces.default]
paths = ["/home/you/projects/myproject"]

The first entry in paths becomes the container's working directory. All paths are bind-mounted inside the container at their original absolute path, so /home/you/projects/myproject is accessible at the same path inside the container.

Note

~ is expanded to your home directory. Paths under system directories (/usr, /etc, /var, /home/agent, and similar) are rejected.


Define multiple workspaces

Add as many [workspaces.<name>] sections as you need:

[workspaces.api]
paths = ["/home/you/projects/api", "/home/you/projects/shared-libs"]

[workspaces.frontend]
paths = ["/home/you/projects/frontend"]

Each workspace gets its own isolated container environment.

Port allocation

jailoc assigns ports starting at 4096, sorted alphabetically by workspace name. Given the example above:

Workspace Port
api 4096
frontend 4097

Adding a workspace with a name that sorts earlier shifts the ports of those that follow.


Add multiple paths

Pass more than one directory to paths when an agent needs access to several repositories at once:

[workspaces.api]
paths = [
  "/home/you/projects/api",
  "/home/you/projects/shared-libs",
]

All listed paths are mounted read-write. The first is the working directory.


Allow specific hosts or networks

By default, containers cannot reach private networks. To grant access to specific services, use allowed_hosts or allowed_networks.

[workspaces.api]
paths = ["/home/you/projects/api"]
allowed_hosts = ["internal-registry.example.com"]
allowed_networks = ["10.10.5.0/24"]

See How to allow specific hosts or networks for step-by-step instructions.


Set a custom image

To use a pre-built image directly, set image in the workspace block:

[workspaces.myproject]
paths = ["/home/you/projects/myproject"]
image = "myregistry.example.com/myteam/myimage:v1.2.3"

To build from a custom Dockerfile instead, use dockerfile:

[workspaces.myproject]
paths = ["/home/you/projects/myproject"]
dockerfile = "https://git.example.com/team/dockerfiles/-/raw/main/myproject.Dockerfile"

See How to use a custom Docker image for all image customization options.


Set a build context

When building a workspace-specific image layer, jailoc uses the parent directory of the workspace dockerfile as the Docker build context by default. Override it with build_context:

[workspaces.myproject]
paths = ["/home/you/projects/myproject"]
build_context = "/home/you/projects/myproject/docker"

Set a connection mode

Control how jailoc connects to the running container:

[workspaces.myproject]
paths = ["/home/you/projects/myproject"]
mode = "remote"   # or "exec", or omit for auto-detect

See How to switch between remote and exec mode for details.


Set environment variables

Pass environment variables to the agent container using the env field:

[workspaces.api]
paths = ["/home/you/projects/api"]
env = ["MY_TOKEN=abc123", "LOG_LEVEL=debug"]

To load variables from a file, use env_file. The file must exist at config load time and follow Docker .env format (KEY=VALUE, # comments, quoted values):

[workspaces.api]
paths = ["/home/you/projects/api"]
env_file = ["~/.config/jailoc/api.env"]

Both can be combined. env entries override env_file entries with the same key.

To apply env vars to all workspaces, use the [defaults] section:

[defaults]
env = ["GOPRIVATE=*.example.com"]
env_file = ["~/.config/jailoc/shared.env"]

Note

Several keys are reserved and cannot be set: OPENCODE_LOG, OPENCODE_SERVER_PASSWORD, DOCKER_HOST, DOCKER_TLS_CERTDIR, DOCKER_CERT_PATH, DOCKER_TLS_VERIFY, SSH_AUTH_SOCK. Setting any of these causes a config validation error. OPENCODE_SERVER_PASSWORD is managed automatically by jailoc. Setting it in env or env_file is rejected, but it can be set as an OS environment variable to override the automatic cascade (useful for CI/CD).


Configure mounts

jailoc mounts several host directories into the container by default (OpenCode config, session transcripts, agent tooling). To add extra mounts or override the defaults, use the mounts field.

Add a host directory to the container:

[workspaces.my-project]
paths = ["/home/you/projects/my-project"]
mounts = ["~/.local/share/opencode:/home/agent/.local/share/opencode"]

Each entry follows host:container[:mode] format. The mode is ro (read-only) or rw (read-write, the default).

To remove a default mount, set an empty host source for that container path:

[workspaces.my-project]
paths = ["/home/you/projects/my-project"]
mounts = [":/home/agent/.opencode:ro"]

This removes the ~/.opencode mount for the my-project workspace.

Mounts set in [defaults] apply to all workspaces. Per-workspace mounts override defaults for the same container path:

[defaults]
mounts = ["~/.local/share/opencode:/home/agent/.local/share/opencode:ro"]

[workspaces.my-project]
paths = ["/home/you/projects/my-project"]
mounts = ["~/.local/share/opencode:/home/agent/.local/share/opencode:rw"]

Pass through OpenCode auth credentials

The container's ~/.local/share/opencode is a named Docker volume by default — your host auth.json is not available inside. To pass it through without replacing the entire volume, mount just the file:

[defaults]
mounts = ["~/.local/share/opencode/auth.json:/home/agent/.local/share/opencode/auth.json:ro"]

The bind mount overlays the single file on top of the named volume. The rest of the data directory (sessions, state) stays in the named Docker volume.

Share additional paths

To make additional host directories (e.g. shared AI instruction files consumed by both Copilot and OpenCode) available inside the container, mount the directory read-only:

[defaults]
mounts = ["~/.config/ai-instructions:/home/agent/.config/ai-instructions:ro"]

~ on the host side expands to your home directory. The container path must use an absolute path — the agent's home is /home/agent.

Note

Dangerous host paths are forbidden in mounts: /, /boot, /dev, /etc, /private, /proc, /sys, /run, /var, ~/.ssh, ~/.gnupg, ~/.aws. Container destinations under /home/agent/... are allowed; other system directories (/usr, /etc, /var, etc.) are forbidden.

See Configuration reference for the full mount format, merge semantics, and validation rules.


Forward SSH agent and Git config

To let the agent clone private repositories or push over SSH, enable SSH agent forwarding. Git configuration is mounted by default.

[defaults]
ssh_auth_sock = true

These can also be set per-workspace. See How to pass through SSH and Git config for details.


Set resource limits

Control the CPU and memory allocated to the opencode container with cpu and memory:

[defaults]
cpu = 2.0
memory = "4g"

[workspaces.heavy-agent]
cpu = 8.0
memory = "16g"

Both fields are optional. Workspace values override defaults; when neither is set, the fallback is 2.0 CPU cores and "4g" memory. The memory field accepts Docker memory format: a positive integer optionally followed by k, m, or g (e.g. 512m, 4g, 1024).