forge env deploy prod --claimable builds the project, publishes it to Reliant hosting under a temporary anonymous identity, and prints a live URL and a claim link. The deploy stays online for 72 hours. If someone opens the claim link and signs up (free) in that time, the deploy becomes theirs.
It’s meant for the moment someone says “deploy this”, “give me a URL” or “put this online” in a project with no hosting yet. If you’re already signed in to Reliant, deploy to your own account instead: see Environments & deploys.
Get forge
You don’t need to install anything if you have Node 18 or later:forge, you can write npx -y @reliantlabs/forge instead. To install the binary:
--claimable needs forge v1.0.15 or later.
Deploy an existing Vite or Next.js app
Run this at the app’s root, where itspackage.json is:
output: "export" in next.config.*. forge lint --static-export lists, with file and line, anything an export can’t serve, such as a dynamic route without generateStaticParams, a server action or cookies(). An app that needs a server at request time can’t use this path.
To deploy a folder of plain HTML, first add a package.json with "scripts": {"build": "vite build"} and vite as a devDependency, run npm install, then follow the steps above.
Deploy a new static site
Deploy a Go API with Postgres
This path needs Go, and Docker to build the service image:--claimable sizes prod to fit the no-account plan.
Before you deploy, give the API at least one entity: a message marked // forge:entity in proto/services/notes/v1/*.proto. Then generate, check and deploy:
What the deploy prints
The deploy runs without prompting, because--claimable implies --yes. It ends with the URL, the time it goes offline, and the claim link. With --json, it prints one document with ok, exit_code and a claim object: state, url, claim_url, expires_at, purge_after, no_outbound_internet and agent_instructions.
What claiming gives you
Opening the claim link signs you up for free, or signs you in, and moves the deploy into your account:- The deploy stops expiring. Later deploys run as you:
forge login, thenforge env deploy prodwithout--claimable. - A static site stays free: one hosted static site per account, under the static free tier.
- A backend gets its outbound internet back. A service and its managed Postgres need paid app hosting to keep running long term.
Limits
The no-outbound-internet rule is the platform, not a bug in your app, so don’t debug it or work around it. An app that calls an outside API at startup won’t come up until the deploy is claimed.
When it’s refused
Every refusal is a non-zero exit with a stablereason in the --json document:
An unclaimed deploy is never held for billing, so exit 7 doesn’t occur.
Adding file uploads
File uploads use aforge.Bucket (the S3 API, with MinIO in forge env up dev) and presigned URLs from forge/pkg/blobstore, so the browser sends the file straight to storage. They need forge v1.0.16 or later and an account: claim the deploy or sign in first, because the no-account plan doesn’t include object storage.
-
In
deploy/kcl/dev/main.k, turn on the scaffolded MinIO and name the bucket: -
In prod, declare the bucket on Reliant hosting,
forge.Bucket {name = "uploads", runtime = forge.OnHosted {}}, or on your own S3, R2 or GCS bucket withforge.BucketOnS3 {...}. -
Hand the service its connection in
deploy/kcl/workloads.k, withenv = forge.bucket_env("UPLOADS", "uploads"). Then read it through the typed config. -
In a handler, presign the upload with
PresignPut. The browser PUTs the file to that URL, and the handler confirms it withStat.
forge skill load storage/blobstore has the whole flow, with the handler and browser code.