CLI Reference
The Kora CLI provides commands for creating, developing, and managing Kora.js applications. It includes project scaffolding, a development server, schema migration tools, and type generation.
Installation
The CLI is included when you install kora or can be installed standalone:
# Included with kora
pnpm add kora
# Or install standalone
pnpm add -D @korajs/clikora create
Scaffolds a new Kora.js application from a template.
Usage
npx create-kora-app [name] [options]Or if the CLI is installed:
kora create [name] [options]Arguments
| Argument | Required | Description |
|---|---|---|
name | No | Project directory name. If omitted, you will be prompted. |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--template | string | -- | Template to use. Skips the template selection prompt. |
--pm | string | -- | Package manager (pnpm, npm, yarn, bun). Skips the package manager prompt. |
--yes, -y | boolean | false | Accept all defaults (recommended template + auto-detected package manager). |
--tailwind / --no-tailwind | boolean | -- | Use Tailwind CSS or plain CSS. Skips styling prompt. |
--sync / --no-sync | boolean | -- | Include sync server or not. Skips sync prompt. |
--skip-install | boolean | false | Skip installing dependencies. |
Templates
| Template | Styling | Sync | Description |
|---|---|---|---|
react-tailwind-sync | Tailwind CSS | Yes | Recommended. Polished dark-themed UI with real-time sync. |
react-tailwind | Tailwind CSS | No | Tailwind CSS with local-only storage. |
react-sync | Plain CSS | Yes | Clean CSS with sync server. |
react-basic | Plain CSS | No | Minimal setup with local-only storage. |
All templates include DevTools enabled by default, SQLite WASM persistence, and a todo app with stats, filters, and a polished UI.
Interactive flow
When run without options, the CLI prompts for configuration:
$ npx create-kora-app my-app
Kora.js - Offline-first application framework
? Select a template:
> React + Tailwind (with sync) (Recommended)
React + Tailwind (local-only)
React + CSS (with sync)
React + CSS (local-only)
? Package manager:
> pnpm
npm
yarn
bun
Creating my-app...
Installing dependencies...
Done! Next steps:
cd my-app
pnpm devNon-interactive usage
# Use a specific template
npx create-kora-app my-app --template react-tailwind-sync --pm pnpm
# Accept all defaults (react-tailwind-sync + detected package manager)
npx create-kora-app my-app --yes
# Mix flags: Tailwind without sync
npx create-kora-app my-app --tailwind --no-sync --pm npmGenerated project structure
my-app/
src/
schema.ts # Your schema definition
main.tsx # Application entry point
App.tsx # Example UI
kora-worker.ts # SQLite WASM worker entry
server.ts # (sync templates) sync server entry point
kora/
generated/
types.ts # Auto-generated TypeScript types
migrations/ # Schema migration files
package.json
tsconfig.json
vite.config.ts
kora.config.ts # Kora configurationkora dev
Starts the full development environment with hot reloading, sync server, and DevTools.
Usage
kora dev [options]Options
| Option | Type | Default | Description |
|---|---|---|---|
--port | number | 5173 | Vite dev server port. |
--sync-port | number | 3001 | Sync server port (if sync is configured). |
--no-sync | boolean | false | Disable the sync server even if configured. |
--no-watch | boolean | false | Disable schema file watching. |
What it starts
- Vite dev server -- Serves your application with hot module replacement (HMR).
- Kora sync server -- Starts automatically if
syncis configured inkora.config.ts. Not started for local-only apps. - Schema watcher -- Watches your schema file for changes and automatically regenerates TypeScript types.
Example
$ kora dev
Kora.js Dev Server
App: http://localhost:5173
Sync: ws://localhost:3001
Watching schema for changes...Configuration file
The kora dev command reads from kora.config.ts in the project root:
// kora.config.ts
import { defineConfig } from 'korajs/config'
export default defineConfig({
schema: './src/schema.ts',
dev: {
port: 5173,
sync: {
enabled: true,
port: 3001,
store: { type: 'sqlite', filename: './kora-dev.db' },
},
watch: {
enabled: true,
debounceMs: 300,
},
},
})kora migrate
Detects schema changes, generates migration files, and applies migrations to the local store.
Usage
kora migrate [options]Options
| Option | Type | Default | Description |
|---|---|---|---|
--dry-run | boolean | false | Show what would change without generating or applying migrations. |
--apply | boolean | false | Apply the migration immediately without prompting. |
--schema | string | Auto-detected | Path to schema file. |
--db | string | From config/default | SQLite path to use for --apply. |
--output-dir | string | kora/migrations | Migration output directory. |
--force | boolean | false | Skip breaking-change confirmation prompts. |
Workflow
The migrate command compares the current schema version with the previous version and generates a migration file describing the changes.
$ kora migrate
Detected schema change: v1 -> v2
Changes:
+ todos.priority (enum: low, medium, high, default: medium)
~ todos.tags (string -> array<string>)
- todos.legacyField (removed)
Generated migration: kora/migrations/002-add-priority-change-tags.ts
? Apply migration to local store? (y/n)Change types
| Symbol | Meaning |
|---|---|
+ | New field added to a collection. |
~ | Existing field type or configuration changed. |
- | Field removed from a collection. |
++ | New collection added. |
-- | Collection removed. |
Generated migration file
// kora/migrations/002-add-priority-change-tags.ts
import { defineMigration } from 'korajs'
export default defineMigration({
version: 2,
description: 'Add priority field, change tags to array',
up: {
// Automatically generated SQL
sql: [
`ALTER TABLE todos ADD COLUMN priority TEXT DEFAULT 'medium' CHECK(priority IN ('low','medium','high'))`,
`ALTER TABLE todos ADD COLUMN tags_new TEXT DEFAULT '[]'`,
// Data migration handled below
],
// Optional: transform existing data
transform: async (tx) => {
const rows = await tx.query('SELECT id, tags FROM todos')
for (const row of rows) {
const tagsArray = row.tags ? [row.tags] : []
await tx.execute(
'UPDATE todos SET tags_new = ? WHERE id = ?',
[JSON.stringify(tagsArray), row.id]
)
}
},
},
down: {
sql: [
`ALTER TABLE todos DROP COLUMN priority`,
],
},
})Dry run
$ kora migrate --dry-run
Detected schema change: v1 -> v2
Changes:
+ todos.priority (enum: low, medium, high, default: medium)
Would generate: kora/migrations/002-add-priority.ts
No changes applied (dry run).kora generate
Generates TypeScript types and other artifacts from your schema.
Usage
kora generate <subcommand> [options]Subcommands
kora generate types
Generates TypeScript type definitions from the current schema. These types provide full autocomplete and type checking for collection operations.
kora generate types [options]| Option | Type | Default | Description |
|---|---|---|---|
--output | string | 'kora/generated/types.ts' | Output file path. |
--schema | string | './src/schema.ts' | Path to the schema file. |
$ kora generate types
Generated TypeScript types from schema v1
Output: kora/generated/types.tsGenerated output
For a schema with a todos collection, the generated file contains:
// kora/generated/types.ts
// Auto-generated by Kora CLI. Do not edit manually.
export interface Todo {
id: string
title: string
completed: boolean
assignee: string | null
tags: string[]
notes: unknown // Rich text (Yjs Y.Text)
priority: 'low' | 'medium' | 'high'
dueDate: number | null
createdAt: number
}
export interface TodoInsert {
title: string
completed?: boolean
assignee?: string | null
tags?: string[]
priority?: 'low' | 'medium' | 'high'
dueDate?: number | null
// createdAt is auto-set, not included
}
export interface TodoUpdate {
title?: string
completed?: boolean
assignee?: string | null
tags?: string[]
priority?: 'low' | 'medium' | 'high'
dueDate?: number | null
}
// Collection type map used internally by Kora
export interface KoraCollections {
todos: {
record: Todo
insert: TodoInsert
update: TodoUpdate
}
}TIP
When using kora dev, types are regenerated automatically whenever your schema file changes. You only need to run kora generate types manually when not using the dev server.
kora deploy
Deploys your Kora application to a cloud platform. Handles Dockerfile generation, server bundling, client building, and platform-specific configuration in a single command.
Looking for a step-by-step walkthrough?
See the Deployment guide for a beginner-friendly tutorial that covers everything from installing the Fly CLI to verifying sync works.
Usage
kora deploy [options]
kora deploy status
kora deploy logs
kora deploy rollback [deployment-id]Options
| Option | Type | Default | Description |
|---|---|---|---|
--platform | string | (prompted) | Target platform: fly, railway, aws-ecs, aws-lightsail. Coming soon: render, docker, kora-cloud |
--app | string | (directory name) | Application name on the platform |
--region | string | iad | Deployment region (e.g., iad, lhr, syd, nrt) |
--prod | boolean | false | Deploy to production environment |
--confirm | boolean | false | Non-interactive mode — fails fast on missing data |
--reset | boolean | false | Delete all deploy state and generated artifacts |
Subcommands
kora deploy status
Shows the current deployment health, platform, app name, region, live URL, and sync URL.
kora deploy logs
Fetches recent logs from the deployed application.
kora deploy rollback [id]
Reverts the deployment to a previous version. If no id is provided, rolls back to the last known deployment.
Deployment Flow
When you run kora deploy, the following steps execute in order:
- Artifact generation — Creates
Dockerfile,.dockerignorein.kora/deploy/ - CLI detection — Verifies the platform CLI is installed (e.g.,
flyctl) - Authentication — Checks login state, prompts if needed
- Provisioning — Creates the app on the platform (idempotent — skips if exists)
- Server bundle — Bundles
server.tsinto a singleserver-bundled.jsusing esbuild - Client build — Runs
vite buildto produce static assets in.kora/deploy/dist/ - Platform config — Generates
fly.tomlorrailway.json - Deploy — Pushes to the platform and returns live URLs
Deploy State
State is persisted in .kora/deploy/deploy.json. On subsequent deploys, stored values (platform, app name, region) are reused automatically.
Reset with:
kora deploy --resetExamples
# Interactive first deploy
kora deploy
# Non-interactive (CI/CD)
kora deploy --platform=fly --app=my-kora-app --region=iad --confirm
# Deploy to AWS Lightsail
kora deploy --platform=aws-lightsail --app=my-app --region=us-east-1 --confirm
# Deploy to AWS ECS Fargate
kora deploy --platform=aws-ecs --app=my-app --region=us-east-1 --confirm
# Production deploy
kora deploy --prod --confirm
# Check status after deployment
kora deploy status
# View logs
kora deploy logs
# Rollback
kora deploy rollbackPrerequisites
| Platform | Requirement |
|---|---|
| Fly.io | Install flyctl, run fly auth login |
| Railway | Install @railway/cli, run railway login |
| AWS ECS | Install Docker Desktop (must be running), AWS CLI, run aws configure |
| AWS Lightsail | Install Docker Desktop (must be running), AWS CLI, lightsailctl plugin, run aws configure |
| Render | Coming soon |
| Docker (self-hosted) | Coming soon |
| Kora Cloud | Coming soon |
Project Requirements
Your project must have:
- A
package.jsonwith any@korajs/*dependency - A server entry file:
server.ts,server.js,src/server.ts, orsrc/server.js viteinstalled as a dev dependency (for client builds)
TIP
The deploy command stores all generated artifacts in .kora/deploy/. Add this to your .gitignore:
.kora/deploy/Global options
These options are available on all commands:
| Option | Description |
|---|---|
--help | Show help for the command. |
--version | Show the CLI version. |
--cwd <path> | Set the working directory. Defaults to the current directory. |
--verbose | Enable verbose logging output. |
kora --version
kora migrate --help
kora dev --cwd ./my-project