CLI Commands¶
Ralph includes a powerful command-line interface (CLI) to help you manage your database schema and generate code. This guide covers all available commands and their usage.
Overview¶
Ralph's CLI can be compiled once and reused without recompilation when you add new migrations. This is because migrations are plain SQL files that are read and executed at runtime.
For setup instructions, see the CLI Customization Guide.
Once set up, you can run the CLI with:
crystal run ./ralph.cr -- [command]
# Or build once and run directly (recommended)
crystal build ralph.cr -o bin/ralph
./bin/ralph [command]
Database Commands¶
These commands manage your database lifecycle, from creation to migrations and seeding.
db:create¶
Creates the database defined in your configuration or specified via the --database flag.
For PostgreSQL, this connects to the default postgres database to execute the CREATE DATABASE command.
Usage:
Example (SQLite):
Example (PostgreSQL):
db:drop¶
!!! danger "Warning" This command will permanently delete your database and all its data. Use with extreme caution.
Drops the database. For PostgreSQL, this command will attempt to terminate all existing connections to the target database before dropping it.
Usage:
Example:
db:migrate¶
Runs all pending SQL migrations from the migrations directory.
Usage:
Options:
-e, --env ENV: Environment (default: development)-d, --database URL: Database URL-m, --migrations DIR: Migrations directory (default:./db/migrations)
Example:
$ ./ralph db:migrate
Running: 20260101120000_create_users
Running: 20260101120100_create_posts
Ran 2 migration(s)
db:rollback¶
Rolls back the most recently applied migration.
Usage:
Options:
--steps=N: Roll back N migrations (default: 1)
Examples:
# Roll back one migration
./ralph db:rollback
# Roll back three migrations
./ralph db:rollback --steps=3
db:rollback:all¶
Rolls back all applied migrations.
Usage:
db:status¶
Shows the status of all migrations (applied or pending).
Usage:
Example output:
Migration status:
Status Migration ID
--------------------------------------------------
[ UP ] 20260107000001
[ UP ] 20260107000002
[ DOWN ] 20260107000003
db:version¶
Shows the current migration version (the most recently applied migration).
Usage:
db:seed¶
Loads and executes the seed file (./db/seeds.cr). The seed file is a regular Crystal file that runs independently, so it must require Ralph and configure the database connection.
Usage:
Creating a Seed File:
Create db/seeds.cr in your project:
#!/usr/bin/env crystal
require "ralph"
require "ralph/backends/sqlite" # or postgres
require "../src/models/*"
# Configure database (must match your app's configuration)
Ralph.configure do |config|
config.database = Ralph::Database::SqliteBackend.new("sqlite3://./db/development.sqlite3")
end
# Use find_or_create_by for idempotent seeds
admin = User.find_or_create_by({"email" => "[email protected]"}) do |u|
u.name = "Administrator"
u.role = "admin"
end
puts "Seeded #{User.count} users"
!!! tip "Idempotent Seeds"
Use find_or_create_by or find_or_initialize_by to make your seeds idempotent—safe to run multiple times without creating duplicates. See CRUD Operations for details.
db:reset¶
Drops, creates, migrates, and seeds the database in one command.
Usage:
db:setup¶
Creates the database and runs all migrations.
Usage:
db:pool¶
Shows connection pool status and configuration.
Usage:
db:pull¶
Generates model files from an existing database schema. Useful for creating models from a legacy database.
Usage:
Options:
--tables=TABLE1,TABLE2: Only pull specific tables--skip=TABLE1,TABLE2: Skip specific tables--overwrite: Overwrite existing model files--dry-run: Preview without generating files--models DIR: Output directory for models
Examples:
# Pull all tables
./ralph db:pull
# Pull specific tables
./ralph db:pull --tables=users,posts
# Preview without generating
./ralph db:pull --dry-run
db:generate¶
Generates a migration from the difference between your models and the database schema.
Usage:
Options:
--name=NAME: Migration name (default: auto_migration)--dry-run: Preview changes without generating-m, --migrations DIR: Output directory
Example:
$ ./ralph db:generate --name=add_status_to_orders
Analyzing models...
Found 3 model(s)
Introspecting database...
Found 2 table(s)
Changes detected:
+ CREATE TABLE orders
+ ADD COLUMN users.status (string)
Generated: ./db/migrations/20260108123456_add_status_to_orders.sql
Generator Commands¶
g:migration¶
Creates a new SQL migration file.
Usage:
Example:
$ ./ralph g:migration create_users
Created migration: ./db/migrations/20260108123456_create_users.sql
The generated file looks like:
-- Migration: create_users
-- Created: 2026-01-08 12:34:56 UTC
-- +migrate Up
-- Write your UP migration SQL here
-- +migrate Down
-- Write your DOWN migration SQL here (reverses the UP)
g:model¶
Generates a model file and an accompanying SQL migration.
Usage:
Field Types:
string- VARCHAR(255)text- TEXTinteger- INTEGERbigint- BIGINTfloat- DOUBLE PRECISIONboolean- BOOLEANtimestamp- TIMESTAMPjson/jsonb- JSON/JSONBuuid- UUID
Example:
$ ./ralph g:model User name:string email:string active:boolean
Created model: User
- ./src/models/user.cr
- ./db/migrations/20260108123456_create_users.sql
The generated migration:
-- Migration: Create users
-- Generated: 2026-01-08 12:34:56 UTC
-- +migrate Up
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
active BOOLEAN NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- +migrate Down
DROP TABLE IF EXISTS users;
Global Options¶
-e, --env ENV: Specifies the environment (e.g.,development,test,production). Default isdevelopment.-d, --database URL: Overrides the database URL from configuration.-m, --migrations DIR: Overrides the migrations directory path. Default is./db/migrations.--models DIR: Overrides the models directory path. Default is./src/models.-h, --help: Shows the help message.version: Shows the Ralph version.
Configuration¶
The CLI looks for database configuration in several places, in order of precedence:
- The
-dor--databaseflag. - The
DATABASE_URLenvironment variable. - The
POSTGRES_URLenvironment variable. - The
SQLITE_URLenvironment variable. - A default SQLite URL based on the environment:
sqlite3://./db/#{environment}.sqlite3.
The CLI automatically detects the database type from the URL scheme (postgres://, postgresql://, or sqlite3://).
Common Workflows¶
Starting a New Project¶
- Set up the CLI (see Customization Guide).
- Run
./ralph db:setupto create the database. - Generate your first model:
./ralph g:model User name:string email:string. - Run
./ralph db:migrate.
Iterating on Schema¶
- Create a migration:
./ralph g:migration add_role_to_users. - Edit the generated SQL file in
db/migrations/. - Run
./ralph db:migrate. - If you made a mistake, run
./ralph db:rollback, fix the file, and migrate again.
Converting from Crystal DSL Migrations¶
If you have existing Crystal-based migrations, you can:
- Run your existing migrations to bring the database up to date
- Create new migrations as SQL files going forward
- Optionally export the SQL from your Crystal migrations and create equivalent
.sqlfiles
Migration File Format¶
Ralph uses SQL migration files with special comment markers:
-- +migrate Up
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL
);
-- +migrate Down
DROP TABLE IF EXISTS users;
For complex statements with semicolons (functions, triggers), use:
For statements that can't run in a transaction:
See Migrations Introduction for full details.
Troubleshooting¶
"Unknown command"¶
Ensure you are using the correct command name. Check ./ralph help for the list of available commands.
"Database creation not implemented"¶
Ralph supports database creation for SQLite and PostgreSQL. Ensure your database URL scheme is supported (sqlite3://, postgres://, or postgresql://).
"No migrations have been run"¶
This message appears when calling db:version on an empty database. Run db:migrate to apply migrations.
"Migration file not found"¶
Ensure your migration files:
- Are in the db/migrations/ directory (or the directory specified with -m)
- Have a .sql extension
- Follow the naming pattern: TIMESTAMP_name.sql (e.g., 20260108123456_create_users.sql)