CLI Reference
Complete reference for Radish CLI v0.20.x commands and workflows.
Installation
Global Installation
npm install -g radish-cli
Local Development
# From the CLI repo root
npm install
npm link # or: npm install -g .
Check Version
radish-cli --version
Commands
init
Initialize a new Radish project with Claude Code skills.
radish-cli init [dir] [options]
Arguments:
[dir]- Project directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--name <name> | App name | Directory name |
--desc <description> | App description | - |
Examples:
# Initialize in current directory
radish-cli init
# Initialize in a specific directory with a name
radish-cli init ./my-project --name my-app --desc "A task manager"
create
Interactive mode that walks through app setup with prompts for name, location, and features. Optionally launches an AI-powered wizard to generate blueprints from natural language.
radish-cli create
Running create without a subcommand enters interactive mode. Use the subcommands below for non-interactive usage.
Regeneration safety
Generators are safe to re-run, with one rule worth knowing: files an app is expected to own are seeded once and then left alone.
| command | preserved after first generation |
|---|---|
create skeleton | src/hooks.server.ts, src/app.css, src/routes/+page.svelte, src/routes/+layout.svelte, .env |
create admin | src/lib/admin-config.ts, src/routes/(public)/login/+page.svelte, +page.server.ts |
Each run lists by name what it declined to overwrite, so a regeneration says what it did not touch rather than staying silent.
Everything else — models, repositories, services, contracts, metadata, routes, admin CRUD
pages — is regenerated in place. Edits to those are lost on the next run. Put
project-specific behaviour in the files above, or in
.claude/commands/radish.local.md, which is also never overwritten.
This is currently a fixed list. It is being replaced by hash comparison, so that files an app has not modified keep receiving improvements while modified ones are preserved — see
workspace/planning/regeneration-contract.md.
create app
Generate a complete full-stack application (skeleton + datalayer + UI layer + admin panel).
radish-cli create app <appName> [directory] [options]
Arguments:
<appName>- Application name (used for directory, database, cookie prefix)
Options:
| Option | Description | Default |
|---|---|---|
--out-dir <path> | Output directory | . |
--blueprints <path> | Path to blueprints directory | ./blueprints |
--description <desc> | App description | A full-stack SvelteKit application |
--mongo-db <name> | MongoDB database name | Derived from app name |
--seed | Seed the database after generation | false |
--mock | Generate mock data after seeding | false |
--mock-count <number> | Number of mock records per entity | 10 |
--dry | Dry run (show what would be generated) | false |
--in-place | Deprecated — pass . as the directory argument instead | false |
Examples:
# Full app from blueprints with seed and mock data
radish-cli create app my-app --blueprints ./blueprints --seed --mock
# Custom mock count
radish-cli create app my-app --blueprints ./blueprints --seed --mock --mock-count 20
# Custom output directory
radish-cli create app my-app --out-dir ./projects --blueprints ./my-blueprints
# Generate into current directory
radish-cli create app my-app .
# Dry run to preview
radish-cli create app my-app --dry
What gets generated:
- SvelteKit skeleton (package.json, svelte.config.js, Dockerfile, docker-compose.yml, .gitlab-ci.yml)
- Datalayer (contracts, models, repos, services, routes)
- Admin panel (dashboard, user management, entity CRUD)
- UI layer (pages, layouts, components from ui.json if present)
- Setup route at
/setupfor first-time admin creation - SEO infrastructure (sitemap.xml, robots.txt, llms.txt)
create datalayer
Generate a data layer with full control over options.
radish-cli create datalayer <outDir> [options]
Arguments:
<outDir>- Output directory (e.g.,.,./my-app)
Options:
| Option | Description | Default |
|---|---|---|
--app-name <name> | Friendly app name (used for DB name and UI title) | Directory name |
-s, --schema <path> | Path to blueprint schema file (JSON or YAML) | - |
--preset <name> | Built-in sample: todo or library | library |
--db <adapter> | Database adapter: mongo or prisma | mongo |
--api-adapter <adapter> | HTTP framework: sveltekit or fastify | sveltekit |
--api-symlink <path> | Symlink API routes to existing app directory | - |
--docker <mode> | Docker compose setup: none, mongo, or full | none |
--seed | Auto-seed database after generation | false |
--db-url <url> | Database connection URL for seeding | - |
--features <list> | Comma-separated feature flags: cms, grants, datasets | - |
--stack <stack> | Target stack: node or laravel | node |
--dry | Dry run (show files without writing) | false |
Examples:
# Basic generation with library preset
radish-cli create datalayer ./my-app
# With custom schema
radish-cli create datalayer . --schema ./blueprints/app.types.json
# Integrated mode with API symlink
radish-cli create datalayer . --api-symlink ./my-sveltekit-app
# Docker compose with MongoDB
radish-cli create datalayer . --docker mongo
# Laravel stack
radish-cli create datalayer . --stack laravel --schema ./blueprints/types.json
# With database seeding
radish-cli create datalayer . --seed --db-url mongodb://localhost:27017/mydb
# Dry run to preview files
radish-cli create datalayer . --dry
create skeleton
Create a complete SvelteKit app skeleton with all config files.
radish-cli create skeleton <appName> [options]
Arguments:
<appName>- Application name
Options:
| Option | Description | Default |
|---|---|---|
--out-dir <path> | Output directory | . |
--description <desc> | App description | A full-stack SvelteKit application |
--mongo-db <name> | MongoDB database name | Derived from app name |
--framework <name> | UI framework: sveltekit | sveltekit |
--dry | Dry run (show files without writing) | false |
create uilayer
Generate UI layer (pages, layouts, components) from blueprints.
radish-cli create uilayer <outDir> [options]
Arguments:
<outDir>- Output directory (will create SvelteKit app)
Options:
| Option | Description | Default |
|---|---|---|
--ui-schema <path> | Path to ui.json blueprint | - |
--types-schema <path> | Path to types.json blueprint (for entity metadata) | - |
--framework <name> | UI framework: sveltekit | sveltekit |
--dry | Dry run (show files without writing) | false |
create auth
Generate auth-only data layer (User/Role/Permission + auth system).
radish-cli create auth <outDir> [options]
Arguments:
<outDir>- Output directory
Options:
| Option | Description | Default |
|---|---|---|
--app-name <name> | Friendly app name (used for DB name and UI title) | - |
--db <adapter> | Database adapter: mongo or prisma | mongo |
--full | Generate complete project (scripts, docs, etc.) | false |
--api-adapter <adapter> | HTTP adapter: sveltekit or fastify | sveltekit |
--api-symlink <path> | Create symlink from target app to generated API routes | - |
--docker <mode> | Docker compose: none, mongo, or full | none |
--dry | Dry run | false |
create admin
Generate admin panel with CRUD pages for all entities.
radish-cli create admin <outDir> [options]
Arguments:
<outDir>- Output directory (the app root)
Options:
| Option | Description | Default |
|---|---|---|
-s, --schema <path> | Path to types blueprint (JSON or YAML) | - |
--app-name <name> | App display name | - |
--dry | Dry run (show files without writing) | false |
generate
Generate JSON blueprints from a natural language description using AI. Requires webhooks configured in .radish.config.json.
radish-cli generate [options]
Running generate without a subcommand runs the full pipeline: app, types, roles, ui, components, theme (same as generate all).
Subcommands: all, app, types, roles, ui, components, theme
generate all (default)
Generate all blueprints in sequence (app -> types -> roles -> ui -> components -> theme).
Options:
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file (txt, md, etc.) | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--run | Immediately run create app after generation | false |
Examples:
# Generate all blueprints interactively
radish-cli generate --name my-app --desc "A task manager"
# Generate from a spec file
radish-cli generate --name my-app --file spec.md
# Generate and immediately create the app
radish-cli generate --name my-app --file prd.txt --run
generate app
Generate just the app blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
generate types
Generate just the types blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--app <path> | Path to app.json for context | - |
generate roles
Generate just the roles blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--app <path> | Path to app.json for context | - |
--types <path> | Path to types.json for context | - |
generate ui
Generate just the UI blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--app <path> | Path to app.json for context | - |
--types <path> | Path to types.json for context | - |
generate components
Generate just the components blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--app <path> | Path to app.json for context | - |
--types <path> | Path to types.json for context | - |
--ui <path> | Path to ui.json for context | - |
generate theme
Generate just the theme blueprint.
| Option | Description | Default |
|---|---|---|
--name <name> | Project name | - |
--desc <description> | App description | - |
-f, --file <path> | Read description from a file | - |
--out <dir> | Output directory for blueprints | ./blueprints |
--app <path> | Path to app.json for context | - |
--components <path> | Path to components.json for context | - |
Examples (subcommands):
radish-cli generate app --name my-app --file prd.txt
radish-cli generate types --app ./blueprints/my-app.app.json
radish-cli generate roles --app ./blueprints/my-app.app.json --types ./blueprints/my-app.types.json
radish-cli generate ui --app ./blueprints/my-app.app.json --types ./blueprints/my-app.types.json
radish-cli generate components --app ./blueprints/app.json --types ./blueprints/types.json --ui ./blueprints/ui.json
validate
Validate Radish blueprint files (JSON or YAML) against schemas.
radish-cli validate [app-path] [options]
Arguments:
[app-path]- Path to the application directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
-t, --types <path> | Path to types blueprint file | - |
-r, --roles <path> | Path to roles blueprint file | - |
-a, --app <path> | Path to app blueprint file | - |
-v, --verbose | Show detailed validation errors | false |
Examples:
# Validate all blueprints in current directory
radish-cli validate
# Validate specific blueprints
radish-cli validate --types ./blueprints/app.types.json --roles ./blueprints/app.roles.json
# Verbose output
radish-cli validate -v
doctor
Run comprehensive project health checks (validation, drift, orphans, search).
radish-cli doctor [app-path] [options]
Arguments:
[app-path]- Path to the application directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
-v, --verbose | Show detailed findings | false |
Examples:
radish-cli doctor
radish-cli doctor ./my-app --verbose
verify
Verify that generated code matches the current blueprint.
radish-cli verify [app-path] [options]
Arguments:
[app-path]- Path to app directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--verbose | Show detailed information | false |
--strict | Exit 1 on any finding (foreign files, warnings) | false |
Exit codes:
0- Generated code matches blueprint1- Generated code out of sync with blueprint (or any finding in strict mode)
Examples:
# Basic verification
radish-cli verify
# Verbose output with details
radish-cli verify --verbose
# Strict mode for CI
radish-cli verify --strict || exit 1
info
Display manifest information about generated code.
radish-cli info [app-path] [options]
Arguments:
[app-path]- Path to app directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--json | Output as JSON | false |
Examples:
# Human-readable info
radish-cli info
# JSON output for scripting
radish-cli info --json
radish-cli info --json | jq '.radishVersion'
browse
Launch the data browser for a Radish-generated application.
radish-cli browse [app-path] [options]
Arguments:
[app-path]- Path to the Radish app directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
-p, --port <port> | Port to run browser on | 5173 |
--build | Build browser for production instead of dev mode | false |
Examples:
# Launch data browser for current directory
radish-cli browse
# Launch on custom port
radish-cli browse ./my-app --port 3000
# Build for production
radish-cli browse --build
seed
Seed the database with roles, an admin user, and sample data.
radish-cli seed [app-path] [options]
Arguments:
[app-path]- Path to app directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--db-url <url> | MongoDB connection URL (overrides MONGO_URL env var) | From .env |
--fixtures <path> | Path to custom fixtures directory | - |
--sample | Also seed sample data for custom entities | false |
--content | Seed ContentBlock records from components.json defaultContent | false |
--sync-roles | Only sync roles and permissions (non-destructive, production-safe) | false |
--generate | Generate fixture templates and save to fixtures/ directory | false |
Behavior notes:
- Role seeding populates permissions from the blueprint's
roles.json - When a
/setuproute exists (generated bycreate app), admin user creation is skipped -- the setup wizard handles first-time admin onboarding instead - Reads
MONGO_URLfrom the app's.envfile if--db-urlis not specified
Examples:
# Full seed (roles + admin + sample data)
radish-cli seed
# Sync roles only after blueprint changes (production-safe)
radish-cli seed --sync-roles
# Seed with sample data for all entities
radish-cli seed --sample
# Seed ContentBlock records
radish-cli seed --content
# Generate fixture templates
radish-cli seed --generate
# With explicit database URL
radish-cli seed --db-url mongodb://localhost:27017/myapp
# With custom fixtures
radish-cli seed --fixtures ./my-fixtures
mock
Generate mock/fake data for entities using Faker.js or AI.
radish-cli mock <app-path> [options]
Arguments:
<app-path>- Path to the application
Options:
| Option | Description | Default |
|---|---|---|
-e, --entity <name> | Entity name to generate mock data for | - |
-a, --all | Generate mock data for all entities | false |
-c, --count <number> | Number of records to generate per entity | 10 |
-o, --output <file> | Output file path (instead of inserting into database) | - |
--overrides <json> | JSON object with field overrides | - |
--resolve-refs | Resolve reference fields by fetching existing entities | false |
--ai | Use AI to generate realistic, context-aware mock data instead of Faker.js | false |
--verbose | Show detailed error messages | false |
Examples:
# Generate mock data for all entities
radish-cli mock ./my-app --all
# Generate 50 records for a specific entity
radish-cli mock ./my-app --entity Task --count 50
# Output to file instead of database
radish-cli mock ./my-app --all --output ./mock-data.json
# AI-generated realistic data
radish-cli mock ./my-app --entity Product --ai
# With field overrides
radish-cli mock ./my-app --entity Task --overrides '{"status":"active"}'
schema
Output JSON schemas for blueprint validation.
radish-cli schema <subcommand> [options]
Subcommands: types, roles, app, ui, all
Each subcommand outputs the corresponding JSON schema to stdout.
Options (all subcommands):
| Option | Description | Default |
|---|---|---|
-p, --pretty | Pretty-print the JSON output | false |
Examples:
# Output types schema (compact)
radish-cli schema types
# Pretty-print the UI schema
radish-cli schema ui --pretty
# Output all schemas
radish-cli schema all --pretty
# Pipe to a file
radish-cli schema types --pretty > types.schema.json
convert
Convert blueprints between YAML and JSON formats.
radish-cli convert <path> [options]
Arguments:
<path>- File or directory to convert
Options:
| Option | Description | Default |
|---|---|---|
--to <format> | Target format: json or yaml | json |
--validate | Validate after conversion | false |
--dry | Show what would be converted without writing | false |
--keep | Keep original files | true |
--no-keep | Remove original files after conversion | - |
Examples:
# Convert YAML blueprints to JSON
radish-cli convert ./blueprints
# Convert a single file to YAML
radish-cli convert ./blueprints/app.types.json --to yaml
# Convert and validate
radish-cli convert ./blueprints --validate
# Dry run
radish-cli convert ./blueprints --dry
wizard
Launch the AI-powered blueprint wizard.
radish-cli wizard [options]
Options:
| Option | Description | Default |
|---|---|---|
--local | Run wizard locally instead of web service | false |
--web | Run wizard in web mode (opens browser) | false |
--web-url <url> | Custom wizard service URL | https://wizard.radish.dev |
-p, --port <port> | Port for local wizard | 1455 |
--output <path> | Directory to save blueprints | Current directory |
See Wizard Reference for details on local and web modes.
Examples:
# Launch local wizard
radish-cli wizard --local
# Launch web wizard
radish-cli wizard --web
# Local wizard on custom port with output directory
radish-cli wizard --local --port 3000 --output ./blueprints
migrate
Manage schema migrations.
radish-cli migrate <subcommand> [options]
Subcommands: generate, status, up, down
migrate generate
Detect schema changes and generate a migration file.
radish-cli migrate generate [app-path] [options]
| Option | Description | Default |
|---|---|---|
--db-url <url> | MongoDB connection URL | From .env |
migrate status
Show pending migrations.
radish-cli migrate status [app-path] [options]
| Option | Description | Default |
|---|---|---|
--db-url <url> | MongoDB connection URL | From .env |
migrate up
Run pending migrations.
radish-cli migrate up [app-path] [options]
| Option | Description | Default |
|---|---|---|
--db-url <url> | MongoDB connection URL | From .env |
--dry | Show what would be executed without running | false |
migrate down
Rollback the last applied migration.
radish-cli migrate down [app-path] [options]
| Option | Description | Default |
|---|---|---|
--db-url <url> | MongoDB connection URL | From .env |
Examples:
# Detect changes and generate migration
radish-cli migrate generate
# Check pending migrations
radish-cli migrate status
# Run migrations (dry run first)
radish-cli migrate up --dry
radish-cli migrate up
# Rollback last migration
radish-cli migrate down
search
Manage search indexes.
radish-cli search <subcommand> [options]
Subcommands: reindex, status, doctor
search reindex
Rebuild search indexes from MongoDB data.
radish-cli search reindex [app-path] [options]
| Option | Description | Default |
|---|---|---|
--entity <name> | Reindex a specific entity only | - |
--db-url <url> | MongoDB connection URL | From .env |
--batch-size <n> | Documents per batch | 500 |
--force | Drop and recreate indexes (destructive) | false |
--dry-run | Show what would happen without making changes | false |
search status
Check search engine health and index status.
radish-cli search status [app-path]
search doctor
Diagnose drift between blueprint search fields and live Typesense schema.
radish-cli search doctor [app-path]
Examples:
# Rebuild all search indexes
radish-cli search reindex
# Reindex a specific entity
radish-cli search reindex --entity Product
# Dry run
radish-cli search reindex --dry-run
# Check search health
radish-cli search status
# Diagnose search drift
radish-cli search doctor
deploy
Deploy application to Coolify.
radish-cli deploy [app-path] [options]
Arguments:
[app-path]- Path to the application (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--prod | Deploy to production | default |
--staging | Deploy to staging | false |
--preview | Create a preview deployment | false |
--target <name> | Deploy to a named target | - |
--tag <tag> | Specific version tag to deploy | - |
--restart | Just restart without changing version | false |
--via <provider> | Deployment provider: coolify or hub | coolify |
deploy init
Set up Coolify app for deployment.
radish-cli deploy init [app-path] [options]
Options (non-interactive / CI mode):
| Option | Description | Default |
|---|---|---|
-i, --instance <name> | Coolify instance name (from cfy config) | - |
--server <uuid> | Server UUID | - |
--project <uuid> | Project UUID | - |
--name <name> | Application name | From package.json |
--image <image> | Docker registry image | - |
--domain <domain> | Application domain | - |
--env <name> | Coolify environment name | production |
--target <name> | Deploy target name | production |
--mongo-url <url> | Set MONGO_URL env var on Coolify app | - |
--auto-secrets | Auto-generate SESSION_SECRET and RADISH_ENCRYPTION_KEY | false |
Interactive mode (default): Prompts for server, project, environment, domain, and registry settings using your configured Coolify instances.
Non-interactive mode: Pass all required flags for CI/scripting use.
Prerequisites:
cfyCLI installed (npm install -g @abeedoo/cfy)- At least one Coolify instance configured (
cfy setup)
Examples:
# Interactive provisioning
radish deploy init
# Non-interactive for CI
radish deploy init \
--server <uuid> --project <uuid> \
--name my-app --image registry.example.com/my-app \
--domain my-app.example.com --auto-secrets
# Deploy latest tag to production
radish deploy
# Deploy specific version
radish deploy --tag v1.2.3
# Deploy to staging
radish deploy --staging
# Just restart, no version change
radish deploy --restart
What deploy init does:
- Creates a Docker image app on Coolify
- Sets environment variables (MONGO_URL, SESSION_SECRET, etc.)
- Configures health checks
- Saves target config to
.radish.deploy.json - Auto-generates
SESSION_SECRETandRADISH_ENCRYPTION_KEY(with--auto-secrets)
clean
Remove all Radish-generated code and configuration.
radish-cli clean [app-path] [options]
Arguments:
[app-path]- Path to app directory (default:.)
Options:
| Option | Description | Default |
|---|---|---|
--dry-run | Show what would be removed without removing | false |
--force | Skip confirmation prompts | false |
Examples:
# Clean with confirmation
radish-cli clean
# Dry run to see what would be removed
radish-cli clean --dry-run
# Force clean without prompts
radish-cli clean --force
analytics
Manage analytics tracking settings.
radish-cli analytics <subcommand>
Subcommands:
| Subcommand | Description |
|---|---|
status | Show current analytics tracking status |
enable | Enable analytics tracking |
disable | Disable analytics tracking |
Hub Integration (coming soon)
The following commands are stubs for future Radish Hub integration:
| Command | Description |
|---|---|
login | Authenticate with Radish Hub (--token <token> for non-interactive) |
apps ls | List your apps on Radish Hub |
apps link | Link local project to a Hub app |
apps info | Show linked app details |
status | Show deployment status |
Workflows
Initial Setup
Create your first Radish project:
# 1. Create project directory
mkdir my-app && cd my-app
# 2. Create blueprint
mkdir blueprints
cat > blueprints/my-app.types.json << 'EOF'
{
"version": 1,
"defaults": {
"owned": true,
"timestamps": true
},
"entities": {
"Task": {
"plural": "tasks",
"fields": {
"title": { "type": "string", "required": true },
"done": { "type": "boolean", "default": false }
},
"filters": ["done"]
}
}
}
EOF
# 3. Generate full app
radish-cli create app my-app --blueprints ./blueprints --seed
# 4. Launch data browser to explore
radish-cli browse
Regeneration
Regenerate after blueprint changes:
# 1. Edit blueprint
vim blueprints/my-app.types.json
# 2. Regenerate (same command as initial generation)
radish-cli create datalayer . --schema blueprints/my-app.types.json
# 3. Review changes
git diff .radish/
# 4. Verify manifest
radish-cli verify --verbose
# 5. Test your app
npm test
# 6. Commit blueprint + generated code together
git add blueprints/ .radish/
git commit -m "feat: add description field to Task"
Blueprint Verification
Check if generated code matches your current blueprint:
# Automated verification
radish-cli verify # Exit 0 if match, exit 1 if mismatch
radish-cli verify --strict # Exit 1 on any finding (foreign files, warnings)
# Display manifest information
radish-cli info # Human-readable format
radish-cli info --json # Machine-readable JSON output
# Full health check
radish-cli doctor --verbose # Validation + drift + orphans + search
Version Management
Check Generated Version
# View top-level manifest
cat .radish/MANIFEST.json
# View datalayer-specific manifest
cat .radish/lib/datalayer/MANIFEST.json
Update CLI Version
# 1. Update CLI
npm update -g radish-cli
# 2. Check new version
radish-cli --version
# 3. Regenerate
radish-cli create datalayer . --schema blueprints/app.types.json
# 4. Review changes
git diff .radish/
# 5. Commit
git commit -m "chore: regenerate with radish-cli v0.20.x"
Semantic Versioning
Radish CLI follows semantic versioning (MAJOR.MINOR.PATCH):
| Version Change | Risk | Description | Action Required |
|---|---|---|---|
| MAJOR (0.x -> 1.x) | High | Breaking changes in generated API | Review CHANGELOG, update code, test thoroughly |
| MINOR (0.19.x -> 0.20.x) | Low-Medium | New features, non-breaking | Safe to regenerate, optional feature adoption |
| PATCH (0.20.0 -> 0.20.1) | Low | Bug fixes only | Safe to regenerate immediately |
Schema Migrations
Safe Changes (No Migration Required)
These changes are backward-compatible:
- Adding optional fields
- Adding new entities
- Changing field labels/descriptions
- Adding indexes
Action: Regenerate and deploy immediately.
Breaking Changes (Migration Required)
These changes require database migration:
- Adding required fields
- Changing field types
- Removing fields
- Renaming fields
Migration Workflow:
# 1. Generate migration
radish-cli migrate generate
# 2. Review the generated migration file
cat migrations/*.mjs
# 3. Dry run
radish-cli migrate up --dry
# 4. Apply
radish-cli migrate up
# 5. Update blueprint and regenerate
radish-cli create datalayer . --schema blueprints/app.types.json
Migration Decision Matrix
| Change | DB Migration? | Code Changes? | Example |
|---|---|---|---|
| Add optional field | No | No | bio: { optional: true } |
| Add required field | Yes | Maybe | priority: { required: true } |
| Remove field | Optional | No | Delete from JSON |
| Rename field | Yes | Yes | Copy data to new field |
| Change type | Yes | Yes | string -> int |
| Add entity | No | No | New entity in JSON |
| Add index | No | No | Auto-created |
Troubleshooting
"Cannot find module" after regeneration
Cause: Package structure changed or dependencies not installed.
Solution:
# Reinstall dependencies in generated packages
cd .radish/lib/datalayer/contracts && npm install
cd ../server && npm install
Tests failing after regeneration
Cause: Breaking change in generated API.
Solution:
- Review CHANGELOG for breaking changes
- Update test code to use new APIs
- Check for schema naming convention changes
Database validation errors
Cause: Schema changed but database has old data.
Solution:
- Run migration (
radish-cli migrate up) before deploying - Ensure all required fields have values
- Check field type compatibility
"File already exists" error
Cause: Generating to wrong directory or permissions issue.
Solution:
- Verify output path is correct
- Check directory permissions
- Use
--dryflag to preview first
Best Practices
1. Commit Blueprint + Generated Code Together
git add blueprints/ .radish/
git commit -m "feat: add Task entity"
Makes code review easier and keeps blueprint changes visible alongside generated changes.
2. Test After Every Regeneration
npm test # Run full test suite
Even "safe" changes can have unexpected effects.
3. Use Version Control
# Never regenerate without committing first
git status
git commit -m "checkpoint before regeneration"
radish-cli create datalayer .
Easy rollback if regeneration causes issues.
4. Pin CLI Version in CI
{
"name": "Install Radish CLI",
"run": "npm install -g radish-cli@0.20.3"
}
Ensures consistent builds across environments.
Dependencies
cfy CLI
The deploy init command requires cfy (@abeedoo/cfy) -- a Coolify v4 API client that manages Coolify instances.
npm install -g @abeedoo/cfy
cfy setup # Configure your first Coolify instance
Instance credentials are stored at ~/.coolify-cli/config (per-user, not committed).
Environment Variables
| Variable | Description | Default |
|---|---|---|
RADISH_APP_PATH | Path to app (browse command) | Current directory |
PORT | Browse/wizard port | 5173 |
MONGO_URL | Database connection string | mongodb://localhost:27017 |
SESSION_SECRET | Secret for signing session cookies (preferred) | - |
RADISH_ENCRYPTION_KEY | Fallback secret when SESSION_SECRET is not set | - |
RADISH_HUB_URL | Hub URL for telemetry reporting | - |
RADISH_HUB_TOKEN | Hub auth token for telemetry push | - |
Generated Files
After create app
A full-stack application includes all of the below:
my-app/
├── package.json # App dependencies
├── svelte.config.js # Path aliases for @generated/*
├── Dockerfile # Debian slim base, node healthcheck
├── docker-compose.yml # expose (not ports), pull_policy: always
├── .gitlab-ci.yml # Kaniko build, CI_REGISTRY vars, deploy trigger
├── .env / .env.example # Environment configuration
├── src/
│ ├── hooks.server.ts # sequence(telemetry, rateLimit, idempotency, auth)
│ ├── routes/
│ │ ├── setup/ # First-run admin creation wizard
│ │ ├── (auth)/ # Login, register (centered layout)
│ │ ├── (public)/ # Public pages (auth optional)
│ │ ├── (app)/ # Authenticated pages (redirect to login)
│ │ ├── admin/ # Admin panel (dashboard, users, entities)
│ │ ├── sitemap.xml/ # Dynamic sitemap
│ │ └── robots.txt/ # Dynamic robots.txt
│ └── lib/
│ └── datalayer/ # Generated datalayer (see below)
└── blueprints/ # Source blueprints
After create datalayer
The datalayer package (at .radish/lib/datalayer/):
datalayer/
├── MANIFEST.json # Datalayer-specific metadata
├── package.json # @generated/datalayer package
├── contracts/ # Zod schemas & TypeScript types
│ ├── common.ts
│ ├── {entity}.ts
│ ├── index.ts
│ └── metadata/ # Field metadata for runtime introspection
├── core/ # Core infrastructure
│ ├── auth/ # Authentication (signed sessions, guards)
│ ├── db/ # Database connection
│ ├── middleware/ # Rate limiting, idempotency
│ ├── models/ # MongoDB models
│ ├── repos/ # Data access layer
│ └── seeds/ # Database seeders
├── telemetry/ # Observability (always-on)
│ ├── adapters/ # ConsoleAdapter, MultiAdapter
│ ├── tracked-fetch.ts # Instrumented fetch for external APIs
│ ├── hub-reporter.ts # Background push to Radish Hub
│ ├── correlation.ts # Correlation ID management
│ ├── logger.ts # Structured logger
│ └── middleware.ts # Request telemetry
├── routes/ # HTTP API routes (SvelteKit)
│ └── api/v1/ # Versioned API endpoints
├── services/ # Business logic with permissions
└── docs/ # App-specific generated documentation
├── API.md # Complete API reference
├── services.md # Service layer docs
├── types.md # TypeScript types
├── roles.md # Auth & permissions
├── AI_CONTEXT.md # AI-friendly summary
└── openapi.json # OpenAPI 3.0 spec
Next Steps
- Blueprint Reference - Learn blueprint syntax
- Generated Code - Understand what gets generated
- Getting Started - Step-by-step tutorial