-
Notifications
You must be signed in to change notification settings - Fork 0
CLI Reference
lagodev ships two interchangeable binaries — lago and artisan —
built from cmd/lago and cmd/artisan respectively. They share the
entire command tree.
go install github.com/devituz/lagodev/cmd/lago@latest # → lago
# or
go install github.com/devituz/lagodev/cmd/artisan@latest # → artisanThis guide uses lago; substitute artisan if you prefer.
| Command | Description |
|---|---|
lago new <name> |
Scaffold a brand-new project directory |
lago init |
Write lago.json with the default path layout |
lago env:init |
Write a documented starter .env file |
lago env |
Print the active env (sensitive values redacted) |
lago env --show-secrets |
Show passwords/keys in clear text |
lago key:generate |
Write a fresh APP_KEY (AES-256, base64) to .env
|
Scaffolds a complete project:
lago new blog
cd blog
go run .Drops in main.go, go.mod, lago.json, .env, config/,
routes/, and stub package directories — everything needed to start
running make:* against it.
Writes lago.json in the current working directory:
{
"paths": {
"models": "models",
"migrations": "migrations",
"factories": "factories",
"seeders": "seeders",
"tests": "tests"
}
}Adjust to fit your layout — see Configuration.
Writes ./.env with every variable the framework understands,
commented out where you don't need to set them.
lago env:init # uses ./.env
lago env:init --path .env.example
lago env:init --force # overwrite an existing filePrints the active environment. Sensitive values (anything matching
PASSWORD, SECRET, KEY, TOKEN) are replaced with ***.
lago env # redacted
lago env --show-secrets # full outputGenerates a 32-byte AES-256 key and writes it to APP_KEY= in the
specified .env. Refuses to overwrite a non-empty APP_KEY unless
--force is passed.
lago key:generate # writes to ./.env
lago key:generate --env .env.prod --force
lago key:generate --print-only # stdout only, no file touched
lago key:generate --show # write AND print to stdoutAll make:* commands accept --fields=name:type[:modifier] (comma
list), --force (overwrite), and --dir (output directory override).
| Command | Description |
|---|---|
lago make:model |
Generate a model struct (embed orm.Model) |
lago make:migration |
Generate a timestamped migration with up/down |
lago make:factory |
Generate a faker-powered factory |
lago make:seeder |
Generate a seeder registered in init()
|
lago make:test |
Generate a test scaffold using lagotest.SQLite
|
lago make:service |
Generate a framework-agnostic CRUD service |
lago make:controller |
Generate a REST controller wrapping a service |
lago make:crud |
One-shot: model + migration + factory + seeder + test |
lago make:model User # minimal: just the struct
lago make:model Post -m -f -s -t -c \
--fields="title:string,body:text,published:bool:default(false)"-mfsc compose. Each flag adds another artifact:
| Flag | Generates |
|---|---|
-m, --migration |
Migration file |
-f, --factory |
Factory |
-s, --seeder |
Seeder |
-t, --test |
Test scaffold |
-c, --controller |
Service + controller |
-a, --all |
All of the above |
lago make:controller PostController --model=PostGenerates a *web.Context-style REST controller (Index, Show,
Store, Update, Destroy) that delegates to a PostService. Pair
with --framework=gin to emit a Gin-flavoured variant via the
adapters/gin adapter.
lago make:migration create_users_table
lago make:migration add_role_to_users_tableThe runner infers a sensible default table name from the migration's
name. Override fields with --fields=...:
lago make:migration create_invoices_table \
--fields="number:string:unique,total:decimal,issued_at:datetime"The fastest path from "I want a Post resource" to a working API:
lago make:crud Post \
--fields="title:string,body:text,published:bool:default(false)"Equivalent to make:model -mfsct.
name:type[:modifier1][:modifier2]...
Types: string, text, longtext, char, int, bigint,
smallint, tinyint, uint, bool, float, double, decimal,
json, jsonb, uuid, date, datetime, timestamp, time,
binary.
Modifiers: nullable, unique, index, primary,
default(VALUE).
Examples:
--fields="email:string:unique"
--fields="age:int:default(18)"
--fields="bio:text:nullable"
--fields="published_at:datetime:nullable"
--fields="role:string:default('user'):index"The same spec feeds three artifacts simultaneously:
| Artifact | Result |
|---|---|
| Model |
Email string \column:"email"`` |
| Migration | t.String("email").Unique() |
| Factory |
Email: f.Email() (auto-picks an apt faker call by name+type) |
lago migrate # apply all pending
lago migrate --pretend # print SQL, don't execute
lago migrate --path 2026_01_01_000001_create_users_table # only that one
lago migrate:status # tabular: applied / pending
lago migrate:rollback # last batch
lago migrate:rollback --step=3 # roll back 3 most recent
lago migrate:reset # roll back EVERYTHING
lago migrate:refresh # reset + up
lago migrate:fresh # DROP all tables, then up
lago migrate:fresh --seed # fresh + run seeders
lago migrate:step --n=2 # apply at most 2 pendingUseful flags across the migrate family:
-
--pretend— render the SQL without executing. -
--lock-timeout=30s— bound the wait on the advisory lock. -
--allow-out-of-order— bypass the safety check when squashing.
See Migrations-and-Schema for what the safety checks actually do.
lago db:seed # all seeders, dependency-ordered
lago db:seed UserSeeder PostSeeder # only these (+ their deps)
lago db:seed --class UserSeeder # Laravel-compatible alias
lago db:seed --transactional # each seeder in its own tx
lago db:wipe --force # DROP every user table
lago db:show # driver, host, tz, tables + row counts
lago db:table users # columns, types, nullability
lago db # interactive SQL prompt (\q to exit)db:wipe requires --force so you can't drop production by reflex.
db:show is the fastest way to confirm you're connected to the
right database — it prints the resolved DSN host + driver alongside
the table list.
You can build your own CLI with the same surface plus your commands. The pattern is:
package main
import (
_ "github.com/devituz/lagodev/drivers/postgres"
"github.com/devituz/lagodev/cli"
_ "myapp/db/migrations"
_ "myapp/db/seeders"
)
func main() {
app := cli.New(cli.Options{ProjectName: "myapp"})
app.AddCommand(myCustomCommand())
app.Execute()
}cli.Options lets you inject a custom *database.Manager, custom
migration/seeder registries, and a custom connector if you don't
want the default .env-driven one. This is how you embed lagodev's
CLI surface into a larger app's tooling.
-
Configuration — what
.envandlago.jsonconfigure. -
Migrations-and-Schema — the schema DSL invoked by
make:migration. -
Factories-and-Seeders — what
make:factoryandmake:seedergenerate.
lagodev on GitHub · MIT-licensed — see LICENSE.