Skip to content

Latest commit

 

History

History
executable file
·
1000 lines (765 loc) · 20 KB

File metadata and controls

executable file
·
1000 lines (765 loc) · 20 KB

Zapper Reference

Complete reference for zap.yaml syntax and all CLI commands.


Table of Contents


Installation

npm install -g pm2 @maplab/zapper

For VS Code/Cursor, install the extension: felixsebastian.zapper-vscode


Project Configuration

Minimal config

project: myapp

native:
  api:
    cmd: pnpm dev

Full config structure

project: myapp                    # Required. Used as PM2/Docker namespace
env_files:                        # Load env vars from these files
  default: [.env.base, .env]
  prod_dbs: [.env.base, .env.prod-dbs]
ports:                            # Port names to assign random values
  - FRONTEND_PORT
  - BACKEND_PORT
git_method: ssh                   # ssh | http | cli (for repo cloning)

native:
  # ... process definitions

docker:
  # ... container definitions

tasks:
  # ... task definitions

homepage: http://localhost:3000   # Optional default URL for `zap launch`

links:
  # ... quick reference links

CLI Commands

Global Options

Available with any command:

--config <file>    # Use a specific config file (default: zap.yaml)
-v, --verbose      # Increase logging verbosity
-q, --quiet        # Reduce logging output
-d, --debug        # Enable debug logging

Examples:

zap --config prod.yaml up
zap --config staging.yaml status
zap --debug restart
zap --verbose --config custom.yaml task build

Starting and stopping

zap up                      # Start all services
zap up backend              # Start one service (and its dependencies)
zap up api worker db        # Start multiple services
zap up --json               # Output command result as JSON
zap down                    # Stop all services
zap down backend            # Stop one service
zap down api worker db      # Stop multiple services
zap down backend --json     # Output command result as JSON
zap restart                 # Restart all services
zap restart api             # Restart one service
zap restart api worker db   # Restart multiple services
zap r api worker            # Short alias for: zap restart api worker

Status and logs

zap status                  # Show status of all services
zap status api db           # Show status for specific services
zap logs api                # Follow logs for one service
zap logs api worker --no-follow  # Show logs for multiple services and exit

When passing multiple services to zap logs, use --no-follow.

Tasks

zap task                           # List all tasks
zap task <name>                    # Run a task
zap run <name>                     # Alias for: zap task <name>
zap task seed
zap task build --target=prod       # Run with named parameters
zap task test -- --coverage        # Run with pass-through args
zap task build --list-params       # Show task parameters as JSON

Utilities

zap reset                   # Stop all services and delete .zap folder
zap reset --json            # Output command result as JSON
zap kill                    # Kill all PM2 processes and containers for current project, across all instances
zap kill my-old-project     # Kill all PM2 processes and containers for a specific project, across all instances
zap kill --force            # Skip the interactive confirmation
zap kill --json             # Output kill result as JSON
zap clone                   # Clone all repos defined in config
zap clone api               # Clone one repo
zap clone api web           # Clone multiple repos
zap clone --json            # Output command result as JSON
zap assign                  # Assign random ports to ports defined in config
zap assign --json           # Output as JSON
zap launch                  # Open homepage (if configured)
zap launch "API Docs"       # Open a configured link by name
zap launch "API Docs" --json # Output command result as JSON
zap open                    # Alias for: zap launch
zap o "API Docs"            # Short alias for: zap launch "API Docs"
zap isolate --json          # Output isolation result as JSON

Profiles

zap profile dev             # Enable a profile
zap profile --disable       # Disable active profile
zap profile dev --json      # Output profile action result as JSON

Environments

zap env --list                    # List available environment sets
zap env prod_dbs                  # Switch env file set
zap env --disable                 # Reset to default env set
zap env prod_dbs --json           # Output environment action result as JSON

Aliases:

zap environment --list
zap envset prod_dbs

JSON Output

Most non-streaming commands support --json and will print machine-readable JSON to stdout. Examples: up, down, restart, clone, reset, kill, status, task (list/params), profile, env, state, config, launch, isolate, and git subcommands.

Streaming commands keep stream output and are not JSON-encoded:

zap logs <service> [more-services...] [--no-follow]
zap task <name>

zap kill <project> does not require a local zap.yaml; it targets resources by prefix (zap.<project>.*).


Native Processes

Native processes run via PM2 on your local machine.

Basic process

native:
  api:
    cmd: pnpm dev

All options

