Docs

Cira takes a repository as it is. There is nothing to add to it - no manifest, no Dockerfile you did not already want, no pipeline.

Deploy an app

Install the CLI and sign in from the machine you already build on:

$npm install -g @cira-app/cli$cira login

Then, in the repository, deploy it. Cira works out the framework, the parts to build, the variables it needs and the workers or scheduled runs it declares, and asks you before it does anything you did not expect.

$cira deploy

A repository with a Procfile, a fly.toml or a scheduled GitHub Actions workflow keeps those: its workers and its timetables come across, switched off until somebody turns them on.

Give it a database

An app that reads DATABASE_URL and has none is offered one when it deploys: its own Postgres, made on Neon for that app alone. Or ask for one outright, which is how a script says yes:

$cira deploy --database

The app gets DATABASE_URL, through Neon’s pooler, and DATABASE_URL_UNPOOLED for migrations - and so do its workers, its scheduled runs and its release command, so a first deploy can create its tables. To look inside, or to take the data with you:

$psql "$(cira database url)"

Removing the app deletes its database and everything in it. An app that already has a database of its own keeps it; Cira never replaces one.

A Redis cache works the same way: offered for a REDIS_URL nobody set, or asked for with cira deploy --cache, and read back with cira cache url.

Open it

Every app is at {app}--{space}.cira.dev, and everyone who is allowed to open it signs in to Cira once. The app never has to know about any of that - it is reached through Cira’s own door, and only by people the app’s managers named.

An app can also answer on a name of your own, like tools.yourcompany.com: add it from the app’s page and make the CNAME record it shows. Cira gets it a certificate, and it opens behind the same sign-in, for the same people.

Use it from an assistant

Cira reads each app for the operations it offers and turns them into tools an assistant can use. Point Claude Code or Cursor at Cira once:

$cira mcp connect

The assistant then gets four tools, whatever the company has deployed: search the company’s capabilities, read one, run one, and check how an app is doing. Everything it runs, it runs as the person asking, with their permissions and nobody else’s. Anything that changes data waits for a person to agree.

Inside Cira, the same thing is a box on the page: ask a question in plain words and Cira uses the company’s own software to answer it.

If your app signs its own users in

Most internal software has its own login, and a call that says only “Cira is calling” is no use to it. Turn on Tell this app who is calling in the app’s settings and Cira sends a signed statement naming the person behind each request:

# Python, with any JWT library
claims = jwt.decode(
    request.headers["x-cira-identity"],
    key=cira_keys(),                    # https://cira.dev/.well-known/cira-jwks.json
    algorithms=["ES256"],
    audience="https://" + request.headers["host"],  # the address it reached you on
    issuer="https://cira.dev",
)
user = find_user_by_email(claims["email"])

It carries who they are - id, name, verified email - which company, and whether a person or their assistant is asking (via). It carries nothing anyone could be signed in with, and it lasts sixty seconds. Its audience is the address Cira calls your app on, which is the host the request arrived at - not your app’s public address, which Cira’s own calls never use. Checking it means a statement meant for another app is refused by yours. Verify it; never trust the header unchecked. Cira removes any such header a browser sends, but your app should not depend on that.

Sign in through your company

An admin can send everyone at your domain through Okta, Microsoft Entra or Google Workspace instead of an emailed code, from the space’s Settings. The same page gives your provider a SCIM address and token, so people are added as you assign them, taken out the moment they are deactivated, and your groups arrive as teams.

Keep an eye on it

Each app has its runtime logs, its recent runs, and a record of who ran what. Cira watches every app by itself and emails whoever manages it when a deploy fails, an app stops answering, a worker keeps stopping or a scheduled run fails.

The rest is on each app’s own page. Pricing is per person, with the always-on parts billed separately.