CLI Reference
forge new
Create a new project.
forge new [project-name] --template <id> [options]
| Option | Description |
|---|---|
--template <id> | Required template id copied from the embedded example catalog |
--output, -o <dir> | Output directory (defaults to project name) |
--no-lock | Skip generating Cargo.lock before the initial commit |
--include-skill | Run the skill installer non-interactively after project creation |
Supported template ids:
with-svelte/minimal
with-svelte/demo
with-svelte/realtime-todo-list
with-dioxus/minimal
with-dioxus/demo
with-dioxus/realtime-todo-list
# Small Svelte starter
forge new my-app --template with-svelte/minimal
# Real-time Dioxus example
forge new my-app --template with-dioxus/realtime-todo-list
# Custom output directory
forge new my-app --template with-svelte/demo --output /path/to/projects/my-app
Post-Scaffold Automation
After scaffolding the project directory, forge new automatically:
- Runs
git initand creates an initial commit - Runs
forge generate -yto produce frontend bindings - Runs
cargo fmtandbun run formatto normalize code style
If a formatter binary is not installed (e.g., bun is missing), the command prints a warning and continues. The project is still fully usable.
Development Environment
Start your development environment with Docker Compose:
# Start development environment
docker compose up --build
# Stop containers
docker compose down
# Stop and remove volumes
docker compose down -v
Requirements
| Tool | Minimum Version |
|---|---|
| Docker | 24+ (with Compose v2) |
Services
When running, the following services are available:
| Service | URL |
|---|---|
| Frontend | http://localhost:9080 |
| Backend | http://localhost:9081 |
PostgreSQL runs inside the Docker network and is not exposed to the host. The backend connects to it via the internal db hostname. To access the database directly, use docker compose exec:
docker compose exec db psql -U postgres -d my-app
docker compose exec db psql -U postgres -d my-app -c "SELECT * FROM users LIMIT 5"
Watch Scope
The backend container uses cargo-watch with an .ignore file (deny-all * with allowlist). Only these paths trigger backend restarts:
src/migrations/build.rsCargo.tomlCargo.lock.envforge.toml
forge test
Run backend unit tests and frontend Playwright tests.
forge test [options] [-- test-args...]
| Option | Description |
|---|---|
--skip-backend | Skip Rust backend unit tests |
--skip-frontend | Skip Playwright frontend tests |
--ui | Run Playwright in interactive UI mode |
--headed | Run in a visible browser window |
Trailing arguments after -- are forwarded to the Playwright test runner.
How it works
forge test runs a fully self-contained test cycle — no running dev server or docker compose needed:
- Builds the project with the
embedded-frontendfeature (frontend compiled in) - Starts a PostgreSQL container on a random port
- Starts the built binary on a random port
- Waits up to 120 seconds for
/_api/healthto return healthy - Runs the Playwright suite against that server
- Stops the binary and removes the PG container
Docker must be available for frontend tests. If you already have a server running (e.g. in CI), set FORGE_TEST_URL to skip the build/start steps entirely.
FORGE_TEST_URL
FORGE_TEST_URL=http://localhost:9081 forge test --skip-backend
When FORGE_TEST_URL is set, forge test skips the build, PG container, and binary start — it just checks that the URL is reachable and runs Playwright against it.
Playwright Browser Install
Playwright browser binaries are installed automatically on first run if missing.
# Run all tests
forge test
# Backend unit tests only
forge test --skip-frontend
# Frontend only, visible browser
forge test --skip-backend --headed
# Pass args through to Playwright
forge test -- --test my_specific_test
forge check
Validate project configuration and dependencies.
forge check [options]
| Option | Description |
|---|---|
--config, -c <path> | Path to forge.toml (default: ./forge.toml) |
Checks Performed
-
forge.toml validity and required sections
-
Cargo.toml and forge dependency
-
Directory structure (src/, src/schema/, src/functions/, migrations/)
-
Migration file naming and
-- @upmarkers -
Function files with forge macros (query, mutation, job, cron, workflow, daemon, webhook, mcp_tool)
-
Schema files with
#[forge::model]or standard derives (Serialize,FromRow) -
SQLx offline cache freshness (warns if
.sqlx/is stale relative to migration files) -
sqlx.tomlpresence andoffline = truevalidation -
Generated bindings staleness (diffs current bindings against freshly generated output)
-
Dioxus-specific checks (
frontend/Dioxus.tomlpresence,rustfmton frontend.rsfiles) -
Rust linting (cargo fmt, clippy)
-
Frontend configuration (if present)
-
Frontend linting (ESLint, Prettier)
# Full project check
forge check
# Custom config location
forge check --config ./config/forge.toml
forge generate
Generate frontend/runtime bindings from backend source code.
forge generate [options]
| Option | Description |
|---|---|
--force | Force regeneration even if files exist |
--output, -o <dir> | Output directory (defaults to the detected target path) |
--target <framework> | Frontend target (sveltekit or dioxus). Defaults to SvelteKit when no framework is auto-detected |
--src, -s <dir> | Source directory to scan (default: src) |
--yes, -y | Auto-accept prompts (useful for CI) |
Generated Files
SvelteKit target:
| File | Description |
|---|---|
| types.ts | TypeScript interfaces from Rust models and input DTOs |
| api.ts | Function bindings for queries, mutations, jobs, and workflows |
| stores.ts | Svelte store exports |
| runes.svelte.ts | Svelte 5 runes helpers |
| reactive.svelte.ts | Generated when queries exist; runes-based subscription functions |
| auth.svelte.ts | Generated when auth is configured |
| index.ts | Re-exports all modules |
Dioxus target:
| File | Description |
|---|---|
| types.rs | Rust types generated from models and input DTOs |
| api.rs | Typed RPC functions and hooks |
| mod.rs | Re-exports of generated modules plus forge-dioxus runtime items |
Backend handler/model files are authored in src/functions/ and src/schema/. forge generate then syncs generated frontend/runtime artifacts from that backend source of truth.
# Generate bindings for the detected target
forge generate
# Generate Dioxus bindings explicitly
forge generate --target dioxus
# Force regenerate everything
forge generate --force
# CI mode (no prompts)
forge generate -y
# Custom directories
forge generate --src ./backend/src --output ./web/src/lib/forge
forge migrate
Manage database migrations.
forge migrate [action] [options]
| Option | Description |
|---|---|
--config, -c <path> | Configuration file path (default: forge.toml) |
--migrations-dir, -m <dir> | Migrations directory (default: migrations) |
Actions
| Action | Description |
|---|---|
up | Run all pending migrations |
down [count] | Rollback the last N migrations (default: 1) |
status | Show migration status |
prepare | Run pending migrations, then refresh the .sqlx/ offline cache. Requires cargo-sqlx (cargo install sqlx-cli --locked); prints install instructions if missing |
Automatic migrations
During development, migrations run automatically when the backend starts. Pending migrations are applied before the server accepts requests, so you don't need to run forge migrate up manually.
Manual migration management
Since PostgreSQL is only accessible inside the Docker network, use docker compose exec to run migration commands or interact with the database directly:
docker compose exec db psql -U postgres -d my-app -c "SELECT * FROM forge_migrations ORDER BY id"
docker compose exec backend forge migrate down
docker compose exec backend forge migrate prepare
docker compose exec db psql -U postgres -d my-app
For production or CI, forge migrate connects via DATABASE_URL directly:
forge migrate up
forge migrate down
forge migrate up --config ./config/forge.toml --migrations-dir ./db/migrations
Migration File Format
Migration files must be named NNNN_name.sql (e.g., 0001_initial.sql) and contain -- @up marker.
-- @up
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
-- @down
DROP TABLE users;
Environment Variables
| Variable | Description | Used By |
|---|---|---|
DATABASE_URL | PostgreSQL connection string (set automatically by docker-compose during dev) | forge migrate, runtime |
RUST_LOG | Log level (e.g., info, debug, trace) | docker compose, runtime |
HOST | Backend host (default: 0.0.0.0) | docker compose, runtime |
PORT | Backend port (default: 9081) | docker compose, runtime |
Exit Codes
| Code | Description |
|---|---|
| 0 | Success |
| 1 | Error (configuration, validation, or runtime failure) |