Reference

CLI

Every kitr command and flag.

Run kitr with pnpm kitr <command>, or pnpm dlx @kitr/kitr <command> without installing. Every command runs from flags alone; nothing prompts.

A global install (pnpm add -g @kitr/kitr) lets you type kitr directly. Inside a project it hands over to the project's own copy, so the version in package.json is the one that edits your files. KITR_GLOBAL=1 skips the handover.

Project commands

Command What it does
kitr new <dir> --kit <kit> Create a project from a kit: kitr new my-app --kit app. See Create a project.
kitr add <pkg...> Install a package and wire it into the project: kitr add jobs. See Add a package.
kitr add <type> <name> Add a platform: kitr add web admin --mode spa. See Platforms.
kitr remove <pkg...> Undo add, then list the files that still import the package.
kitr <pkg>:<cmd> Run a command a package adds: kitr jobs:work.
kitr doctor Check the project for problems. Exits 1 on errors.
kitr info Print a JSON summary of the project.
kitr upgrade Move every kitr package to one version: kitr upgrade --to 0.2.0.

Create a project

Kits: blank, app, fullstack, server, and the presets saas, site, realtime, desktop, tauri and mobile. Kits shows what each one writes.

Flag What it does
--kit <kit> The kit to start from. Any npm package that is a kit works: --kit @acme/starter.
--platform <name=type,...> Replace the kit's platforms: --platform site=web,api=server.
--mode, --pwa, --runtime, --targets, --port Set the platforms' options.
--pm <npm|pnpm|yarn|bun> The package manager to use.
--no-install, --no-git Skip installing dependencies or creating a git repository.
--registry <url|path> Copy components from another registry.
--force Write into a folder that is not empty.

Add a package

kitr add installs the package, registers its provider in kitrrc.ts, writes config/<pkg>.ts and updates AGENTS.md. It also adds the packages it needs: adding api adds server and logger.

Questions a package asks are flags: kitr add jobs --no-worker. --yes takes the defaults, and kitr add <pkg> --help lists the questions. --dry-run shows the changes without writing them.

Any npm package with a kitr setup module works: kitr add @acme/stripe. See Package contract.

Check and upgrade