native:
  api:
    cmd: pnpm dev              # Required. Command to run
    cwd: ./backend             # Working directory (relative to zap.yaml)
    env:                       # Env vars to pass (whitelist)
      - PORT
      - DATABASE_URL
      - DEBUG=true             # Inline override
    depends_on: [postgres]     # Start these first
    profiles: [dev, test]      # Only start when profile matches
    repo: myorg/api-repo       # Git repo (for zap clone)
    healthcheck: 10            # Seconds to wait before considering "up"
    # OR
    healthcheck: http://localhost:3000/health  # URL to poll for readiness

Working directory

native:
  frontend:
    cmd: pnpm dev
    cwd: ./packages/frontend   # Relative to project root

Multiple processes

native:
  api:
    cmd: pnpm dev
    cwd: ./api

  worker:
    cmd: pnpm worker
    cwd: ./api

  frontend:
    cmd: pnpm dev
    cwd: ./web

Docker Services

Containers managed via Docker CLI.

Basic container

docker:
  redis:
    image: redis:latest
    ports:
      - 6379:6379

All options

docker:
  postgres:
    image: postgres:15         # Required. Docker image
    ports:                     # Port mappings (host:container)
      - 5432:5432
    env:                       # Env vars for container
      - POSTGRES_DB=myapp
      - POSTGRES_PASSWORD=dev
    volumes:                   # Volume mounts
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    depends_on: [other]        # Start dependencies first
    profiles: [dev]            # Profile filtering
    healthcheck: 10            # Seconds to wait before considering "up"
    # OR
    healthcheck: http://localhost:5432  # URL to poll for readiness

Common database setups

PostgreSQL

docker:
  postgres:
    image: postgres:15
    ports:
      - 5432:5432
    env:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data

MongoDB

docker:
  mongodb:
    image: mongo:7
    ports:
      - 27017:27017
    volumes:
      - mongodb-data:/data/db

Redis

docker:
  redis:
    image: redis:7-alpine
    ports:
      - 6379:6379

MySQL

docker:
  mysql:
    image: mysql:8
    ports:
      - 3306:3306
    env:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=myapp
    volumes:
      - mysql-data:/var/lib/mysql

Environment Variables

Zapper uses a whitelist approach: define where vars come from, then each service declares which ones it needs.

Loading from files

env_files: [.env]                    # Single file
env_files: [.env.base, .env]         # Multiple files (later files override)

Environment sets (recommended)

You can define multiple env file sets and switch between them with zap env <name>. The default set is optional; if omitted and no environment is active, no env files are loaded.

env_files:
  default: [.env.base, .env]
  prod_dbs: [.env.base, .env.prod-dbs]

Legacy array syntax is still supported:

env_files: [.env.base, .env]

Recommended pattern

Split into two files:

  • .env.base — non-secrets (ports, URLs), committed to git
  • .env — secrets (API keys, passwords), gitignored
env_files: [.env.base, .env]

Whitelisting per service

Each service only receives the vars it explicitly lists:

native:
  backend:
    cmd: pnpm dev
    env:
      - PORT
      - DATABASE_URL
      - JWT_SECRET

  frontend:
    cmd: pnpm dev
    env:
      - VITE_API_URL

Backend sees PORT, DATABASE_URL, JWT_SECRET. Frontend only sees VITE_API_URL. No leakage.

Inline values

Override or hardcode values inline:

native:
  api:
    cmd: pnpm dev
    env:
      - PORT=3000                    # Hardcoded value
      - DATABASE_URL                  # From env_files
      - DEBUG=true                    # Override

Port assignment

Define port variable names in your config and assign random values with zap assign:

project: myapp
ports:
  - FRONTEND_PORT
  - BACKEND_PORT
  - DB_PORT

env_files: [.env]

native:
  frontend:
    cmd: pnpm dev
    env:
      - FRONTEND_PORT
  backend:
    cmd: pnpm dev
    env:
      - BACKEND_PORT
      - DB_PORT

Then run:

zap assign              # Assigns random ports to .zap/ports.json

The assigned ports have highest precedence - they override values from any .env files. This is useful for:

  • Avoiding port conflicts when running multiple instances
  • Dynamic port assignment in development
  • Sharing configurations with different port needs

Interpolation works with assigned ports:

# .env
FRONTEND_PORT=3000
FRONTEND_URL=http://localhost:${FRONTEND_PORT}

After zap assign:

# If FRONTEND_PORT was assigned 54321
FRONTEND_URL will be http://localhost:54321

