Airway includes a built-in scaffolding CLI. You can use it through the main command:
go run . cli ...When running airway cli ..., Airway automatically tries to load .env from the current project root first.
If you already built the binary, the same commands also work as:
./airway cli ...airway cli db:create
airway cli db:drop
airway cli db:migrate [version]
airway cli db:rollback [step]
airway cli db:status
airway cli generate [action|api|model|migration|service|cmd] [params]
airway cli plugin install /path/to/project
airway cli schema:dump
airway cli schema:showgo run . cli generate api adminThis creates:
app/api/admin_api/routes.goapp/api/admin_api/index_action.go
Generated route shape:
func Routes(r *gin.RouterGroup) {
g := r.Group("/admin")
{
g.GET("/index", IndexAction)
}
}Use this when you want to create a new API namespace quickly.
go run . cli generate action admin showThis creates:
app/api/admin_api/show_action.go
Use this when the API folder already exists and you only need a new endpoint handler.
go run . cli generate model postThis creates:
app/models/post.go
The generated model includes:
ID,CreatedAt,UpdatedAtTableName()- REPL registration via
registerREPLModel
go run . cli generate service post title:string published:boolThis creates:
app/services/post.go
The generated file includes:
FindPostCreatePostUpdatePostDeletePost
Field arguments use name:type format.
go run . cli generate cmd post title publishedThis creates:
cmd/post.go
This generator is useful if your project exposes extra custom CLI helpers around generated services.
go run . cli generate migration create_postsThis creates a new SQL migration file under:
db/migrate
go run . cli db:migratego run . cli db:migrate 20260327120000go run . cli db:rollbackgo run . cli db:rollback 3go run . cli db:statusMigration commands read:
AIRWAY_DB_DSNAIRWAY_PGas a legacy fallback
In normal local development, these values can come directly from your project's .env file because airway cli ... loads it automatically.
The migration commands use the current Airway DSN and work with the databases supported by the project, including PostgreSQL, MySQL, and SQLite.
Install the current project as a plugin into another Airway project:
go run . cli plugin install /path/to/projectThis copies:
./app/*into/path/to/project/app/./cmd/*into/path/to/project/cmd/./db/migrate/*.sqlinto/path/to/project/db/migrate/
Migration files copied through plugin install are prefixed with a fresh timestamp to avoid version collisions.
Here is a minimal workflow for adding a posts feature from scratch.
go run . cli generate migration create_postsThen edit the generated SQL file in db/migrate/ and define the table you need.
Example:
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
published BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);Run the migration:
go run . cli db:migratego run . cli generate model postThis creates app/models/post.go.
At this point you will usually extend the generated struct with your real fields, for example:
type Post struct {
ID sql.IdType `db:"id" json:"id"`
Title string `db:"title" json:"title"`
Published bool `db:"published" json:"published"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}go run . cli generate service post title:string published:boolThis creates app/services/post.go with basic CRUD helpers.
go run . cli generate api post
go run . cli generate action post create
go run . cli generate action post showThis gives you:
app/api/post_api/routes.goapp/api/post_api/index_action.goapp/api/post_api/create_action.goapp/api/post_api/show_action.go
Open config/routes.go and import the generated package:
import (
"github.com/gin-gonic/gin"
"github.com/daqing/airway/app/api/post_api"
"github.com/daqing/airway/app/api/up_api"
"github.com/daqing/airway/app/websocket"
)Then register it inside apiGroupRoutes:
func apiGroupRoutes(r *gin.Engine) {
v1 := r.Group("/api/v1")
{
post_api.Routes(v1)
}
}With the generated default route file, you will get an endpoint like:
GET /api/v1/post/index
For example, create_action.go is only a scaffold. You still need to:
- define request params
- call
services.CreatePost(...) - return data through
render.OK(...)orrender.Error(...)
justOr:
go run .At that point you have the full skeleton for:
- database migration
- model
- service
- API handlers
- route registration
- Generators do not overwrite existing files. If the target file already exists, the command returns
file already exists. generate apicreates files, but you still need to wire the generatedRoutes(...)into your router setup.generate serviceassumes your project has anapp/servicespackage.- Generated files are starting points. They are meant to be edited after creation.