code-docs/packages/cli.md
The command-line interface for Lowdefy. Provides commands for initializing, developing, building, and running Lowdefy applications.
The CLI is the primary entry point for developers working with Lowdefy:
lowdefy initInitialize a new Lowdefy project in the current directory.
lowdefy init
Creates:
lowdefy.yaml - Main configuration file.gitignore - Ignores build artifactslowdefy devStart the development server with hot reload.
lowdefy dev [options]
Options:
| Option | Description | Default |
|---|---|---|
--config-directory | Config directory path | Current directory |
--dev-directory | Dev server directory | .lowdefy/dev |
--port | Server port | 3000 |
--no-open | Don't open browser | Opens browser |
--watch | Additional paths to watch | - |
--watch-ignore | Paths to ignore | - |
--ref-resolver | Custom ref resolver path | - |
--log-level | Log level (error/warn/info/debug) | info |
What happens:
@lowdefy/build on configlowdefy buildBuild a production-ready application.
lowdefy build [options]
Options:
| Option | Description | Default |
|---|---|---|
--config-directory | Config directory path | Current directory |
--server-directory | Server output directory | .lowdefy/server |
--no-next-build | Skip Next.js build | Builds Next.js |
--ref-resolver | Custom ref resolver path | - |
--log-level | Log level | info |
What happens:
@lowdefy/build on confignext build on the serverlowdefy startStart a built production application.
lowdefy start [options]
Options:
| Option | Description | Default |
|---|---|---|
--config-directory | Config directory path | Current directory |
--server-directory | Server directory | .lowdefy/server |
--port | Server port | 3000 |
--log-level | Log level | info |
lowdefy init-dockerGenerate a Dockerfile for containerized deployment.
lowdefy init-docker [options]
lowdefy init-vercelGenerate Vercel deployment scripts.
lowdefy init-vercel [options]
lowdefy upgradeUpgrade a Lowdefy app by walking through migration prompts that handle breaking changes between versions.
lowdefy upgrade [options]
Options:
| Option | Description | Default |
|---|---|---|
--to | Target version | Latest stable |
--plan | Show upgrade plan without executing | - |
--resume | Resume interrupted upgrade | - |
--config-directory | Config directory path | Current directory |
--log-level | Log level | info |
What happens:
lowdefy.yaml@lowdefy/codemods@latest from npm (reuses fetchNpmTarball)resolveChain.jsexecutePhase.jslowdefy.yaml version after each phase┌─────────────────┐
│ upgrade command │
│ (upgrade.js) │
└────────┬────────┘
│
▼
┌──────────────────────┐ ┌───────────────────────────┐
│ fetchNpmTarball │────▶│ @lowdefy/codemods@latest │
│ (reused from CLI) │ │ → .lowdefy/codemods/ │
└──────────────────────┘ └───────────────────────────┘
│
▼
┌──────────────────────┐
│ resolveChain.js │ Reads registry.json, computes
│ │ version chain using semver ranges
└────────┬─────────────┘
│
▼
┌──────────────────────┐
│ executePhase.js │ For each phase in the chain:
│ │ presents prompts in order
└────────┬─────────────┘
│
▼
┌──────────────────┐
│ handlePrompt.js │ Reads .md prompt, presents options:
│ │ clipboard / view / skip
│ │ AI tool detection
└────────┬─────────┘
│
▼
┌──────────────────────┐
│ upgradeState.js │ Writes .lowdefy/upgrade-state.json
│ │ for --resume and build-time warnings
└──────────────────────┘
| Module | Purpose |
|---|---|
commands/upgrade/upgrade.js | Command entry point — fetch codemods, orchestrate |
commands/upgrade/resolveChain.js | Version chain resolution from registry.json using semver ranges |
commands/upgrade/executePhase.js | Phase orchestrator — presents prompts in order |
commands/upgrade/handlePrompt.js | Presents prompt options — clipboard, AI detection, manual guide |
commands/upgrade/upgradeState.js | Reads/writes .lowdefy/upgrade-state.json for resume and build warnings |
fetchNpmTarball — Reused from the existing server download flow to fetch @lowdefy/codemods@latest.validateVersion.js — Extended to check for .lowdefy/upgrade-state.json and warn about pending codemods during build and dev.@lowdefy/codemods — External package containing all migration prompts and registry. See codemods.md.Why @lowdefy/codemods@latest: The codemods package contains the full migration history for all versions. Fetching @latest ensures the chain resolver has complete coverage. The --to flag controls the target version, not the codemods package version. This mirrors how getServer.js decouples CLI version from server version.
Why prompts instead of scripts: AI tools execute find-and-replace reliably from markdown prompts. Prompts can be updated after publishing (they're just text), work with any AI tool, and one format eliminates the need for script execution infrastructure (child_process.fork, backup logic, etc.).
Why lazy AI detection: The CLI checks for AI tool environment indicators only when presenting a prompt. Detection never blocks the upgrade flow — it may add options in future, falls back to clipboard/manual otherwise.
All options can be set via environment variables:
| Variable | Corresponding Option |
|---|---|
LOWDEFY_DIRECTORY_CONFIG | --config-directory |
LOWDEFY_DIRECTORY_DEV | --dev-directory |
LOWDEFY_DIRECTORY_SERVER | --server-directory |
LOWDEFY_LOG_LEVEL | --log-level |
LOWDEFY_DISABLE_TELEMETRY | --disable-telemetry |
PORT | --port |
┌─────────────────┐
│ lowdefy CLI │
│ (Commander.js) │
└────────┬────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Commands │
├──────────┬──────────┬──────────┬──────────┬─────────┬────────┤
│ init │ dev │ build │ start │ upgrade │ init-* │
└──────────┴────┬─────┴────┬─────┴────┬─────┴────┬────┴────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────┐
│ Server Package Download │
│ (from npm: @lowdefy/server-*) │
└──────────────────────────────────┘
│
▼
┌──────────────────────────────────┐
│ @lowdefy/build │
│ (config compilation) │
└──────────────────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Next.js Server │
│ (dev server or production) │
└──────────────────────────────────┘
/commands/| Directory | Purpose |
|---|---|
init/ | Project initialization logic |
dev/ | Development server orchestration |
build/ | Production build orchestration |
start/ | Production server startup |
upgrade/ | Codemod upgrade orchestration |
init-docker/ | Dockerfile generation |
init-vercel/ | Vercel scripts generation |
/utils/| Module | Purpose |
|---|---|
runCommand.js | Command wrapper with error handling |
createPluginTypesMap.js | Generate plugin type maps |
The CLI uses createCliLogger from @lowdefy/logger/cli (ora spinners, colored terminal output). The logger is available as context.logger with four level methods (error, warn, info, debug). Color is passed via merge objects: logger.info({ color: 'blue' }, 'text'). Spin/succeed: logger.info({ spin: true }, 'Building...').
When running the dev server, the CLI pipes the manager process stdout through createStdOutLineHandler which parses pino JSON lines, reconstructs errors, and routes them to logger[level](error) or logger[level]({ color/spin/succeed }, msg) for rendering.
See @lowdefy/logger for the full logging architecture.
The CLI downloads @lowdefy/server and @lowdefy/server-dev on demand:
The build package (@lowdefy/build) is also downloaded:
The CLI enforces Node.js >= 18:
if (Number(nodeMajorVersion) < 18) {
throw new Error('...');
}
This ensures compatibility with:
# 1. Create new project
npx lowdefy init
# 2. Develop locally
npx lowdefy dev
# 3. Build for production
npx lowdefy build
# 4. Run production server
npx lowdefy start
# Or deploy to Vercel/Docker
npx lowdefy init-vercel # or init-docker
The dev server watches:
.yaml, .yml, .json, .json5 in config directory--watchnode_modules, .git, .lowdefyOn change:
@lowdefy/build