Docker env vars

Docker services can use env vars too:

docker:
  postgres:
    image: postgres:15
    env:
      - POSTGRES_PASSWORD=dev        # Hardcoded
      - POSTGRES_DB                   # From env_files

Inspecting resolved env vars

zap env --service api              # Show resolved env vars for a service
zap env api                        # Works if no environment set named 'api'

Instances

Instances let you run multiple copies of the same project from Git worktrees without process/container name collisions.

zap isolate                           # Create random 6-char local instance ID in .zap/instance.json
zap isolate my-feature-123            # Provide an explicit instance ID
zap up                                # Start with instance-aware names

If you are in a worktree without isolation, Zapper prints a warning for non-isolate commands and still runs commands. See Instances for full details.


Tasks

One-off commands that can use your env vars and accept parameters.

Basic task

tasks:
  seed:
    cmds:
      - pnpm db:seed

All options

tasks:
  seed:
    desc: Seed the database          # Description (shown in help)
    cwd: ./backend                   # Working directory
    env:                             # Env vars to pass
      - DATABASE_URL
    params:                          # Named parameters
      - name: count
        default: "10"
        desc: Number of records
      - name: env
        required: true
        desc: Target environment
    cmds:                            # Commands to run (in order)
      - pnpm db:migrate
      - 'pnpm db:seed --count={{count}}'

Running tasks

zap task seed
zap task lint

Parameters

Tasks can accept named parameters and pass-through arguments.

Named parameters

Define parameters with defaults and validation:

tasks:
  build:
    desc: Build for target environment
    params:
      - name: target
        default: development
        desc: Build target
      - name: minify
        desc: Enable minification
    cmds:
      - 'echo "Building for {{target}}"'
      - 'npm run build -- --env={{target}}'

Run with parameters:

zap task build --target=production --minify=true

Required parameters

Mark parameters as required (task fails if not provided):

tasks:
  deploy:
    params:
      - name: env
        required: true
        desc: Deployment environment
    cmds:
      - 'deploy.sh {{env}}'
zap task deploy --env=staging    # Works
zap task deploy                  # Error: Required parameter 'env' not provided

Pass-through arguments (REST)

Use {{REST}} to forward extra CLI arguments:

tasks:
  test:
    desc: Run tests with optional args
    cmds:
      - 'pnpm vitest {{REST}}'

Everything after -- is passed through:

zap task test -- --coverage src/
# Runs: pnpm vitest --coverage src/

Custom delimiters

If your commands contain {{ and }}, use custom delimiters:

project: myapp
task_delimiters: ["<<", ">>"]

tasks:
  build:
    cmds:
      - 'echo "Building <<target>>"'

Listing task parameters

For tooling integration (VS Code extension), get parameter info as JSON:

zap task build --list-params

Output:

{
  "name": "build",
  "params": [
    { "name": "target", "default": "development", "required": false, "desc": "Build target" }
  ],
  "acceptsRest": false
}

Common task patterns

Database operations

tasks:
  db:migrate:
    desc: Run database migrations
    env: [DATABASE_URL]
    cmds:
      - pnpm prisma migrate dev

  db:seed:
    desc: Seed the database
    env: [DATABASE_URL]
    cmds:
      - pnpm prisma db seed

  db:reset:
    desc: Reset and reseed database
    env: [DATABASE_URL]
    cmds:
      - pnpm prisma migrate reset --force

Code quality

tasks:
  lint:
    cmds:
      - pnpm eslint . --fix
      - pnpm prettier --write .

  typecheck:
    cmds:
      - pnpm tsc --noEmit

  test:
    env: [DATABASE_URL]
    cmds:
      - pnpm vitest run

  checks:
    desc: Run all checks before committing
    cmds:
      - pnpm eslint .
      - pnpm tsc --noEmit
      - pnpm vitest run

Dependencies

Control startup order with depends_on.

Basic dependency

docker:
  postgres:
    image: postgres:15
    ports:
      - 5432:5432

native:
  api:
    cmd: pnpm dev
    depends_on: [postgres]     # Postgres starts first

Dependency chain

docker:
  postgres:
    image: postgres:15

  redis:
    image: redis:7

native:
  api:
    cmd: pnpm dev
    depends_on: [postgres, redis]

  worker:
    cmd: pnpm worker
    depends_on: [api]          # API (and its deps) start first

  frontend:
    cmd: pnpm dev
    depends_on: [api]

