Project and Setup
The [coast] section is the only required section in a Coastfile. It identifies the project and configures how the Coast container is created. The optional [coast.setup] subsection lets you install packages and run commands inside the container at build time.
[coast]
name (required)
A unique identifier for the project. Used in container names, volume names, state tracking, and CLI output.
[coast]
name = "my-app"
compose
Path to a Docker Compose file. Relative paths are resolved against the project root (the directory containing the Coastfile, or root if set).
[coast]
name = "my-app"
compose = "./docker-compose.yml"
[coast]
name = "my-app"
compose = "./infra/docker-compose.yml"
If omitted, the Coast container starts without running docker compose up. You can either use bare services or interact with the container directly via coast exec.
You cannot set both compose and [services] in the same Coastfile.
runtime
Which container runtime to use. Defaults to "dind" (Docker-in-Docker).
"dind"— Docker-in-Docker with--privileged. The only production-tested runtime. See Runtimes and Services."sysbox"— Uses the Sysbox runtime instead of privileged mode. Requires Sysbox to be installed."podman"— Uses Podman as the inner container runtime.
[coast]
name = "my-app"
runtime = "dind"
root
Overrides the project root directory. By default, the project root is the directory containing the Coastfile. A relative path is resolved against the Coastfile's directory; an absolute path is used as-is.
[coast]
name = "my-app"
root = "../my-project"
This is uncommon. Most projects keep the Coastfile at the actual project root.
worktree_dir
Directories where git worktrees live. Accepts a single string or an array of strings. Defaults to ".worktrees".
# Single directory
worktree_dir = ".worktrees"
# Multiple directories, including an external one
worktree_dir = [".worktrees", ".claude/worktrees", "~/.codex/worktrees"]
Relative paths are resolved against the project root. Paths starting with ~/ or / are treated as external directories — Coast adds a separate bind mount so the container can access them. This is how you integrate with tools like Codex that create worktrees outside the project root.
At runtime, Coast auto-detects the worktree directory from existing git worktrees (via git worktree list) and prefers that over the configured default when all worktrees agree on a single directory.
See Worktree Directories for the full reference, including external directory behavior, project filtering, and examples.
default_worktree_dir
Which directory to use when creating new worktrees. Defaults to the first entry in worktree_dir. Only relevant when worktree_dir is an array.
[coast]
name = "my-app"
worktree_dir = [".worktrees", "~/.codex/worktrees"]
default_worktree_dir = ".worktrees"
autostart
Whether to automatically run docker compose up (or start bare services) when a Coast instance is created with coast run. Defaults to true.
Set to false when you want the container running but want to start services manually — useful for test-runner variants where you invoke tests on demand.
[coast]
name = "my-app"
extends = "Coastfile"
autostart = false
primary_port
Names a port from the [ports] section to use for quick-links and subdomain routing. The value must match a key defined in [ports].
[coast]
name = "my-app"
primary_port = "web"
[ports]
web = 3000
api = 8080
See Primary Port and DNS for how this enables subdomain routing and URL templates.
[coast.setup]
Customizes the Coast container itself — installing tools, running build steps, and materializing config files. Everything in [coast.setup] runs inside the DinD container (not inside your compose services).
packages
APK packages to install. These are Alpine Linux packages since the base DinD image is Alpine-based.
[coast.setup]
packages = ["nodejs", "npm", "git", "curl"]
run
Shell commands executed in order during build. Use these for installing tools that aren't available as APK packages.
[coast.setup]
packages = ["nodejs", "npm", "python3", "wget", "bash", "ca-certificates"]
run = [
"ARCH=$(uname -m | sed 's/aarch64/arm64/' | sed 's/x86_64/amd64/') && wget -qO /tmp/go.tar.gz https://go.dev/dl/go1.24.1.linux-${ARCH}.tar.gz && tar -C /usr/local -xzf /tmp/go.tar.gz && rm /tmp/go.tar.gz",
"GOBIN=/usr/local/bin go install github.com/air-verse/air@v1.61.7",
]
[[coast.setup.files]]
Files to create inside the container. Each entry has a path (required, must be absolute), content (required), and optional mode (3-4 digit octal string).
[coast.setup]
packages = ["nodejs", "npm"]
run = ["mkdir -p /app/config"]
[[coast.setup.files]]
path = "/app/config/dev.json"
content = '''
{
"logLevel": "debug",
"featureFlags": { "newDashboard": true }
}
'''
mode = "0644"
Validation rules for file entries:
pathmust be absolute (start with/)pathmust not contain..componentspathmust not end with/modemust be a 3 or 4 digit octal string (e.g."600","0644")
Full example
A Coast container set up for Go and Node.js development:
[coast]
name = "my-fullstack-app"
compose = "./docker-compose.yml"
runtime = "dind"
worktree_dir = [".worktrees", "~/.codex/worktrees"]
primary_port = "web"
[coast.setup]
packages = ["nodejs", "npm", "python3", "make", "curl", "git", "bash", "ca-certificates", "wget", "gcc", "musl-dev"]
run = [
"ARCH=$(uname -m | sed 's/aarch64/arm64/' | sed 's/x86_64/amd64/') && wget -qO /tmp/go.tar.gz https://go.dev/dl/go1.24.1.linux-${ARCH}.tar.gz && tar -C /usr/local -xzf /tmp/go.tar.gz && rm /tmp/go.tar.gz && ln -s /usr/local/go/bin/go /usr/local/bin/go",
"GOBIN=/usr/local/bin go install github.com/air-verse/air@v1.61.7",
"pip3 install --break-system-packages pgcli",
]
[[coast.setup.files]]
path = "/app/config/dev.json"
content = '''
{
"logLevel": "debug",
"featureFlags": { "newDashboard": true }
}
'''
mode = "0644"