vandor.
CLI Reference

vandor run / vandor dev

Run your Vandor application in production or development mode

Runtime Commands

Vandor provides four runtime commands for starting your application. Two are for production use, and two are for development with hot reload.

Synopsis

# Production
vandor run:app [flags]
vandor run:worker [flags]

# Development (hot reload)
vandor dev:app [flags]
vandor dev:worker [flags]

Overview

Vandor projects are organized around two types of runners:

  • App runner -- Your main application process. Typically this is an HTTP server that handles incoming requests.
  • Worker runner -- A background worker process. This handles async tasks, scheduled jobs, event consumers, and other non-HTTP workloads.

You can run either or both, depending on your project. A simple REST API might only need run:app, while a full-featured system might run both an app and a worker.

vandor run:app

Start the app runner in production mode.

vandor run:app

This builds and runs your application using the compiled binary at cmd/app/main.go. It loads configuration from config/base.yaml merged with config/runner/app.yaml.

When to use

  • Deploying to production
  • Running in Docker containers
  • Performing integration tests against a production-like build
  • Running behind a process manager (systemd, supervisord, etc.)

vandor run:worker

Start the worker runner in production mode.

vandor run:worker

This builds and runs the worker binary at cmd/worker/main.go. It loads configuration from config/base.yaml merged with config/runner/worker.yaml.

When to use

  • Running background job processors in production
  • Running scheduled task executors
  • Running event consumers or stream processors

vandor dev:app

Start the app runner in development mode with hot reload.

vandor dev:app

This watches your source files for changes and automatically rebuilds and restarts the app process. You get fast feedback without manually stopping and restarting the server every time you make a change.

What hot reload does

  1. Watches .go files, configuration files, and templates for changes
  2. When a change is detected, rebuilds the binary
  3. Gracefully stops the old process
  4. Starts the new process
  5. All of this happens in a few seconds

When to use

  • Day-to-day development
  • Testing API endpoints locally
  • Debugging with live code changes

vandor dev:worker

Start the worker runner in development mode with hot reload.

vandor dev:worker

Same as dev:app, but for the worker process. It watches for file changes and automatically rebuilds and restarts the worker.

When to use

  • Developing background job handlers
  • Testing scheduled tasks locally
  • Debugging event consumers

Configuration Loading

Both app and worker runners load configuration in layers:

config/
  base.yaml              Shared configuration (applied to all runners)
  runner/
    app.yaml             App-specific overrides
    worker.yaml          Worker-specific overrides

How it works:

  1. base.yaml is loaded first. This contains settings shared across all runners -- things like database connection strings, logging levels, and external service URLs.
  2. The runner-specific file (app.yaml or worker.yaml) is loaded on top, overriding any values from base.yaml.

Example: base.yaml

app:
  name: my-project
  env: development

database:
  host: localhost
  port: 5432
  name: mydb

logger:
  level: info
  format: json

Example: runner/app.yaml

http:
  port: 8080
  host: 0.0.0.0
  read_timeout: 30s
  write_timeout: 30s

Example: runner/worker.yaml

worker:
  concurrency: 10
  queues:
    critical: 6
    default: 3
    low: 1

No Task runner, no Air. Vandor handles the build-watch-restart cycle internally. You do not need to install or configure Task, Air, or any other external tool. Just run vandor dev:app and start coding.

Running Both App and Worker

In many projects, you will want to run the app and worker side by side during development. Open two terminal windows (or use tmux/screen):

Terminal 1:

vandor dev:app

Terminal 2:

vandor dev:worker

Both processes will independently watch for file changes and rebuild as needed.

Production Deployment

For production, you typically build the binary separately and run it directly:

# Build
go build -o ./bin/app ./cmd/app
go build -o ./bin/worker ./cmd/worker

# Run (no vandor CLI needed at runtime)
./bin/app
./bin/worker

Runtime independence. In production, your application does not need the vandor binary at all. The vandor run:app and vandor run:worker commands are convenience wrappers. Your compiled Go binaries are fully self-contained.

However, vandor run:app and vandor run:worker are available if you prefer them for simpler deployment setups or local production testing.

Docker Example

# Build stage
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /bin/app ./cmd/app

# Runtime stage
FROM alpine:3.19
COPY --from=builder /bin/app /app
COPY config/ /config/
CMD ["/app"]

Notice that the Dockerfile does not install or use the vandor CLI. The built binary runs independently.

Troubleshooting

Port already in use

Error: listen tcp :8080: address already in use

Another process is using the port. Either stop that process or change the port in config/runner/app.yaml.

Hot reload not detecting changes

Make sure you are editing files inside the project directory. Changes to files outside the project root are not watched.

Worker not processing tasks

Check that:

  1. Your task queue (Redis for Asynq, etc.) is running
  2. The worker configuration in config/runner/worker.yaml is correct
  3. Queue names match between the app (enqueuing) and worker (processing)