When you run zap up frontend, Zapper starts: postgres → redis → api → frontend.


Profiles

Run different subsets of services.

Defining profiles

native:
  api:
    cmd: pnpm dev
    profiles: [dev, test]

  api-prod:
    cmd: pnpm start
    profiles: [prod]

  frontend:
    cmd: pnpm dev
    profiles: [dev]

docker:
  postgres:
    image: postgres:15
    profiles: [dev, test]

  postgres-test:
    image: postgres:15
    env:
      - POSTGRES_DB=test
    profiles: [test]

Using profiles

zap up                     # Starts only services with no `profiles` field
zap profile dev            # Enables 'dev' profile and starts matching services
zap restart                # Restarts all services using active profile filtering
zap profile --disable      # Disables active profile

Default behavior

Services without a profiles field run regardless of profile state. Services with a profiles field run only when an active profile matches.


Links

Quick reference links for your project. These are for your own reference and can be displayed by tooling.

You can also set a top-level homepage URL as the default target for zap launch with no arguments.

Homepage

homepage: http://localhost:3000

Basic usage

links:
  - name: API Docs
    url: https://api.example.com/docs
  - name: Staging
    url: https://staging.example.com
  - name: Figma
    url: https://figma.com/file/abc123

Environment variable interpolation

Link URLs support ${VAR} syntax to reference environment variables from your env_files:

env_files: [.env]

links:
  - name: API
    url: http://localhost:${API_PORT}
  - name: Frontend
    url: http://localhost:${FRONTEND_PORT}

Opening links

zap launch                     # Open homepage
zap launch "API Docs"          # Open by link name (quote if spaces)
zap open                       # Alias for: zap launch
zap o "API Docs"               # Short alias for: zap launch "API Docs"

Properties

Property Required Description
name Yes Display name (max 100 characters)
url Yes URL (supports ${VAR} interpolation)

Git Cloning

For multi-repo setups, Zapper can clone repositories.

Configuration

project: myapp
git_method: ssh              # ssh | http | cli

native:
  api:
    cmd: pnpm dev
    cwd: ./api
    repo: myorg/api-service

  web:
    cmd: pnpm dev
    cwd: ./web
    repo: myorg/web-app

Git methods

Method URL Format Notes
ssh git@github.com:myorg/repo.git Requires SSH key
http https://github.com/myorg/repo.git May prompt for auth
cli Uses gh repo clone Requires GitHub CLI

Cloning

zap clone                  # Clone all repos
zap clone api              # Clone one repo
zap clone api web          # Clone multiple repos

Repos are cloned to the path specified in cwd.


Full Example

A complete example for a typical full-stack app:

project: myapp
env_files: [.env.base, .env]
git_method: ssh

native:
  api:
    cmd: pnpm dev
    cwd: ./api
    repo: myorg/api
    env:
      - PORT
      - DATABASE_URL
      - REDIS_URL
      - JWT_SECRET
    depends_on: [postgres, redis]

  worker:
    cmd: pnpm worker
    cwd: ./api
    env:
      - DATABASE_URL
      - REDIS_URL
    depends_on: [api]

  frontend:
    cmd: pnpm dev
    cwd: ./web
    repo: myorg/web
    env:
      - VITE_API_URL
    depends_on: [api]

docker:
  postgres:
    image: postgres:15
    ports:
      - 5432:5432
    env:
      - POSTGRES_DB=myapp
      - POSTGRES_PASSWORD=dev
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    ports:
      - 6379:6379

tasks:
  db:migrate:
    desc: Run migrations
    env: [DATABASE_URL]
    cmds:
      - pnpm --filter api prisma migrate dev

  db:seed:
    desc: Seed database
    env: [DATABASE_URL]
    params:
      - name: count
        default: "10"
        desc: Number of seed records
    cmds:
      - 'pnpm --filter api prisma db seed --count={{count}}'

  test:
    desc: Run tests with optional args
    env: [DATABASE_URL]
    cmds:
      - 'pnpm vitest {{REST}}'

  deploy:
    desc: Deploy to environment
    params:
      - name: env
        required: true
        desc: Target environment (staging, production)
    cmds:
      - 'deploy.sh {{env}}'

  lint:
    cmds:
      - pnpm eslint . --fix
      - pnpm tsc --noEmit

homepage: http://localhost:5173

links:
  - name: API Docs
    url: http://localhost:3000/docs
  - name: Storybook
    url: http://localhost:6006