CLI
Scaffold Ownfold server setup, generate adapter schemas, and apply SQLite or PostgreSQL migrations.
Install
pnpm add -D @ownfold/cli@beta
The CLI writes files only inside the current project. Existing generated files are preserved unless
you pass --force.
Command reference
| Command | Required input | Reads config | Writes |
|---|---|---|---|
ownfold init |
--database |
No | Config, server scaffold, schemas/migrations |
ownfold generate |
Config, or programmatic database/output | Yes | Schemas and migration files |
ownfold migrate |
Config plus database location | Yes | SQLite schema or PostgreSQL database |
ownfold doctor |
Config, package manifest, environment names, generated assets | Yes | Nothing |
ownfold help, --help, -h |
None | No | Nothing |
Flags
| Flag | Accepted by | Values / default |
|---|---|---|
--database |
init |
sqlite, postgres, drizzle, prisma; required |
--identity |
init |
better-auth, auth-js, workos, custom, none; default custom |
--output |
init |
Generated artifact directory; default ownfold |
--config |
All operational commands | Config path relative to current directory; default ownfold.config.json |
--force |
init, generate |
Replace generated files that already exist |
--database-path |
migrate with SQLite |
SQLite file; default ownfold.sqlite |
--database-url |
migrate with non-SQLite config |
PostgreSQL URL; falls back to DATABASE_URL |
Unknown commands, options, database names, identities, or missing flag values exit with status 1
and a recovery-oriented message. Successful generation prints every written path. A migration with
nothing pending prints No migrations pending..
doctor
pnpm ownfold doctor
The doctor checks coordinated @ownfold/* package ranges, required environment variable names,
generated schema assets, and the standard server scaffold. It never prints or compares secret
values. Secure context, origin/CSRF controls, custom route mounting, and production database state
remain explicit manual checks. The programmatic API returns a typed DoctorReport with stable
check codes, pass/fail/warning statuses, and an overall healthy flag.
init
Choose the adapter. The command creates ownfold.config.json, ownfold.server.ts,
env.server.ts, and schema files.
pnpm ownfold init --database sqlite --identity custompnpm ownfold init --database postgres --identity custompnpm ownfold init --database drizzle --identity custompnpm ownfold init --database prisma --identity customChoose the identity scaffold with --identity better-auth, --identity auth-js,
--identity workos, --identity custom, or --identity none. The default custom scaffold denies
every request until you connect a verified session. none emits singleUserResolver and is only
for private single-user processes.
Use --output path/to/schema to change the generated schema directory or --config path/to/config.json
to change the config path.
generate
Regenerate schema and migration files after upgrading Ownfold:
pnpm ownfold generate
| Adapter | Generated files |
|---|---|
| SQLite | ownfold/schema.sql |
| PostgreSQL | ownfold/migrations/*.sql |
| Drizzle | ownfold/migrations/*.sql; import typed tables from @ownfold/drizzle/schema |
| Prisma | ownfold/schema.prisma and ownfold/migrations/*.sql |
Review changes before using --force. Commit generated schemas with the application migration
history.
migrate
pnpm ownfold migrate --database-path ./ownfold.sqliteThe schema uses idempotent CREATE TABLE IF NOT EXISTS statements. When the path is omitted and an
existing ownfold.db is found, the CLI creates a consistent SQLite backup at a missing or empty
ownfold.sqlite before migrating. The backup includes committed write-ahead-log (WAL) data and also
handles an application opening the new default once before migration. The legacy file remains
unchanged, and applications using the generated environment reader open the adopted database. If
ownfold.sqlite is non-empty, migration fails closed and asks for an explicit
--database-path because the intended database is ambiguous.
pnpm ownfold migrate --database-url "$DATABASE_URL"DATABASE_URL is used when --database-url is omitted. Each numbered migration runs in a
transaction and is recorded in ownfold_migrations. A failed migration rolls back; already applied
migrations are not repeated.
pnpm ownfold migrate --database-url "$DATABASE_URL"Or run the generated SQL through the application’s Drizzle migration workflow.
pnpm prisma migrate dev --name add-ownfold
pnpm prisma generateMerge the generated ownfold/schema.prisma fragment first. To apply the equivalent Ownfold SQL
directly, use pnpm ownfold migrate --database-url "$DATABASE_URL".
Never run migrations in a request handler. Apply them as a controlled deployment step before code that depends on the new schema begins serving traffic.
Configuration file
{
"version": 1,
"database": "postgres",
"identity": "workos",
"output": "ownfold"
}
version1
1databaseDatabaseProvider
DatabaseProvideridentityIdentityProvider
IdentityProvideroutputstring
stringThe parser rejects unknown database/identity values, unsupported versions, and an empty output
path. When identity is absent it defaults to custom for compatibility. Paths are resolved from
the command’s current working directory.
Generated server scaffold
init writes ownfold.server.ts beside the config. The selected database changes only the adapter
construction; the selected identity changes only getUserId:
| Identity | Generated behavior |
|---|---|
better-auth |
Imports betterAuthUserResolver(auth). |
auth-js |
Imports authJsUserResolver around the host auth() loader. |
workos |
Imports workosAuthKitUserResolver() for a TanStack Start AuthKit context. |
custom |
Emits a typed resolver that returns null until the application connects verified sessions. |
none |
Uses singleUserResolver("local-owner"); private single-user processes only. |
init also writes env.server.ts. It calls typed readers from @ownfold/server for the selected
database and identity provider. Ownfold owns the T3 Env schemas internally; the generated
application only sets the documented variables and does not install T3 Env or Valibot.
The scaffold is a starting file owned by the application. Review imports, the generated environment configuration, database lifecycle, and authentication before serving it.
File replacement behavior
Generation is conservative:
- parent directories are created as needed;
- an existing target returns an error unless
--forceis present; - the CLI does not merge an existing Prisma schema or edit an existing migration;
- a failure reports the exact path and preserves unrelated files; and
--forcereplaces only resolved generated targets, not the output directory wholesale.
Review the diff before committing forced regeneration.
Programmatic API
The package root also exports the command operations for custom build tooling. They return
CliResult<T> instead of exiting the process.
import { generateSchema } from "@ownfold/cli"
const generated = await generateSchema({
cwd: process.cwd(),
database: "postgres",
output: "ownfold",
})
if (generated.status === "error") {
console.error(generated.message)
process.exitCode = 1
} else {
for (const path of generated.value) console.log(path)
}
initializeProject(options)
databaseDatabaseProvider
DatabaseProvideridentity?IdentityProvider
IdentityProvidercwdstring
stringconfigPath?string
stringoutput?string
stringforce?boolean
booleanWrites the config, server scaffold, and selected schema artifacts. Returns the absolute paths in write order. If a later write fails, earlier new files remain and are named in the filesystem; the result does not falsely report success.
generateSchema(options)
cwdstring
stringconfigPath?string
stringdatabase?DatabaseProvider
DatabaseProvideroutput?string
stringforce?boolean
booleanWhen database or output is omitted, both missing values are loaded from the config. SQLite emits
one schema file. PostgreSQL and Drizzle emit ordered SQL migrations. Prisma additionally emits the
schema fragment.
migrateDatabase(options)
cwdstring
stringconfigPath?string
stringdatabasePath?string
stringdatabaseUrl?string
stringSQLite executes the idempotent bundled schema and returns sqlite-schema. If no path is supplied,
an existing legacy ownfold.db is backed up consistently to a missing or empty ownfold.sqlite
before migration, including committed WAL data; the source database is preserved. A non-empty
destination fails closed as ambiguous. PostgreSQL creates
the ownfold_migrations ledger, checks each bundled migration by name, and applies each pending file
in its own transaction.
readConfig(cwd, configPath?)
Reads and validates JSON into OwnfoldConfig. Invalid JSON, missing files, invalid values, or read
errors return { status: "error", message }; the function does not throw expected configuration
failures.
Exported types
| Type | Values / purpose |
|---|---|
DatabaseProvider |
`sqlite |
IdentityProvider |
`better-auth |
CliResult<T> |
`{ status: “ok”, value: T } |
OwnfoldConfig |
Parsed version-1 configuration |
InitOptions, GenerateOptions, MigrateOptions |
Programmatic operation inputs |
See Database adapter APIs, Authentication APIs, and the complete export index.