For people

Doing it by hand

Saasie is designed so a code agent can take someone from a sentence to a running app without them opening a terminal. This page is the other way round: what those steps actually are, in order, for someone who would rather do it themselves.

There is no hidden path here and no reduced version. The CLI an agent drives is this CLI, and the commands below are the same ones it runs. It takes about ten minutes.

1. Install the CLI

One self-contained executable — the runtime is compiled in, so there is nothing to install alongside it and no package manager involved.

curl -fsSL https://saasie.io/install.sh | sh

If piping a script into a shell is not something you do, that is a reasonable position: every build and its checksum is published, and the installer is plain text you can read first.

2. Log in

An account is an email address. There is no password, no browser step, and no card before anything runs. A code arrives in your inbox; you hand it back.

saasie otp you@example.com
saasie token 123456

The token is stored on this machine from then on. saasie whoami says who you are; saasie logout revokes it.

3. Write the blueprint

One file, saasie.yaml, at the root of your repository. It declares what runs — and nothing about where, because every deployment of it gets its own hostnames and its own databases with their own generated passwords.

version: 1

databases:
  db:
    engine: postgres

services:
  web:
    dockerfile: Dockerfile
    context: .
    port: 3000
    health:
      path: /health
    env:
      PORT: { service: web, property: port }
      DATABASE_URL: { database: db, property: url }

Two things there catch nearly everyone. PORT is not injected — nothing is — so a framework that reads it and falls back to a default will listen somewhere else and never become ready. And your process must bind 0.0.0.0, not 127.0.0.1, or it is unreachable from outside its own container and reads as dead.

Check it before you push: saasie validate. The full schema, with every reference type, is on the blueprint page.

4. Claim a name

The name is global and permanent — it becomes the repository, the hostname and the URL.

saasie new acme

5. Push

A push to main builds every service in the blueprint and rolls it out. Any other branch is accepted and starts nothing.

git remote add saasie "$(saasie app acme git get-url)"
git push saasie main

So that HTTPS pushes authenticate themselves without putting a live token in .git/config, register the credential helper once:

git config --global credential.helper '!saasie git-credential'

6. Check it from outside

This is the step worth arguing about, so it gets its own section.

A green build does not mean your app runs. The build log ends when the image is pushed — your server has not executed at that point. And because a rollout only replaces the old version once the new one answers its health path, a new version that cannot start leaves the old one serving happily. Nothing 500s, nothing restarts, and the app simply does not change.

So read the running code, not the log. The cheapest reliable check is to make the app state its own version — an endpoint returning the commit, or any value you changed in the same commit — and fetch it over the public URL.

saasie app acme build list     # did it build
saasie app acme status         # is it running, and if not why
saasie app acme logs           # what it has said lately

curl -s https://acme.saasie.app/version

status reads the cluster rather than our records, which is the point: it names a failing health path, and prints Kubernetes' own reason when a container is up and not answering.

What happens next is where it gets sharp

Everything above is the easy half. The two that bite are both about the second deploy, not the first:

Migrations Your old and new code run against the same database simultaneously during every rollout. Add columns, do not rename them. And if you serialise with a Postgres advisory lock through a connection pool, you can deadlock every future deploy in a way that never throws.
Deploying Adding a second service moves the first one's URL, because a multi-service Saasie has no bare <name>.saasie.app at all.

And if you would rather not

Entirely fair. Hand this to a code agent — point it at saasie.io/agent.txt — and it will do all of the above. The only step it cannot do for you is step 2, because the login code goes to your inbox and not its.