Skip to main content
Any coding agent that can run a shell command can put a project online with no Reliant account, token or card. 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:
Wherever a command on this page says 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 its package.json is:
A Next.js app must build as a static export: set 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.
Don’t name the project api. The hosted service workload is already called api, and a database with the same name is refused.
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:
Adding a feature covers entities, RPCs and migrations.

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.
To deploy again after a change, run the same command. You keep the same URL and the same claim link, and the expiry doesn’t move. If you’re an agent, give the user the URL and the claim link, and tell them when it expires. For example:
Never put the claim link anywhere public: an issue, a pull request, a commit, a log or a README.

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, then forge env deploy prod without --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 stable reason in the --json document: An unclaimed deploy is never held for billing, so exit 7 doesn’t occur.

Adding file uploads

File uploads use a forge.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.
  1. In deploy/kcl/dev/main.k, turn on the scaffolded MinIO and name the bucket:
  2. In prod, declare the bucket on Reliant hosting, forge.Bucket {name = "uploads", runtime = forge.OnHosted {}}, or on your own S3, R2 or GCS bucket with forge.BucketOnS3 {...}.
  3. Hand the service its connection in deploy/kcl/workloads.k, with env = forge.bucket_env("UPLOADS", "uploads"). Then read it through the typed config.
  4. In a handler, presign the upload with PresignPut. The browser PUTs the file to that URL, and the handler confirms it with Stat.
forge skill load storage/blobstore has the whole flow, with the handler and browser code.