Zapper

Configuration

Zapper projects are configured with a zap.yaml file in the project root. packages/cli/src/config/schemas.ts is the source of truth for supported fields.

Zapper projects are configured with a zap.yaml file in the project root. packages/cli/src/config/schemas.ts is the source of truth for supported fields.

Minimal Config

project: myapp

native:
  api:
    cmd: pnpm dev

Top-Level Fields

project: myapp
env: [.env.base, .env]
profiles:
  default:
    env_files: [.env.base, .env]
    services: "*"
  e2e:
    env_files: [.env.base, .env.e2e, .env]
    services: [api, worker, postgres]
    isolate: true
ports:
  - FRONTEND_PORT
  - BACKEND_PORT
init_task: seed
git_method: ssh
task_delimiters: ["{{", "}}"]

native:
  # process definitions

docker:
  # container definitions

volumes:
  # top-level Docker volume declarations

secrets:
  # top-level Docker secret declarations

tasks:
  # task definitions

homepage: http://localhost:3000
notes: "API: http://localhost:${API_PORT}"
links:
  - name: API Docs
    url: http://localhost:${API_PORT}/docs
  • project is required and is used as the native/Docker namespace.
  • env defines root environment file stacks.
  • env_files is accepted as a compatibility alias for root env.
  • profiles defines named runtime profiles with env files, service selection, and optional stack isolation.
  • ports lists uppercase env var names that Zapper assigns per instance.
  • init_task names a task to run after zap init.
  • git_method controls repo clone URLs: ssh, http, or cli.
  • task_delimiters changes task template delimiters.
  • native defines local supervisor-managed processes.
  • docker and containers define Docker-managed services.
  • volumes declares reusable Docker named volumes.
  • secrets declares local file/env-backed secrets for Docker services.
  • processes is accepted as a legacy process form.
  • tasks defines one-off commands.
  • homepage, links, and notes expose project metadata to CLI and tools.

Environment Files

Root env is a file stack:

env: [.env.base, .env]

Use profiles when you need named env file stacks or service subsets:

profiles:
  default:
    env_files: [.env.base, .env]
  proddata:
    env_files: [.env.base, .env.proddata, .env]
    services: "*"

Select a saved profile or use one for a single command:

zap profile set proddata
zap --profile proddata up
zap profile reset

Later files override earlier files. Root env_files remains a compatibility alias, but new configs should prefer env.

Profile service subsets automatically include depends_on dependencies. A profile can list a native app service and Zapper will still include the Docker services that app depends on.

See Environment Variable Management for detailed resolution rules.

Config Interpolation

String values inside service, task, metadata, build, watch, volume, and secret configuration support shell-style interpolation from the resolved root env stack, assigned ports, and the current process environment:

env: [.env]

docker:
  api:
    image: myapp/api:${API_TAG:-dev}
    ports:
      - "${API_PORT?API_PORT is required}:3000"

Supported forms:

  • ${VAR} expands to the variable value or an empty string.
  • ${VAR:-default} uses default when the variable is unset or empty.
  • ${VAR?message} fails config loading with message when the variable is unset or empty.
  • $$ emits a literal $.

Port Assignment

Define port variable names in config and initialize them with zap init:

project: myapp
ports:
  - FRONTEND_PORT
  - BACKEND_PORT
  - DB_PORT

Assigned ports have highest precedence over values from .env files. This supports multiple instances of the same project without port collisions.

Most config-backed commands initialize missing instance state automatically. Read-only commands such as zap status, zap ls, zap state, zap logs, and zap startup-log do not create or update .zap/state.json just by loading the project.

State writes are protected by a local lock and saved atomically. If .zap/state.json is malformed, commands that need to update state fail instead of replacing it with default state.

Interpolation uses assigned port values:

FRONTEND_PORT=3000
FRONTEND_URL=http://localhost:${FRONTEND_PORT}

After initialization, if FRONTEND_PORT is assigned 54321, FRONTEND_URL resolves to http://localhost:54321.

Init Task

Set init_task to run a task after initialization:

init_task: seed

tasks:
  seed:
    cmds:
      - pnpm db:seed

zap init performs normal initialization and then runs the task.

Git Cloning

For multi-repo projects, add repo to services and choose a clone method:

project: myapp
git_method: ssh

native:
  api:
    cmd: pnpm dev
    cwd: ./api
    repo: myorg/api-service
MethodURL FormatNotes
sshgit@github.com:myorg/repo.gitRequires SSH key
httphttps://github.com/myorg/repo.gitMay prompt for auth
cliUses gh repo cloneRequires GitHub CLI

Repos are cloned to the service cwd.

zap clone
zap clone api
zap clone api web

On this page