CLI Reference
All inz subcommands with flags and examples.
inz [command] [flags]| Global flag | Description |
|---|---|
--org |
Organization id (org_...) for org-scoped cloud commands. |
--no-telemetry |
Disable anonymous usage and error telemetry for this run. See Telemetry. |
inz init
Section titled “inz init”Scaffold a new instancez project in the current directory.
Writes instancez.yaml, a .development.env.example, and optional boilerplate. Never touches a database. The example code function is scaffolded only when Node.js 22+ is on your PATH; otherwise init warns and omits the functions: block.
inz init [name] [flags]| Flag | Default | Description |
|---|---|---|
--dir |
. |
Output directory. |
--force |
false |
Overwrite existing scaffolding files. |
--template |
Scaffold from a template id (cloud catalog, falls back to the built-in one offline). See templates. | |
--list-templates |
false |
List available templates (built-in list when offline) and exit. |
inz init my-app --dir ./my-appinz dev
Section titled “inz dev”Start a local development server with hot-reload.
Reads config, connects to Postgres, runs migrations, and watches for file changes. Requires INSTANCEZ_DATABASE_URL (a superuser DSN) to provision roles on every startup, or set INSTANCEZ_OWNER_DATABASE_URL and INSTANCEZ_AUTH_DATABASE_URL directly. Startup order: validate the config, check that the HTTP port is free, then start embedded Postgres and function dependencies.
inz dev [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Config source: file path, s3://bucket/key or gcs://bucket/key. Env: INSTANCEZ_CONFIG. |
--dashboard |
readwrite |
Dashboard mode: disabled, readonly, or readwrite. |
--dashboard-write-dotenv |
true |
Allow the dashboard to write secrets to .development.env. |
--dotenv-path |
.development.env |
Path to the .env file for dashboard secret writing. |
--embedded-pg |
false |
Start an embedded Postgres 16 (data at ./pgdata/); no external DB needed. Prints its DSN in the banner; port is kept across runs. |
--no-watch |
false |
Disable hot-reload. |
--port |
(from config or 8080) |
Override server port. |
--reset-pg |
false |
Wipe ./pgdata/ before starting (requires --embedded-pg). Refused while another inz dev uses ./pgdata/. |
--verbose |
false |
Enable debug logging. |
--watch |
true |
Watch the config source for changes. |
--watch-interval |
1m |
S3-watch poll interval (minimum 10s). |
INSTANCEZ_DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres inz devinz serve
Section titled “inz serve”Start the production server.
Unlike dev, does not hot-reload and defaults to dashboard disabled.
Even without --migrate, every boot creates the migration-history table if missing, as its own locked step, then — in a second locked transaction — creates auth.jwt_keys if missing, re-applies the privilege revokes on auth.* and _instancez_migrations, and adds any auth columns or indexes that newer releases introduced. Boot fails if either step fails. With --watch, this also re-runs after every hot-reloaded migration; a failure there is logged, not fatal, and the functions of the failed config are not loaded (they reload only after a successful migration).
inz serve [flags]| Flag | Default | Description |
|---|---|---|
--allow-destructive |
false |
Permit DROP TABLE and DROP COLUMN during migration. Without it, inz serve refuses to apply a plan that drops a table or column and reports what would have been lost. inz dev always permits drops and logs each one. Env: INSTANCEZ_ALLOW_DESTRUCTIVE. |
--migrate-lock-timeout |
5s |
Longest an inz serve migration statement waits for a table lock. If a long query holds the table, the migration fails and the server keeps running on the last applied config instead of blocking traffic behind the pending lock. 0 disables the limit. Env: INSTANCEZ_MIGRATE_LOCK_TIMEOUT. |
--bundle |
— | Bundle pointer: file path or s3://bucket/key[#version] or gcs://bucket/key[#version]. When set, reads config and functions from the bundle archive instead of --config. Env: INSTANCEZ_BUNDLE. |
--config |
instancez.yaml |
Config source: file path, s3://bucket/key or gcs://bucket/key. Ignored when --bundle is set. Env: INSTANCEZ_CONFIG. |
--dashboard |
disabled |
Dashboard mode. Env: INSTANCEZ_DASHBOARD. |
--dashboard-write-dotenv |
false |
Allow dashboard to write secrets to a .env file. Env: INSTANCEZ_DASHBOARD_WRITE_DOTENV. |
--dotenv-path |
— | Path to .env file when --dashboard-write-dotenv is set. Env: INSTANCEZ_DOTENV_PATH. |
--migrate |
false |
Run pending migrations on startup. |
--port |
(from config or 8080) |
Override server port. |
--watch |
false |
Watch the config source for changes. In bundle mode, polls the bundle ETag (S3) or mtime (local) instead of the config file. Env: INSTANCEZ_WATCH. |
--watch-interval |
1m |
S3-watch poll interval. Env: INSTANCEZ_WATCH_INTERVAL. |
inz serve --migrate --config instancez.yaml
# Bundle mode: config + functions come from a single archive (no race condition)inz serve --bundle s3://my-bucket/bundles/app.tar.gz --migrate --watchinz serve --bundle /path/to/bundle.tar.gz --migrateinz validate
Section titled “inz validate”Validate instancez.yaml structure and references without starting the server.
Follows include: files. Checks YAML structure, identifiers, cross-references, and verifies that each declared code function’s file: exists on disk.
Local validation (including --use-dsn) loads .development.env first. An unset ${INSTANCEZ_ENV_*} reference (with no :- default) warns and is treated as empty, as in inz dev. Any other unset ${VAR} is still an error. inz validate and inz dev also warn when an OAuth provider other than google/apple ends up with an empty client_secret (inz serve rejects it). When an unset variable is outside the INSTANCEZ_ENV_ namespace, the report lists it together with every other error. ${VAR} on a full-line # comment is ignored everywhere (this includes a line starting with # inside a | block scalar). inz serve and inz bundle stay strict and fail on any unset ${VAR}. inz cloud deploy parses leniently and leaves validation to the cloud, so it does not fail locally on an unset variable. --project and --cloud load no .development.env and resolve no env references locally. They send the file as written, unless it uses include:. Then they send one merged file without the include: key. Shorthands (timestamps, owner) are sent as written, so the cloud needs a release that knows them before such a config deploys.
With --use-dsn, also connects to the database and prints the migration plan (DDL diff) without applying it.
Add --dry-run-ddl to also run the migration inside a transaction that is always rolled back. That surfaces unknown columns in RLS policies and bad language: sql rpc bodies as real Postgres errors, and exits non-zero on failure. It is opt-in because it takes the migration advisory lock and DDL locks until the rollback (lock_timeout 2s, statement_timeout 30s per statement, 2 minutes for the whole run). When the database already matches the config, it skips the plan but still re-creates every rpc with body checking on. It needs a DSN with the instancez roles provisioned, and runs destructive changes inside the rolled-back transaction. With --json, the output gains dry_run ("ok" or the error).
inz validate [flags]| Flag | Default | Description |
|---|---|---|
--cloud |
false |
Validate against the cloud’s policy rules server-side (projectless; the same rules a deploy enforces). Requires inz cloud login. Cannot be combined with --project. |
--config |
instancez.yaml |
Config source. Env: INSTANCEZ_CONFIG. |
--json |
false |
Output errors as JSON (for CI): an array of {path, message, line, column, suggestion}. line and column are omitted when unknown. |
--project |
— | Preview against a cloud project. Bare --project uses instancez.yaml’s linked project; --project <id> or --project=<id> targets a different one. Never creates a project; link one first with inz cloud deploy --new. |
--use-dsn |
— | After syntax check, plan a migration against this owner-class DSN (plan only — never applied). |
--dry-run-ddl |
false |
With --use-dsn, also run the migration in a rolled-back transaction. Takes DDL locks until rollback. |
inz validateinz validate --use-dsn postgres://owner:pass@localhost/mydbinz validate --cloud # check against the cloud's policy rulesinz validate --project # preview against instancez.yaml's linked projectinz validate --project abc123 # preview against a specific project idinz gen types
Section titled “inz gen types”Generate TypeScript types for @supabase/supabase-js from instancez.yaml. It reads the file only, with no database or network. See TypeScript types.
inz gen types [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Local config file. Env: INSTANCEZ_CONFIG. |
--out |
— | Write to this file instead of stdout. |
An invalid config prints the validation errors, exits 1 and writes nothing.
inz gen types --out database.types.tsinz vet
Section titled “inz vet”Lint instancez.yaml for security problems: open RLS policies, disabled RLS, hardcoded secrets, unsafe auth and CORS settings. It reads the file only, with no database or network, and does not interpolate ${...} values.
inz vet [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Local config file. Env: INSTANCEZ_CONFIG. |
--json |
false |
Print the report as JSON. Env: INSTANCEZ_JSON. |
--fail-on |
high |
Exit 1 when a finding is at this severity or above: info, low, medium, high, critical, or none. Env: INSTANCEZ_FAIL_ON. |
Exit codes: 0 when nothing reaches --fail-on, 1 when something does, or when the file cannot be read or parsed. A structurally invalid file (wrong types) is an error; run inz validate for details.
--json prints every finding, even those below --fail-on:
{ "findings": [ { "rule": "rls-disabled", "severity": "critical", "path": "tables.posts.rls_enabled", "line": 4, "title": "Row-level security is off", "message": "Anyone with the public key can read and write every row in posts.", "fix": "Set rls_enabled: true and add policies, unless the table is meant to be public.", "edit": { "path": ["tables", "posts", "rls_enabled"], "value": true } } ], "counts": { "info": 0, "low": 0, "medium": 0, "high": 0, "critical": 1 }, "checks": { "total": 21, "passed": 20 }}checks.total is the number of rules below, and checks.passed is how many of them have no finding. The human output ends with the same tally, for example 21 of 22 checks passed. unknown-key is reported but is not a check.
edit is present when one config change resolves the finding: rls-disabled (only for a table that already has policies, since turning RLS on without any denies every row), anonymous-signins, jwt-expiry-long, signup-unverified-email (only when an email provider is configured), cors-null-origin and max-limit-disabled. path lists object keys and array indexes. remove: true deletes the value instead of setting it, and value is then the value expected at path. Findings whose right fix depends on your app, such as policies, have no edit.
The running engine serves the same report at GET /_admin/vet (secret key required). It returns 400 invalid_config when the config does not parse.
Run it in CI to block a merge:
- run: inz vet --fail-on mediumDashboard
Section titled “Dashboard”The dashboard’s Security page runs the same scan. A banner shows how many checks passed, with severity chips to filter the list. Pick a finding to see its detail. When the finding has an edit, a Fix it button rechecks first. Otherwise it shows the change in the usual save confirmation and reloads the list after you confirm; it needs write access to the config.
| Rule | Severity | Flags |
|---|---|---|
rls-disabled |
critical | A table with rls_enabled: false. |
policy-open-write |
critical | An insert, update or delete policy whose using or with_check is always true. |
policy-open-read |
low, high | A select policy whose using is always true. High when the table has sensitive columns. |
policy-authed-read-sensitive |
medium | A select policy that only checks the caller is signed in, on a table with sensitive columns. |
policy-no-identity-write |
medium, high | A write policy that never checks the caller’s identity, directly or through a declared rpc that does. High when the table has an owner column. |
bucket-open-write |
critical | A storage policy that lets any caller with a JWT (including anonymous sign-in users) write or delete. |
bucket-open-read |
medium | A select policy on a non-public bucket whose using is always true, so any caller with a JWT can list and read every object. |
bucket-authed-write |
medium | An insert, update or delete storage policy that only checks the caller is signed in (auth.is_authenticated(), auth.uid() IS NOT NULL), so any user can upload anywhere, or replace or delete other users’ objects. |
bucket-no-rls |
medium, high | A bucket with no policies. High when other buckets have them. |
bucket-public |
low | A bucket with public: true. |
rpc-definer-no-auth |
low, medium, high | A security: definer function callable without sign-in, so its reads bypass RLS. High when the body writes (or runs EXECUTE) with no auth.* check, medium when it only reads or writes with a check, low when it only reads and checks auth.uid(), auth.jwt(), auth.email() or auth.role(). |
rpc-definer-search-path |
high | A security: definer function with no pinned search_path. |
rpc-dynamic-sql |
medium, high | A plpgsql EXECUTE on a string built with || or format(%s). High on definer functions. |
function-public-secrets |
low | A function with auth_required: false that has secret-looking env values, so anyone can trigger its use (not read it). |
hardcoded-secret |
high | A literal email api_key, storage keys, OAuth client_secret, or secret-looking function env value. |
jwt-expiry-long |
medium, high | auth.jwt_expiry over 1 hour. High over 24 hours. |
signup-unverified-email |
low, medium | Sign-up is open and auth.email.verify_email is off. Low when no providers.email is configured to send mail. |
anonymous-signins |
low | auth.allow_anonymous: true. |
redirect-insecure |
low, medium | An auth redirect URL that uses a wildcard or local http (low), or plain http or a javascript:, data: or vbscript: scheme (medium). |
cors-wildcard |
low | * in server.cors.origins. |
cors-null-origin |
medium | null in server.cors.origins. |
unknown-key |
medium | A key that is not a known setting (usually a typo), so it has no effect. |
max-limit-disabled |
medium | server.max_limit: -1 (no row limit). |
Sign-in rules (bucket-authed-write, policy-authed-read-sensitive) read expressions with a small tokenizer, not a SQL parser. They skip string literals, quoted identifiers and comments. Known limits, all of which err toward not flagging:
- Only a top-level
OR, or theELSEor sign-in-guardedTHENof one whole searchedCASE, is checked. A sign-in check hidden in a subquery, a function body,COALESCE,NOT, or the simple formCASE x WHEN ...is not seen. - A sign-in check
ANDed with a condition counts as scoped only when that condition mentionsauth.uid(),auth.jwt(),auth.email(),service_roleor a declared rpc that reads the caller. Other filters (bucket_id = 'x',deleted_at IS NULL, path checks) do not scope, so the policy is still flagged. - Dollar-quoted strings and
E'...'backslash escapes are not special-cased. - An insert policy that only checks sign-in is flagged even when open uploads are intended. Scope it by path, for example
(storage.foldername(name))[1] = auth.uid()::text, or ignore the finding.
inz bundle
Section titled “inz bundle”Build a self-contained tar.gz bundle from instancez.yaml and functions/.
The bundle is the deployment artifact for projects that use code functions. It contains instancez.yaml, functions/ (with vendored node_modules/), and a manifest.json. Upload it to S3 then set functions_bundle: in instancez.yaml to the returned pointer.
The bundled instancez.yaml follows include:: the files are merged into one and the include: key is dropped. Configs without include: are bundled as written. Shorthands such as timestamps and owner are not expanded in the bundle.
Runs stateless validation (same as inz validate) including checking that each declared function’s file: exists on disk. npm output is shown only when npm ci fails.
inz bundle [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml. |
--output |
bundle.tar.gz |
Destination: local file path (relative to the current directory), s3://bucket/key or gcs://bucket/key. Local files are written with mode 0600. |
inz bundle # write ./bundle.tar.gzinz bundle --output my-app.tar.gz # write to another local fileinz bundle --output s3://my-bucket/bundle.tar.gz # upload to S3, print pointerinz db reset
Section titled “inz db reset”Drop all data in the local development database. Local only: it refuses any database host that is not localhost, a loopback address (127.0.0.0/8, ::1) or a unix socket, and there is no override. A tunnel or proxy listening on localhost (SSH tunnel, kubectl port-forward, Cloud SQL proxy) counts as local, so check where it points.
It drops public, auth, storage and every schema your tables declare, then recreates an empty public. Other schemas are kept, but it uses DROP SCHEMA ... CASCADE, so views, foreign keys, functions and columns whose type lives in a dropped schema (for example an enum in public) are dropped too. The prompt lists them first. With INSTANCEZ_OWNER_DATABASE_URL and INSTANCEZ_AUTH_DATABASE_URL, the drop runs as the owner login.
It needs a valid instancez.yaml (to know which schemas to drop). It does not migrate or seed: run inz dev afterwards to recreate the schema. Flags read the same INSTANCEZ_* environment defaults as inz dev (for example INSTANCEZ_EMBEDDED_PG), except --yes, which is never read from the environment.
Asks Drop all data in <host:port/db>? [y/N] on a terminal. Without a terminal it exits with an error unless --yes is set. If inz dev holds locks on the database, it fails after 5 seconds instead of hanging.
With --embedded-pg it deletes pgdata and pgdata.runtime next to the config file (the config file must exist), and refuses while inz dev --embedded-pg is running. If the process in pgdata/postmaster.pid is gone but the PID was reused, delete that file.
inz db reset [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml. |
--embedded-pg |
false |
Delete the embedded Postgres data dir instead of dropping schemas. |
--yes, -y |
false |
Skip the confirmation prompt. |
inz db resetinz db reset --embedded-pg --yesinz cloud deploy
Section titled “inz cloud deploy”Write the current instancez.yaml to an instancez Cloud project.
Shows a diff of what would change and prompts for confirmation before writing. If no project is linked, pass --new to create one (after local validation passes) or --project <id> to target an existing one without editing the yaml.
inz cloud deploy [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml. |
--new |
false |
Create a new instancez Cloud project when none is linked yet (only after local validation passes). |
--project |
— | Target this cloud project id for this run, instead of instancez.yaml’s project.cloud.project_id. Does not modify the file. |
--yes, -y |
false |
Skip the deploy confirmation prompt. |
inz cloud deploy --new # first deploy: create + link + pushinz cloud deploy --project abc123 # target a specific project without editing the yamlinz cloud deploy --yes # skip the confirmation prompt (e.g. in CI)inz doctor
Section titled “inz doctor”Run preflight checks for inz dev: config validity, the superuser database DSN, and Postgres role layout.
Database checks are skipped when no DSN is set (a missing or unreachable database is reported once), and the DSN hint suggests inz dev --embedded-pg, which needs none.
Exits non-zero if any check fails.
inz doctor [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml. |
--json |
false |
Print results as one JSON object: {"ok", "checks":[{"name","ok","detail","hint"}]}. Still exits non-zero on failure. |
inz doctorinz cloud status
Section titled “inz cloud status”Show the linked cloud project’s current state: name, ID, URL, and deploy status.
Requires a linked project (inz cloud deploy --new links one).
inz cloud status [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml. |
--json |
false |
Print the project and deploy state as JSON (the API response). Never prompts for login. |
inz cloud statusinz cloud login
Section titled “inz cloud login”Authenticate against instancez Cloud via device-code flow.
Opens a browser to confirm a one-time code, then stores a Personal Access Token at ~/.instancez/credentials.
inz cloud login [flags]| Flag | Default | Description |
|---|---|---|
--force |
false |
Re-authenticate even if already logged in. |
inz cloud logininz cloud logout
Section titled “inz cloud logout”Remove the PAT stored at ~/.instancez/credentials. The token remains valid server-side until revoked from the dashboard.
inz cloud logoutinz cloud whoami
Section titled “inz cloud whoami”Print the currently logged-in instancez Cloud user.
inz cloud whoamiinz cloud frontend deploy
Section titled “inz cloud frontend deploy”Upload an externally-built static frontend bundle to an instancez Cloud project.
The bundle is served as the project’s static site. <dist-dir> must contain index.html (a Vite/SPA build). The project id is read from project.cloud.project_id in instancez.yaml, or pass --project.
inz cloud frontend deploy <dist-dir> [flags]| Flag | Default | Description |
|---|---|---|
--config |
instancez.yaml |
Path to instancez.yaml (for the linked project id). |
--project |
— | Target this cloud project id instead of instancez.yaml’s project.cloud.project_id. |
npm run build && inz cloud frontend deploy distinz completion
Section titled “inz completion”Generate the shell autocompletion script.
inz completion bash|zsh|fish|powershellsource <(inz completion zsh) # load for the current shellinz telemetry
Section titled “inz telemetry”Manage anonymous usage and error telemetry. See Telemetry for what is collected.
inz telemetry statusinz telemetry enableinz telemetry disablestatus prints whether telemetry is enabled, how to disable it (or the reason it is off), and your anonymous id. enable and disable save the choice in ~/.instancez/telemetry.json.
inz version
Section titled “inz version”Print the binary version. inz --version prints the same line. Builds from go build/go install without ldflags report the module version and git commit.
inz version