TenancyJS

CLI

Inspect, manage, migrate, provision, and run against your live tenants - from one command.

The tenancy CLI (tenancyjs-cli) is how you operate a tenancy. It loads your tenancy.config.ts at runtime - Node 24 strips the types, so there's no transpiler dependency - and acts against your real tenants through your store and hooks. It orchestrates and fails closed, but never invents ORM behaviour it hasn't tested.

npx tenancy <command> [--config <path>] [--json]

Every operational command:

  • loads your runtime, resolves tenants through the hardened store,
  • redacts secrets from human and --json output,
  • disposes connections on exit - including on failure,
  • exits non-zero on error (so it's CI-friendly).

Set up a project

npx tenancy init          # scaffold config + wiring for your framework and ORM
npx tenancy init --framework express --orm drizzle # explicit non-interactive stack
npx tenancy tenant check  # verify the runtime loads and the store works

tenant check is the honest one. It reads each adapter's own capability report and warns about any adapter/strategy combination that isn't tested-supported, instead of pretending it's production-ready:

OK   runtime: tenancy config loaded
OK   adapters: 1 adapter(s) configured
WARN adapter:mongoose: schemaPerTenant is reported as "rejected", not
     tested-supported - not in the verified matrix; use at your own risk
OK   store: implements list, find, create
OK   store.list: read 12 tenant(s)

It exits 0 when healthy and 2 when a probe fails.

Init recognizes Express with Prisma, TypeORM, Sequelize, or Drizzle; AdonisJS with Lucid; and Next.js with Prisma. It previews by default and never overwrites an existing file.

Manage tenants

Read and write your bring-your-own tenant store.

npx tenancy tenant list
npx tenancy tenant show acme
npx tenancy tenant create acme --set plan=pro --set region=eu
npx tenancy tenant suspend acme
npx tenancy tenant activate acme

--set key=value is repeatable and is validated before the runtime loads, so a typo fails fast. The id is optional on create if your store generates it.

Run a script in a tenant scope

Run a one-off script - a backfill, an admin task - inside a resolved tenant (or the central) scope. The script's top-level code and its default export run with the active context.

npx tenancy run ./backfill.ts --tenant acme
npx tenancy run ./rollup.ts --central

You must pass exactly one of --tenant <id> or --central; the tenant is resolved (and validated) through your store before the script runs.

Provision & migrate

For schema- and database-per-tenant, these delegate to the provisioner hooks in your config - the CLI never runs an ORM itself. It resolves each tenant's placement from the store record and runs your hook.

npx tenancy tenant provision acme     # create the tenant's schema/database
npx tenancy tenant migrate acme       # run your migrator for one tenant
npx tenancy tenant migrate --all      # ...for every tenant, reporting each outcome
npx tenancy tenant deprovision acme   # drop it - explicit id only

--all is only valid for migrate. deprovision always requires an explicit id, so a destructive drop can never fan out across every tenant by accident. A partial --all run reports which tenants failed and exits non-zero.

Every command

CommandDoes
tenancy initScaffold config + wiring for your stack
tenancy tenant checkHealth-probe the runtime + warn on untested combos
tenancy tenant listList tenants from your store
tenancy tenant show <id>Show one tenant
tenancy tenant create [<id>] [--set k=v …]Create a tenant
tenancy tenant suspend <id> / activate <id>Change tenant status
tenancy tenant provision <id> / deprovision <id>Create / drop a tenant's placement
tenancy tenant migrate (<id> | --all)Migrate one or all tenants
tenancy run <script> (--tenant <id> | --central)Run a script in a scope
tenancy doctorInspect a project's static setup
tenancy test:leak --test-file <path>Run a cross-tenant isolation leak test

Add --json to any of them for machine-readable, still-redacted output.

On this page