Skip to content

The Standalone Airway CLI

Airway ships as a standalone, go-installable command-line tool. One airway binary covers the whole project lifecycle: scaffolding a new application, generating code, managing the database, and starting the server.

bash
go install github.com/daqing/airway@latest

This installs the airway command into your Go bin directory (make sure $(go env GOPATH)/bin is on your PATH). Inside any Airway project the same commands also run as go run . <command>.

Quick start: from zero to a running app

bash
airway new myapp                    # or: airway new github.com/me/myapp
cd myapp
cp .env.example .env                # set DSN and PORT
airway db:create
airway db:migrate
go run . server                     # start the HTTP server

airway new scaffolds a complete project skeleton (routes, models, views, WebSocket hub, storage, Docker setup) from an embedded template, replaces the placeholder with your module path, and runs go mod tidy. The target directory is the last path segment of the module path (github.com/me/myapp./myapp) and must not already exist as a non-empty directory.

How the binary dispatches commands

The airway binary is a CLI first:

  • airway server starts the HTTP server (it requires AIRWAY_ENV; when AIRWAY_ENV=local, .env is loaded automatically).
  • Every other argument is dispatched to the CLI. All CLI commands auto-load .env from the current directory, so run them from your project root.
  • Running airway with no arguments prints usage.

The framework repository itself behaves the same way: go run . server starts the server, go run . <command> runs a CLI command. (A project generated by airway new additionally starts the server when its binary is run with no arguments.)

Command reference

bash
airway new <module-path>                                # scaffold a new project
airway server                                           # start the HTTP server
airway generate [action|api|model|migration|service|cmd] [params]
airway db:create
airway db:drop
airway db:migrate [version]
airway db:rollback [step]
airway db:status
airway schema:dump
airway schema:show
airway engine new <module-path>                         # scaffold a new engine module
airway engine:list
airway engine:install [name]
airway upload [key] /path/to/file
airway repl                                             # project binary only
airway version
airway help                                             # or -h / --help

generate can be shortened to g (airway g api admin).

Generators

Generators read the module path from the current directory's go.mod, so generated code imports your project's packages — run them from the project root. Generators never overwrite existing files.

bash
airway generate api admin                       # app/api/admin_api/ (routes + index action)
airway generate action admin show               # new action in an existing API module
airway generate model post                      # app/models/post.go (with REPL registration)
airway generate service post title:string       # CRUD service in app/services/
airway generate cmd post title published        # custom CLI helper in cmd/
airway generate migration create_posts          # SQL up/down pair in db/migrate/

After generate api, remember to wire the generated Routes(...) into config/routes.go.

Database and migrations

Migration files are plain SQL pairs under db/migrate/:

  • <timestamp>_<name>.up.sql — the forward migration
  • <timestamp>_<name>.down.sql — the rollback migration

Because migrations are plain SQL files, the standalone CLI can migrate any Airway project without compiling the project itself. Each migration runs in a transaction, applied versions are tracked in the schema_migrations table, and db:migrate / db:rollback refresh the db/schema.json snapshot automatically. Migrations work with PostgreSQL, MySQL, and SQLite; the driver is inferred from the DSN scheme.

bash
airway db:migrate                # apply all pending migrations
airway db:migrate 20260327120000 # migrate up to a specific version
airway db:rollback               # roll back the latest migration
airway db:rollback 3             # roll back three steps
airway db:status                 # show applied/pending per migration

Database commands resolve the DSN from the first of these environment variables that is set: DSN, AIRWAY_DSN, AIRWAY_DB_DSN (legacy), AIRWAY_PG (legacy). Since the CLI auto-loads .env, setting DSN there is enough.

The older Go DSL migration mechanism (schema.RegisterChange) is still supported, but DSL migrations only run when compiled into the binary that executes them. If the CLI finds timestamped .go migration files under db/migrate, it prints a warning — prefer SQL migrations so the standalone CLI can run them.

Schema snapshot

bash
airway schema:dump   # inspect the database and write db/schema.json
airway schema:show   # print the current db/schema.json

Engines

Scaffold a new engine module (works with the globally installed airway — it only writes files):

bash
airway engine new im                              # directory: im, engine name: im
airway engine new github.com/me/airway-im-engine  # name derived from the last path segment

Engines are optional feature modules enabled via blank imports in engines.go (see docs/engine.md):

bash
go run . engine:list           # list registered engines and mount paths
go run . engine:install <name> # copy an engine's embedded SQL migrations into db/migrate/

Engines register at compile time, so run these through the project binary (go run . ...): the globally installed airway can only see the engines compiled into itself. engine:install assigns fresh timestamps to the copied migrations and skips files that are already installed; afterwards they are ordinary migrations managed by db:migrate / db:rollback / db:status.

File upload

bash
airway upload /tmp/foo.png               # key derived from the path (tmp/foo.png)
airway upload images/foo.png /tmp/foo.png # explicit storage key

Uploads go through the storage configured in .env (STORAGE_DRIVER, STORAGE_ROOT, cloud credentials, ...).

REPL

bash
go run . repl

The REPL only sees the models compiled into the binary you run — project models register via registerREPLModel in app/models, which delegates to lib/replreg. Use go run . repl inside your project; the globally installed airway repl only sees the framework's built-in models.

Global airway vs. the project binary

Some commands depend on code compiled into the running binary (models, engines, Go DSL migrations). Use the right binary for each:

CommandGlobal airwayProject binary (go run . ...)
new, generate, serveryesyes
engine newyesyes
db:create / db:drop / db:migrate / db:rollback / db:statusyes (SQL migrations)yes
schema:dump / schema:show, upload, versionyesyes
replframework's built-in models onlyuse this — sees your project models
engine:list / engine:installengines compiled into airway itselfuse this — sees your project's engines

Compatibility

The pre-0.5 form airway cli <command> still works as an alias for airway <command>. airway plugin install is deprecated — use engines instead (see docs/engine.md).

See also: docs/cli.md for the full scaffolding guide with a step-by-step feature example.