Varel CLI Reference
The Varel Command Line Interface (CLI) provides powerful commands for scaffolding, database management, and project creation. This comprehensive reference covers all CLI commands and their usage.
Table of Contents
- Installation
- Global Commands
- Project Commands
- Scaffolding Commands
- Database Commands
- User Management
- Secret Management
- Complete Workflows
- Tips & Best Practices
- Troubleshooting
Installation
Step 1: Compile Varel CLI
# Clone Varel repository
git clone https://github.com/leafscale/varel.git
cd varel
# Compile CLI in production mode
v -prod varel
# This creates the 'varel' executable (2-3MB)
Step 2: Install Globally
# Create symlink to make 'varel' available globally
./varel symlink
# Output: ✓ Symlink created: /usr/local/bin/varel
# Verify installation
varel version
# Output: Varel version 0.1.0
Step 3: Verify
# View all available commands
varel --help
# Output shows all commands:
# - new, init, generate, db, user, symlink, version, help
Global Commands
version
Show Varel version information.
varel version
# Output:
# Varel version 0.1.0
# V compiler: 7e933328b6268cfc37d4d9734f03638193040c83
help
Display help information.
varel help
# or
varel --help
# Shows:
# - Usage information
# - All available commands
# - Examples
# - Documentation links
symlink
Create symlink in /usr/local/bin for global access.
./varel symlink
# Creates: /usr/local/bin/varel -> /path/to/varel
# Requires: sudo permissions
Project Commands
new
Create a new Varel application with complete project structure.
varel new <project_name>
Example:
varel new myshop
# Output:
# Creating new Varel project: myshop
#
# Initializing Varel project in /home/user/myshop...
# Created directory structure
# Created main.v
# Created v.mod
# Created config/config.toml
# Created controllers/home_controller.v
# Created controllers/api_controller.v
# Created README.md
# Created PROJECT_STRUCTURE.md
#
# ✓ Project myshop created successfully!
#
# Get started:
# cd myshop
# v run main.v
#
# Visit: http://localhost:8080
What Gets Created:
main.v- Application entry point with routesv.mod- V module definitionconfig/config.toml- Application configurationcontrollers/- Home and API controllersmodels/- Database models directoryviews/- VeeMarker templates directorymiddleware/- Custom middleware directorydb/migrations/- Database migrationsdb/seeds/- Seed datapublic/- Static files (CSS, JS, images)storage/- Logs and uploadstests/- Unit and integration tests
Next Steps:
cd myshop
v run main.v
# Visit http://localhost:8080
init
Initialize Varel in an existing directory.
cd existing_project
varel init
# Creates same structure as 'new' but in current directory
# Prompts before overwriting existing files
Use Case: Convert existing V project to Varel application.
Scaffolding Commands
generate scaffold
Generate a complete RESTful resource (controller, model, views, migrations, tests).
varel generate scaffold <ResourceName> <field>:<type> [<field>:<type> ...]
Supported Field Types:
| Type | SQL Type | Description | Example |
|---|---|---|---|
string |
VARCHAR(255) | Short text | name:string |
text |
TEXT | Long text, unlimited | description:text |
int |
INTEGER | Whole number | stock:int |
i64 |
BIGINT | Large integer | user_id:i64 |
decimal |
DECIMAL(10,2) | Money/prices | price:decimal |
float |
REAL | Floating point | rating:float |
bool |
BOOLEAN | True/false | published:bool |
date |
DATE | Date only | birthday:date |
datetime |
TIMESTAMP | Date and time | created_at:datetime |
timestamp |
TIMESTAMP | Alias for datetime | updated_at:timestamp |
Example:
varel generate scaffold Product name:string price:decimal description:text stock:int published:bool
# Generates:
#
# ✓ Created controllers/products_controller.v (with all 7 RESTful actions)
# ✓ Created models/product.v (with CRUD methods)
# ✓ Created views/products/index.html (list view)
# ✓ Created views/products/show.html (detail view)
# ✓ Created views/products/new.html (create form)
# ✓ Created views/products/edit.html (edit form)
# ✓ Created db/migrations/20251013123045_create_products.up.sql
# ✓ Created db/migrations/20251013123045_create_products.down.sql
# ✓ Created tests/controllers/products_controller_test.v
#
# ✓ Scaffold generated successfully!
#
# Next steps:
# 1. varel db migrate
# 2. Add routes to main.v
# 3. Visit http://localhost:8080/products
Using Route Prefixes:
The --prefix flag allows you to generate scaffolds for routes under a specific path prefix (e.g., admin sections):
varel generate scaffold User email:string role:string --prefix /admin
# Generates resources for /admin/users routes
# All generated URLs, redirects, and route comments use /admin prefix:
# - GET /admin/users (index)
# - GET /admin/users/new (new)
# - POST /admin/users (create)
# - GET /admin/users/:id (show)
# - GET /admin/users/:id/edit (edit)
# - PUT /admin/users/:id (update)
# - DELETE /admin/users/:id (destroy)
Prefix Examples:
# Admin panel resources
varel generate scaffold User email:string --prefix /admin
varel generate scaffold Product name:string price:f64 --prefix /admin
# API resources
varel generate scaffold Article title:string body:text --prefix /api/v1
# Dashboard resources
varel generate scaffold Widget name:string --prefix /dashboard
What Gets Prefixed:
When using --prefix, all generated code uses the prefix:
Views - All links and form actions include prefix
<a href="/admin/users"><form action="/admin/users">
Controllers - All redirects use prefix
ctx.redirect_temporary('/admin/users/' + id)
Tests - All test requests use prefix
app.get('/admin/users')app.post('/admin/users', data)
Route Registration Comments - Show correct routes
// app.get('/admin/users', ...)
Registering Prefixed Routes:
After generating with --prefix, register routes in main.v:
import controllers
mut user_ctrl := controllers.UserController{}
// Register admin routes with prefix
app.get('/admin/users', fn [user_ctrl] (mut ctx http.Context) http.Response {
return user_ctrl.index(mut ctx)
})!
app.get('/admin/users/new', fn [user_ctrl] (mut ctx http.Context) http.Response {
return user_ctrl.new(mut ctx)
})!
app.post('/admin/users', fn [user_ctrl] (mut ctx http.Context) http.Response {
return user_ctrl.create(mut ctx)
})!
// ... other routes
Complete Example with Multiple Types:
varel generate scaffold BlogPost \
title:string \
slug:string \
body:text \
excerpt:text \
published:bool \
view_count:int \
rating:float \
published_at:datetime \
author_id:i64
What Each File Contains:
Controller (
controllers/products_controller.v)index- List all productsshow- Show single productnew- Show create formcreate- Handle form submissionedit- Show edit formupdate- Handle update submissiondestroy- Delete product
Model (
models/product.v)- Struct definition with all fields
create()- Insert new recordfind()- Find by IDall()- Get all recordsupdate()- Update recorddelete()- Delete record
Views (
views/products/)index.html- Table with all productsshow.html- Product detailsnew.html- Creation form with validationedit.html- Edit form with current values
Migrations (
db/migrations/).up.sql- CREATE TABLE with all fields.down.sql- DROP TABLE (for rollback)
Tests (
tests/controllers/)- Tests for all 7 actions
- Database transaction rollback
generate migration
Generate a blank database migration.
varel generate migration <migration_name>
Example:
varel generate migration add_featured_to_products
# Output:
# ✓ Created db/migrations/20251013124530_add_featured_to_products.up.sql
# ✓ Created db/migrations/20251013124530_add_featured_to_products.down.sql
#
# Edit the migration files and run: varel db migrate
Generated Files:
db/migrations/20251013124530_add_featured_to_products.up.sql:
-- Write your UP migration here
-- Example: ALTER TABLE products ADD COLUMN featured BOOLEAN DEFAULT false;
db/migrations/20251013124530_add_featured_to_products.down.sql:
-- Write your DOWN migration here
-- Example: ALTER TABLE products DROP COLUMN featured;
Common Migration Patterns:
-- Add column
ALTER TABLE products ADD COLUMN featured BOOLEAN DEFAULT false;
-- Add index
CREATE INDEX idx_products_featured ON products(featured);
-- Add foreign key
ALTER TABLE orders ADD CONSTRAINT fk_orders_user_id
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-- Rename column
ALTER TABLE products RENAME COLUMN price TO unit_price;
-- Change column type
ALTER TABLE products ALTER COLUMN stock TYPE BIGINT;
-- Add unique constraint
ALTER TABLE users ADD CONSTRAINT unique_users_email UNIQUE (email);
Database Commands
db create
Create the database specified in config/config.toml.
varel db create
# Output:
# Creating database: myapp_development
# ✓ Database created successfully!
Configuration (config/config.toml):
[database]
host = "localhost"
port = 5432
database = "myapp_development"
user = "postgres"
password = ""
db migrate
Run all pending database migrations.
varel db migrate
# Output:
# Running migrations...
# ✓ 20251013120000_create_users.up.sql
# ✓ 20251013121000_create_products.up.sql
# ✓ 20251013122000_create_reviews.up.sql
# ✓ Migrations complete! (3 applied)
Migration Tracking:
Varel tracks applied migrations in a schema_migrations table:
SELECT * FROM schema_migrations;
-- version | applied_at
-- ----------------------------------- | ------------------------
-- 20251013120000_create_users | 2025-10-13 12:05:23
-- 20251013121000_create_products | 2025-10-13 12:05:24
-- 20251013122000_create_reviews | 2025-10-13 12:05:25
db rollback
Rollback the last applied migration.
varel db rollback
# Output:
# Rolling back last migration...
# ✓ 20251013122000_create_reviews.down.sql
# ✓ Rollback complete!
Note: Only rolls back ONE migration at a time. Run multiple times to rollback multiple migrations.
db status
Show migration status (applied vs pending).
varel db status
# Output:
# Migration Status:
# [x] 20251013120000_create_users.up.sql (applied)
# [x] 20251013121000_create_products.up.sql (applied)
# [ ] 20251013122000_create_reviews.up.sql (pending)
# [ ] 20251013123000_add_featured_to_products.up.sql (pending)
#
# Applied: 2
# Pending: 2
db drop
Drop the database (destructive!).
varel db drop
# Prompts for confirmation:
# WARNING: This will permanently delete the database 'myapp_development'
# Are you sure? (yes/no): yes
#
# Dropping database: myapp_development
# ✓ Database dropped
Use Case: Clean up test database or start fresh.
User Management
user create
Create a new user with bcrypt-hashed password.
varel user create <username> <password>
Example:
varel user create admin mySecurePassword123
# Output:
# Creating user: admin
# ✓ User created successfully!
# Username: admin
# Password hash: $2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYIr9OQvL2u
# Stored in: config/users.toml
Storage (config/users.toml):
[[users]]
username = "admin"
password_hash = "$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYIr9OQvL2u"
roles = ["admin"]
created_at = "2025-10-13T12:30:45Z"
user list
List all users from config/users.toml.
varel user list
# Output:
# Users:
# - admin (roles: admin)
# - editor (roles: editor, user)
# - viewer (roles: user)
#
# Total: 3 users
user delete
Delete a user from config/users.toml.
varel user delete <username>
# Example:
varel user delete editor
# Output:
# Deleting user: editor
# ✓ User deleted successfully!
Secret Management
Varel provides cryptographically secure secret key generation for session encryption and other security features.
secret generate
Generate a random secret key for session encryption or other security purposes.
Basic Usage:
# Generate 64-character secret (32 bytes, default)
varel secret generate
# Output: 9e40bd70d1a083bef588513f9fe2e4569e9e401eb181ea0d348da55f543337c2
With Custom Length:
# Generate 128-character secret (64 bytes)
varel secret generate --length 64
# Output: 34899e24d2ad0aa66fbb2d45da12abf372af406e1f9c087aa9dfc9c6757240e6afe9c68551b56580b686d37842193224fdb91be16be66826868b3d7f512810c0
Replace Secret in config.toml:
# Generate and automatically update config/config.toml
varel secret generate --replace
# Output:
# ✓ Updated secret_key in config/config.toml
# New secret: 05fc043d8f61efbc0aaa9f153f23623a9bc7bd83d29af82f182edc5c147cb401
Options:
--length, -l <bytes>: Length in bytes (default: 32, produces 64 hex characters)--replace, -r: Replace secret_key in config/config.toml automatically
Security Features:
- Uses
crypto.randfor cryptographically secure random number generation - Minimum 16 bytes (32 characters) enforced
- Hex-encoded output (safe for TOML config files)
- Default 32 bytes provides 256 bits of entropy
Use Cases:
- Session Secret Rotation: Periodically rotate session secrets in production
- New Environments: Generate unique secrets for staging/production
- Security Incident Response: Quickly generate new secrets after compromise
- Development: Test with different secret keys
Best Practices:
- Development: Auto-generated secret during
varel newis sufficient - Production: Use
--replaceto generate a unique secret before deployment - Secret Rotation: Regularly rotate secrets (e.g., every 90 days)
- Never Commit Secrets: Add
config/config.tomlto.gitignoreor use environment variables
Example Workflow:
# Before deploying to production
cd myapp
varel secret generate --replace
# Verify the new secret
grep secret_key config/config.toml
# secret_key = "92d7e1d6cd4158fd92c58f717871f32ff88b11a2e41644de20f9e5abadd62302"
# Deploy to production
git add config/config.toml
git commit -m "Rotate session secret for production"
git push production master
Note: New projects created with varel new automatically generate a unique secret key. You only need to use this command for:
- Rotating secrets in existing projects
- Generating additional secrets for other purposes
- Creating environment-specific secrets
Complete Workflows
Workflow 1: New Project from Scratch
# 1. Create new project
varel new blog
cd blog
# 2. Create database
varel db create
# 3. Generate Post resource
varel generate scaffold Post title:string body:text published:bool author:string
# 4. Run migrations
varel db migrate
# 5. Create admin user
varel user create admin admin123
# 6. Start application
v run main.v
# 7. Visit http://localhost:8080/posts
Workflow 2: Add Feature to Existing Project
# 1. Generate new resource
varel generate scaffold Comment post_id:i64 author:string body:text
# 2. Run migration
varel db migrate
# 3. Add routes in main.v
# (Register comments controller)
# 4. Test
v run main.v
Workflow 3: Database Schema Changes
# 1. Generate migration
varel generate migration add_email_to_users
# 2. Edit migration file
# db/migrations/YYYYMMDDHHMMSS_add_email_to_users.up.sql:
# ALTER TABLE users ADD COLUMN email VARCHAR(255) UNIQUE;
# db/migrations/YYYYMMDDHHMMSS_add_email_to_users.down.sql:
# ALTER TABLE users DROP COLUMN email;
# 3. Run migration
varel db migrate
# 4. Check status
varel db status
# 5. If needed, rollback
varel db rollback
Workflow 4: Clean Development Database
# Manually reset database (drop + create + migrate)
varel db drop
varel db create
varel db migrate
Tips & Best Practices
Scaffolding
DO:
- ✅ Use singular, PascalCase names:
Product,BlogPost,UserProfile - ✅ Keep initial scaffolds simple, add complexity via migrations
- ✅ Review generated code before using
- ✅ Customize templates to fit your needs
DON'T:
- ❌ Use plural names:
Products(useProduct) - ❌ Use snake_case:
blog_post(useBlogPost) - ❌ Generate with too many fields initially (add via migrations)
Migrations
DO:
- ✅ Test migrations on development database first
- ✅ Write reversible migrations (proper
.down.sql) - ✅ Use transactions (PostgreSQL does this automatically for DDL)
- ✅ Add indexes for foreign keys and frequently queried columns
- ✅ Check status before migrating:
varel db status
DON'T:
- ❌ Edit applied migrations (create new migration instead)
- ❌ Skip writing
.down.sqlfiles - ❌ Run migrations directly on production without testing
- ❌ Ignore migration errors
Database Commands
DO:
- ✅ Use
varel db statusfrequently to check state - ✅ Back up production database before migrations
- ✅ Use
varel db dropandvarel db createfreely in development - ✅ Version control your migrations
DON'T:
- ❌ Use
varel db dropon production without backups - ❌ Run migrations without reviewing SQL first
- ❌ Forget to commit migration files to git
User Management
DO:
- ✅ Use strong passwords (minimum 12 characters)
- ✅ Limit number of admin accounts
- ✅ Rotate passwords regularly
- ✅ Store
config/users.tomlsecurely (add to.gitignore)
DON'T:
- ❌ Commit passwords to git
- ❌ Use simple passwords like "password" or "admin123"
- ❌ Share admin credentials
Troubleshooting
Command Not Found
Problem: varel: command not found
Solutions:
# 1. Check if symlink exists
ls -la /usr/local/bin/varel
# 2. Recreate symlink
cd /path/to/varel
./varel symlink
# 3. Add to PATH manually
export PATH=$PATH:/path/to/varel
# Add to ~/.bashrc or ~/.zshrc for persistence
Database Connection Errors
Problem: Failed to connect to database
Solutions:
# 1. Check PostgreSQL is running
systemctl status postgresql
# or
pg_isready
# 2. Verify config/config.toml settings
cat config/config.toml
# 3. Test connection manually
psql -h localhost -U postgres -d myapp_development
# 4. Check environment variables
echo $DB_HOST $DB_PORT $DB_NAME $DB_USER $DB_PASSWORD
Migration Fails
Problem: Migration fails with SQL error
Solutions:
# 1. Check the SQL syntax in migration file
cat db/migrations/YYYYMMDDHHMMSS_migration_name.up.sql
# 2. Test SQL manually
psql -h localhost -U postgres -d myapp_development
# Run the SQL from migration file
# 3. Fix the migration file
# Edit db/migrations/YYYYMMDDHHMMSS_migration_name.up.sql
# 4. Rollback if already applied
varel db rollback
# 5. Re-run migration
varel db migrate
Scaffold Generates Invalid Code
Problem: Generated code doesn't compile
Solutions:
# 1. Check field types are supported
varel generate scaffold --help
# 2. Use proper naming (singular, PascalCase)
varel generate scaffold Product # ✅ Correct
varel generate scaffold products # ❌ Wrong
# 3. Report bug if it's a framework issue
# GitHub: https://github.com/leafscale/varel/issues
Permission Denied
Problem: Permission denied when creating symlink
Solutions:
# 1. Use sudo
sudo ./varel symlink
# 2. Or install to local bin (no sudo required)
mkdir -p ~/.local/bin
cp varel ~/.local/bin/
# Add to PATH: export PATH=$PATH:~/.local/bin
Environment Variables
Override config values with environment variables:
# Database
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=myapp_production
export DB_USER=postgres
export DB_PASSWORD=secure_password
# Server
export PORT=8080
export VAREL_ENV=production
# Run with environment variables
varel db migrate
See Also
- Getting Started Guide - Learn Varel basics
- Controllers Guide - Understanding controllers
- Database Guide - Database operations
- Templates Guide - View templates
- Deployment Guide - Production deployment
Getting Help
- CLI Help:
varel --helporvarel <command> --help - Documentation: See
docs/guides/directory - Examples: Check
examples/directory - Issues: Report bugs at https://github.com/leafscale/varel/issues
- Discord: Join V language Discord for support
Varel CLI makes building web applications fast and enjoyable! 🚀