Quick Start
Want a guided walkthrough? The Learn Launchfile course takes you step by step from zero to multi-component apps.
A Launchfile describes what your application needs to run. Create a file called Launchfile (no extension) in your project root:
Minimal example
Three fields and a start command — the simplest possible Launchfile:
name: my-app
runtime: node
commands:
start: "node server.js"Adding a database
Declare what your app needs. The platform figures out how to provide it:
name: my-app
runtime: node
requires:
- type: postgres
set_env:
DATABASE_URL: $url
commands:
start: "node server.js"
health: /healthThe $url expression is resolved at deploy time — the platform provisions Postgres and injects the connection URL into your environment.
Validate with the SDK
Use the TypeScript SDK to parse and validate your Launchfile:
import { readLaunch, validateLaunch } from "launchfile";
const app = readLaunch(`
name: my-app
runtime: node
requires: [postgres]
commands:
start: "node server.js"
`);
const result = validateLaunch(app);
if (!result.success) {
console.error(result.error.issues);
}Run it
Launchfile has two modes: Docker for quick, self-contained runs, and native macOS for local development.
Docker (default)
Run any catalog app with one command — no source code needed:
npx launchfile up ghost
# Pulls Ghost + MySQL, wires everything, starts at http://localhost:2368Ghost starts with MySQL, health checks, and persistent storage — all from pre-built images. When you're done:
npx launchfile down --destroy
# Removes all containers and volumes — 100% cleanNative macOS (for development)
For local development, clone a repo and run natively — databases via Homebrew, runtimes via version managers, no containers:
git clone https://github.com/TryGhost/Ghost
cd Ghost
npx launchfile up --native
# Installs Node via fnm, MySQL via Homebrew, runs Ghost from sourceNow try it with your own app — create a Launchfile in your project root, then run npx launchfile up.
A flag the CLI does not know is refused before anything starts: launchfile up --storagex vol=/srv/vol exits 1 with no such flag --storagex — did you mean --storage?, so a typo never launches with defaults.
When a launch fails
A failed up writes a structured record of what went wrong. Ask for it afterwards — from any directory, in a new shell:
npx launchfile diagnose
# my-app failed during release slot
# phase: release
# disposition: failed the deploy — the release stage aborted it (D-48)
# exit code: 1The record names the lifecycle slot that failed — prepare, release, run, bootstrap — not the command name, because the same command fills different slots in different modes. Alongside it is the disposition: whether the failure killed the deploy, killed the invocation, or was only reported.
The record also carries the failing command, the exit code, and the log tails. Secrets are masked when the record is written, and it stores the names of your environment variables, never their values.
npx launchfile diagnose --json | jq .phase
# "release"--json writes the raw record to stdout and nothing else, so it pipes cleanly. Records live at ~/.launchfile/errors/, one per app, and are cleared by the next successful up.
One failure has its own phase: health. A component that never becomes healthy fails the launch, so up exits non-zero and names the components that never passed. Their containers stay running so you can look at them, and the deployment is listed as unhealthy — launchfile status, launchfile logs, and launchfile down all reach it. A component that declares no health check counts as healthy once its container is running.
Next steps
- Browse the app catalog for >50 ready-to-launch apps
- Browse real-world examples from minimal to multi-component
- Read the full specification for every field and expression
- Explore the SDK reference for parsing, validation, and serialization