inversedocs
Pages

CLI

The inverse-embed package installs one command under two names, inverse and inverse-embed. Run it with npx, or install it globally.

terminal
npx inverse-embed@latest --help
# or
npm i -g inverse-embed && inverse --help

Commands

CommandWhat it does
login [--origin URL]Signs in through your browser and saves the token.
deploy [dir] [--name N] [--env .env] [--force] [--quiet] [--json]Checks env, uploads the app in dir (default: here), streams the build and prints its link.
logs [id] [--json]Prints the app's last build: status, error and log.
apps [--json]Lists the apps you made.
share [id] [flags]Sets who can open an app. With no flags, prints its link and current access.
domains [id] [--json]Lists the app's custom domains and re-checks their DNS. See domains.
domains add <domain> [id]Serves the app at your domain and prints the DNS records to set.
domains remove <domain> [id]Removes a custom domain.
open [id]Prints the app's link and opens it in your browser.
skill install [--dir path] [--print]Installs the agent skill. See agent skill.
sync <room link> [flags]Streams a room's session into your project, and optionally to a webhook.
mcp <room link>Runs an MCP server on stdio over the room's context. See MCP.

share, domains and open default to the app saved in this folder, so you only pass an id for another app.

login

Opens /cli/login in your browser and listens on a one-time 127.0.0.1 port for the answer. After you click Authorize Inverse CLI, the token is saved to ~/.inverse/config.json, readable only by you. Tokens last 90 days. The login waits up to 5 minutes.

deploy

Uploads source only and lets Inverse build it. The upload skips:

  • node_modules, build output (.next, dist, build, .svelte-kit, .output and similar) and .git
  • .env*, .npmrc, .yarnrc, vercel.json and key files (.pem, .key, .p12, .pfx)
  • your .inverse folder

The limit is 500 files and 3 MB. The folder needs a package.json; its name becomes the app name on the first deploy unless you pass --name. New apps start private, and each account can host up to 50. The command waits up to 20 minutes for the build.

Before uploading, deploy looks for the environment variables your source requires (process.env.X and import.meta.env.X without a fallback, and the required keys of a t3-env or zod schema in an env file) and stops if any aren't saved on Inverse. It reads names only, never values. Push them with inverse env push .env, or pass --force when they're optional. It also warns when the app's installed inverse-embed is older than the CLI, with the exact command to update it. Use an exact version: pnpm 11 holds back versions published less than a day ago, so @latest can resolve to an older one.

While it builds, deploy prints each phase (queued, installing, building, deploying, ready or failed) and the build log, dimmed. --quiet hides the log. The whole log is saved to .inverse/deploys/<time>.log, and inverse logs prints the last build's log from Inverse. The first deploy saves the app's id as soon as its build starts, so a failed first build still shows on Inverse Dev with its error, and its variables can be set before you try again.

terminal
$ npx inverse-embed deploy
queued…
installing…
  │ Running "pnpm install"
building…
  │ Running "next build"
ready…
Live: https://www.inverse.at/a/imported-3f9c0a1b2d4e5f60
Manage: https://www.inverse.at/dev
Log: .inverse/deploys/2026-11-01T12-00-00-000Z.log

share

FlagEffect
--privateOnly you.
--linkAnyone with the link.
--publicAnyone, and listed in the store.
--email a@b.coAdds a person to the share list. Repeat it for more people; up to 50 in total.
--price 5.00A price in dollars, up to 1000. 0 makes it free. Buyers pay once through Stripe Checkout, once this Inverse server has a Stripe key.
--pens / --no-pensTurns pen tools (draw and highlight over the app) on or off in its rooms. Off by default.

Pick one of --private, --link and --public. You can combine it with --email and --price. See sharing for what each level means.

terminal
npx inverse-embed share --private --email ana@team.co --email li@team.co

domains

Serves the app at a domain you own, up to 5 per app. The domain shows the app itself; its Inverse link (/a/<id>) stays the way into the live room. After add, set the printed records at your DNS provider: an A record to 76.76.21.21 for an apex domain, or a CNAME to cname.vercel-dns.com for a subdomain, plus a TXT record when ownership needs verifying. Names are relative to your apex (@ is the apex). Run inverse domains to check again; DNS can take a few minutes to an hour.

terminal
$ npx inverse-embed domains add app.example.com
app.example.com  waiting for DNS
  Set at your DNS provider:
    CNAME app                      cname.vercel-dns.com

sync

Streams a room into .inverse/sessions/<room>/ while it runs: recap.md, session.json, events.jsonl and intent.json. Stop it with Ctrl+C.

FlagEffect
--out dirWhere sessions go. Default .inverse/sessions.
--webhook URLPOSTs each new event once as { room, type, at, data }.
--secret KEYSigns webhook requests with x-inverse-signature: sha256=<HMAC of the body>.
terminal
npx inverse-embed sync https://www.inverse.at/apps/<room> --webhook https://your.app/hooks/inverse --secret "$INVERSE_WEBHOOK_SECRET"

Add .inverse/ to .gitignore (or at least .inverse/sessions/ and .inverse/deploys/): it holds what your visitors wrote and said, and your build logs.

Environment

VariableUse
INVERSE_TOKENA CLI token, used instead of the saved login. For CI and agents.
INVERSE_ORIGINThe Inverse server. Default https://www.inverse.at.
INVERSE_WEBHOOK_SECRETThe sync webhook secret when you don't pass --secret.

Environment variables win over ~/.inverse/config.json. Copy a token from that file after inverse login and keep it in your CI secrets.

.inverse/app.json

The first deploy writes the app's id and link next to your source. Later deploys from this folder update the same app, so its link, name, sharing, price and branding stay. Only the account that owns the app can redeploy it. Delete the file to deploy as a new app.

.inverse/app.json
{
  "id": "imported-3f9c0a1b2d4e5f60",
  "link": "https://www.inverse.at/a/imported-3f9c0a1b2d4e5f60"
}

--json for agents and scripts

deploy, logs, apps, share and domains take --json. The result is printed as JSON on stdout. A failure prints { "error": "…" } and exits with status 1.

deploy --json streams instead: one JSON event per line as it happens, and the last line is always the outcome, a result or an error. Read the stream as it comes, or take the last line with tail -1.

typeFields
warningwarning: the app's inverse-embed is older than the CLI, with the command to update it.
preflightmissing: required env names not saved on Inverse. Not sent with --force.
phasephase (queued, installing, building, deploying, ready, failed), at.
logat, stream (stdout, stderr, command…), text. ANSI colors and obvious tokens are stripped.
resultThe app (below), plus logFile.
errorerror, missing (env names the build blamed), log (the build's last lines), logFile, hint.
inverse deploy --json
{"type":"phase","phase":"queued","at":1793491200000}
{"type":"phase","phase":"building","at":1793491203000}
{"type":"log","at":1793491203120,"stream":"stdout","text":"Running "next build""}
{"type":"phase","phase":"ready","at":1793491260000}
{"id":"imported-3f9c0a1b2d4e5f60","name":"my-app","description":"","url":"https://…","ownerName":"Ana","mine":true,"visibility":"private","shared":[],"price":0,"createdAt":1793491200000,"updatedAt":1793491260000,"link":"https://www.inverse.at/a/imported-3f9c0a1b2d4e5f60","type":"result","logFile":".inverse/deploys/2026-11-01T12-00-00-000Z.log"}

price is in cents. apps --json prints an array of the same app objects.