forge docs

From npm i to a live URL.

Everything Forge does is a command. This page is the whole surface — install, link, ship, then the flags you'll reach for when defaults stop being enough. Start with forge --help; it prints the same tree.

Forge CLI documentation

Quickstart

Three commands, about sixty seconds. The CLI is a single ~6 MB binary with no daemon and no background agent — install it, and everything else happens over stdout.

Install the CLI

Via npm, Homebrew, or the curl installer — all three land the same binary on your PATH.

$ npm i -g forge
# or: brew install forge-dev/tap/forge
# or: curl -fsSL https://get.forge.run | sh

$ forge --version
forge 3.2.0 (darwin-arm64)

Ship it

Build, upload, provision, route — one command, one URL. Traffic only shifts after the healthcheck passes, so a failed deploy leaves production untouched.

$ forge deploy
→ resolving project… api-service (node 22)
✓ build complete in 2.4s · 142 modules
↑ uploaded 3.1 MB in 1.8s
✓ deployed https://api-service.forge.run · 9.2s
note: the first deploy of a project provisions the runtime and takes longer than the 9.2s benchmark figure — that number is a cold rebuild of an already-provisioned service. Warm deploys with a primed cache land around 3.9s.

Command index

The full top-level tree. Every command accepts --json for machine-readable output and --project to override the linked project.

forge init

Detect the runtime and link the working directory to a project.

forge deploy

Build, upload and route a new immutable version to production.

forge preview

Deploy the current branch to an isolated preview URL.

forge rollback

Shift traffic back to a previous version, usually in under a second.

forge env

Set, list and remove encrypted environment variables per environment.

forge logs

Stream or tail structured logs from any version or region.

forge db

Provision managed Postgres and fork it for preview branches.

forge export

Emit the generated Dockerfile and compose file — your exit hatch.

forge deploy

Builds the project, uploads the artifact, provisions runtimes in every configured region and shifts traffic once the healthcheck returns 2xx. Each deploy is an immutable version tagged v1, v2, … — nothing is ever overwritten in place.

$ forge deploy [--prod|--preview] [flags]
Flags accepted by forge deploy
flagdefaultwhat it does
--watchoff Redeploy on every save. Incremental — only changed modules are rebuilt and shipped.
--regionfrom config Comma-separated region list for this deploy only, e.g. iad1,fra1.
--token— Non-interactive auth for CI. Reads $FORGE_TOKEN when the flag is omitted.
--no-cacheoff Force a cold build, ignoring the layer cache. Useful when reproducing a build bug.
--messagegit subject Label attached to the version, shown in forge ls and rollback pickers.
--jsonoff Emit one JSON object per line instead of the human log. Exit code is unchanged.

Exit codes

Deploys are safe to chain with && — the command exits non-zero on any failure, including a healthcheck that never goes green.

  • 0 — deployed, traffic shifted, healthcheck green.
  • 1 — build failed. Production is untouched; failing log lines print to stderr.
  • 2 — healthcheck never passed within the timeout. The new version is left parked, not routed.
  • 3 — auth or project resolution failed. Check $FORGE_TOKEN and .forge/project.json.

forge rollback

Shifts traffic to an earlier immutable version. Nothing rebuilds — the artifact is already provisioned, so this is a routing change measured in hundreds of milliseconds.

$ forge rollback --to v41
✓ traffic shifted to v41 in 0.8s
  v42 kept for diffing: forge diff v41 v42

Omit --to and Forge steps back exactly one version. Add --list to print the retained versions with their deploy messages and timestamps before choosing.

retention: the free tier keeps the last 5 versions, Team keeps 50, Enterprise is configurable. Rolling back to an evicted version rebuilds from source instead of routing — still correct, just not instant.

forge env

Environment variables are encrypted with AES-256 at rest, scoped per environment, and injected into the runtime at boot. They are never written to disk on your machine and never appear in build logs.

$ forge env set STRIPE_KEY --prod
? paste value (hidden): ••••••••
✓ encrypted & stored prod only

$ forge env ls --prod
STRIPE_KEY      set 2d ago    ••••••••
DATABASE_URL    set 2w ago    ••••••••
LOG_LEVEL       set 2w ago    info

Values marked non-secret at set time (like LOG_LEVEL above) render in plaintext in env ls; everything else stays masked and can only be overwritten, never read back.

Subcommands of forge env
subcommandscope flagwhat it does
env set--prod / --previewPrompt for a value and store it encrypted for that environment.
env ls--prod / --previewList keys with last-modified times. Secret values stay masked.
env rm--prod / --previewRemove a key. Takes effect on the next deploy, not retroactively.
env pull--previewWrite non-secret preview vars to a local .env for development.

forge.toml

Optional. Forge detects the runtime, port and build step on its own — reach for a config file only when you outgrow the defaults. Every key below has a working default, and the whole file is usually under fifteen lines.

# forge.toml — every key optional
runtime     = "node22"
regions     = ["iad1", "fra1", "sin1"]
healthcheck = "/healthz"

[build]
command     = "npm run build"
output      = "dist"

[scale]
min         = 1
max         = 12

# monorepo: one block per service
[[service]]
name        = "worker"
root        = "apps/worker"
forge.toml top-level keys
keydefaultwhat it does
runtimedetectedPin the runtime image. Node, Go, Python and Rust targets are supported.
regions["iad1"]Where the service runs. Additional regions are a paid-plan capability.
healthcheck"/"Path polled before traffic shifts. Must return 2xx within the timeout.
build.commanddetectedOverride the inferred build step when your setup is unusual.
scale.min0Keep N instances warm. 0 allows scale-to-zero between requests.
service—Repeatable block defining one service per monorepo subdirectory.

CI & tokens

Forge is non-interactive whenever a token is present, so it drops into any pipeline that can run a shell command. Mint a scoped token with forge token create, store it as a secret, and let your existing CI keep doing what it's good at — tests.

# any CI runner that can run a shell step
$ npm i -g forge
$ forge deploy --prod --token $FORGE_TOKEN
✓ deployed → https://api-service.forge.run · 9.2s

This works the same way under GitHub Actions, GitLab CI, CircleCI, Jenkins or a cron job on a box you own — Forge only needs a shell and outbound HTTPS. Because the command exits non-zero on a failed healthcheck, your pipeline goes red without any extra wiring.

  • Tokens are scoped per project and per environment; a preview token cannot touch production.
  • forge token ls shows last-used timestamps so you can revoke what's gone stale.
  • Add --json in CI to capture the deploy URL for a downstream step.
tip: keep tests in CI and let Forge own the deploy step. Teams that move the whole pipeline into forge deploy usually end up rebuilding a test runner inside it.

$ forge init — free for side projects.

You've read the reference. The install is one command and the first deploy is about sixty seconds after that.

See pricing →

100 deploys/mo free · Pro from $19/seat · SOC 2 Type II