kitr doctor checks kitrrc.ts against package.json, missing config files, imports that should go through an @kitr/* package, and versions that drift from the tested set. --json prints the result for scripts; --strict turns warnings into errors.

kitr upgrade also moves upstream libraries to the versions that kitr release was tested with. It lists major bumps without applying them; --majors applies them.

Platforms

Command What it does
kitr dev [names...] Run every platform in development, or only the named ones: kitr dev site.
kitr build [names...] Build for production into dist/<name>/.
kitr start [names...] Serve the builds. kitr serve is an alias.
kitr platforms List platforms, their options and the config files each build uses. types, scaffold <name> and remove <name> are subcommands.
kitr config <name> [option] [value] Read or set one platform option: kitr config site port 4000, kitr config admin without analytics,consent.

To pick a few, list them (kitr build admin api) or use --filter=admin,api. Both do the same thing.

With more than one platform, kitr dev prefixes each line with the platform's name ([site]). KITR_<NAME>_<OPTION> overrides any option at run time: KITR_SITE_PORT=4000 kitr dev site.

The server without Vite imports config/index.ts, which kitr add regenerates. When a platform has a config/<platform>/ folder or a without list, that file picks the build's object with forBuildPlatform(); see Config per platform.

Workspaces

A repository with several kitr apps lists them in kitr.workspace.ts at its root:

// kitr.workspace.ts
import { defineWorkspace } from '@kitr/kitr'

export default defineWorkspace({
  apps: { www: 'apps/www', app: 'apps/app', phone: 'apps/phone' },
})

Each app is a complete kitr project with its own kitrrc.ts. Shared code goes in ordinary workspace packages.

Command What it does
kitr workspace List the apps with their platforms and packages.
kitr dev, kitr start Run in every app at once.
kitr build, kitr generate, kitr typecheck, kitr doctor, ... Run in every app, one after another. Exits 1 if any fails.
kitr build phone Run in one app: kitr build phone ios builds its ios platform. kitr build --filter=phone,www runs in those two.
kitr --app phone <command> Run any command in one app without cd. KITR_APP=phone does the same.

Inside an app directory every command is the app's own, as if there were no workspace.

Generators

kitr make:<kind> <name> writes one file and registers it where it belongs. kitr make lists the generators your project has.

A nested name makes a folder: make:controller admin/users writes server/controllers/admin/users-controller.ts. --dry-run shows what would change, and --force overwrites a file. To change a template, kitr eject stub <kind> copies it to stubs/<kind>.ts. Project structure explains where each kind of file lives.

Command Writes
make Nothing. Lists every generator and the path it writes.
make:page projects app/pages/projects.tsx, and .page('/projects', { lazy }) appended to app/routes.ts
make:page projects/:id app/pages/projects/id.tsx, and .page('/projects/$id', { lazy })
make:layout admin app/layouts/admin.tsx with <Outlet />, and .layout('_admin', { lazy }, (admin) => admin) appended to app/routes.ts
make:component user-card app/components/user-card.tsx
make:form project app/components/forms/project-form.tsx
make:hook toggle app/hooks/use-toggle.ts
make:store cart app/stores/cart.ts (createKitrStore)
make:queries projects app/queries/projects.ts (keys, queries, mutation with effects)
make:query projects/list app/actions/projects/list.ts (defineQuery('projects.list', ...))
make:mutation projects/create app/actions/projects/create.ts (defineMutation('projects.create', ...))
make:validator project app/validators/project.ts (create/update zod schemas)
make:exception payment-failed app/exceptions/payment-failed-error.ts (a KitrError subclass)
make:provider analytics app/providers/analytics-provider.ts, listed in kitrrc.ts providers
make:channel chat app/channels/chat.ts (defineChannel)
make:controller projects [--resource] server/controllers/projects-controller.ts (with all CRUD methods for --resource)
make:service billing server/services/billing-service.ts (a class to bind in a provider)
make:middleware audit server/middleware/audit.ts
make:job send-digest server/jobs/send-digest.ts (defineJob). Needs the jobs package.
make:mail welcome server/mail/welcome.tsx (defineMail with a preview)
make:test projects test/projects.test.ts, run by the project's vitest (createTestApp)

A package can add its own generators. See Building packages.

Components

Command What it does
kitr ui add <name...> Copy components into app/components/ui: kitr ui add button card.
kitr ui list List the components in the registry.

Components come from kitr's own registry. To use another shadcn-format registry, pass --registry <url\|path> or set KITR_REGISTRY.

API and server

Command What it does
kitr api:sync Write openapi.json and routes.gen.ts from server/routes.ts. kitr generate runs it for you.
kitr routes:list Print every route: method, path, name.
kitr css:types Write a .d.ts beside every *.module.css.

Type generation

kitr generate writes the project's generated files: types under .kitr/ (ignored by git), each package's own files, such as the API route table, then the app's own steps from generate in kitrrc.ts. You rarely run it yourself: kitr dev, kitr build, kitr new and kitr add run it, and the dev server reruns it when a file changes.

Command What it does
kitr generate Write every generated file.
kitr generate --check Exit non-zero when a file is stale, without writing. Skips package and app steps. For CI.
kitr generate --quiet Print only failures; an app step's output shows only when it fails.
kitr generate --watch Regenerate on change, for editors without the dev server.
kitr typecheck kitr generate, then tsc --noEmit. The kits' typecheck script.
kitr types Write only the .kitr/ types. Takes --check, --watch and --only <name>.
Generator Reads Writes
platforms platforms in kitrrc.ts .kitr/platforms.d.ts, so app.platform has your platform names.
actions app/actions/**/*.ts .kitr/actions.ts, so useQuery('projects.list') is typed.

Add your own step

An app adds a step of its own, such as a content index, under generate in kitrrc.ts. run is a shell command or a function:

// kitrrc.ts
import { defineKitrConfig } from '@kitr/kitr/app'

export default defineKitrConfig({
  packages: [],
  providers: [],
  generate: [{ name: 'content', run: 'node scripts/content.mjs', watch: ['content/**/*.md'] }],
})

It runs after the type generators and the package steps, in kitr generate, kitr dev, kitr build and kitr typecheck, and kitr doctor lists it. Add your own code has the details.

Add a type generator to a package

A package adds a generator with defineTypes() and points its setup module at it with the types hook:

// packages/<name>/src/types.ts
import { defineTypes } from '@kitr/core'

export default defineTypes({
  name: 'channels',
  watch: (rc) => [`${rc.directories.app ?? 'app'}/channels/**/*.ts`],
  generate: (ctx) => [{ file: 'channels.d.ts', content: render(ctx.glob('app/channels', '**/*.ts')) }],
})
// packages/<name>/src/kitr.ts
import { definePackage } from '@kitr/core/package'

export default definePackage({
  name: 'channels',
  add(ctx) {
    ctx.types.enable()
  },
  types: () => import('./types'),
})

generate returns { file, content } pairs relative to .kitr/, and the runner writes them. watch lists the files that rerun it in dev.

Leaving kitr

kitr eject stubs copies every generator template into your project. kitr eject all also prints the import rewrites that remove kitr: each kitr/* import maps to the library it re-exports.