vel Commands
> Complete reference for the per-project `vel` CLI - serve, build, migrations, queues, code generation, maintenance, and keys.
vel is the per-project binary. It’s created in your project root when
you scaffold an app with velocity new. Run ./vel <command> - or
alias vel to ./vel in your shell - from the project directory.
For the installer CLI (velocity new, velocity self-update, etc.),
see Installer Commands.
Server
vel serve
Start the development server with live reload.
vel serve [flags]| Flag | Short | Default | Description |
|---|---|---|---|
--port | -p | 4000 | HTTP port |
--env | -e | development | Environment name (sets APP_ENV) |
--no-watch | off | Disable file-watching / auto-rebuild | |
--tags | (none) | Build tags passed to go build |
vel serve
vel serve --port 3000
vel serve --env staging --no-watch
vel serve --tags="integration"On start:
- Vite dev server launches on
:5173(full-stack projects only). - The Go app compiles to
.vel/tmp/server. .gofiles are watched; a change rebuilds and restarts.
vel build
Compile a production binary.
vel build [flags]| Flag | Short | Default | Description |
|---|---|---|---|
--output | -o | project dir name | Output path (.exe appended when --os windows) |
--os | (host) | Target GOOS | |
--arch | (host) | Target GOARCH | |
--tags | (none) | Go build tags |
vel build
vel build --output ./bin/myapp
vel build --os linux --arch amd64Database
vel migrate
Run all pending migrations.
vel migrate [--pretend]--pretend prints the SQL that would run without executing it - useful
for reviewing migration output before committing.
vel migrate:fresh
Drop all tables, then run every migration from scratch.
vel migrate:fresh [--force]In a production-class environment this command refuses to run unless
--force (-f) is passed. The guard treats production, prod,
staging, and any unrecognised APP_ENV value as production, so a
typo’d APP_ENV cannot disable it.
vel migrate:rollback
Roll back the most recent batch of migrations.
vel migrate:rollback [--step N] [--force]| Flag | Short | Default | Description |
|---|---|---|---|
--step | -s | 1 | Number of batches to roll back (must be >= 1) |
--force | -f | off | Bypass the production-environment guard |
Like migrate:fresh, this is gated in production-class environments;
pass --force to proceed.
vel migrate:status
Show which migrations have run.
vel migrate:statusvel db:wipe
Drop every table in the current database without running migrations.
vel db:wipe [--force]In a production-class environment this command refuses to run unless
--force (-f) is passed (same guard as migrate:fresh).
Queue and Scheduler
vel queue:work
Start a worker that processes queued jobs.
vel queue:work [--queue NAME] [--tries N] [--timeout S]| Flag | Short | Default | Description |
|---|---|---|---|
--queue | -q | default | Queue to consume from |
--tries | (driver) | Max attempts per job before marking failed | |
--timeout | (driver) | Per-job timeout in seconds |
vel queue:work
vel queue:work --queue emails --tries 3 --timeout 60vel schedule:work
Run the scheduler loop - picks up scheduled jobs defined via
v.Schedule(...) and dispatches them when due.
vel schedule:workTypically run under a process supervisor (systemd, Docker, etc.) rather than manually.
Cache
vel cache:clear
Flush the configured cache store.
vel cache:clearMaintenance Mode
vel down
Put the app into maintenance mode. All requests return 503 except those bearing the bypass secret.
vel down [--secret TOKEN] [--retry N]| Flag | Default | Description |
|---|---|---|
--secret | (none) | Bypass token. Send it in the X-Maintenance-Bypass header (or visit /<secret>) to mint a signed velocity_maintenance_bypass cookie that exempts the browser |
--retry | (none) | Value for the Retry-After response header (seconds) |
vel down --secret "abc123" --retry 60vel up
Exit maintenance mode.
vel upKeys
vel key:generate
Generate a fresh 32-byte encryption key and write it to .env under
APP_KEY, base64-encoded with a base64: prefix. If .env does not
exist it’s created; an existing APP_KEY= line is replaced in place.
The .env file is written with owner-only (0600) permissions.
vel key:generateRoutes
vel route:list
Print every registered route with method, path, and name.
vel route:listRebuilds the bootstrap lifecycle internally before printing - the
output always reflects the current v.Routes(...) definition.
Code Generation
All make:* commands scaffold a file into the conventional location
for that type. Names are converted to the right case for the artifact
(snake_case for migration files, PascalCase for types).
Every make:* command accepts a --dir <path> flag to override the
default output directory (the artifact’s conventional folder). The value
is validated and must stay inside the project tree.
vel make:handler
vel make:handler <name> [--resource] [--api] [--dir PATH]| Flag | Short | Default | Description |
|---|---|---|---|
--resource | -r | off | Scaffold CRUD methods (Index/Show/Store/Update/Destroy) |
--api | off | JSON responses instead of view rendering | |
--dir | internal/handlers | Output root override |
Output: internal/handlers/<name>.go. Namespaced names like
Admin/Dashboard nest under the output root.
vel make:handler User
vel make:handler Post --resource
vel make:handler Admin/Dashboard
vel make:handler Product --api --resource
vel make:handler User --dir internal/web/handlersvel make:model
vel make:model <name> [--uuid] [--soft-deletes] [--migration] [--dir PATH]| Flag | Short | Default | Description |
|---|---|---|---|
--uuid | off | Use UUID primary key | |
--soft-deletes | off | Add deleted_at column and scope | |
--migration | -m | off | Also scaffold the migration |
--dir | internal/models | Output directory override |
Output: internal/models/<name>.go.
vel make:migration
vel make:migration <name> [--create TABLE] [--table TABLE] [--uuid] [--soft-deletes] [--dir PATH]| Flag | Accepts | Description |
|---|---|---|
--create | =VALUE or space | Generate a “create” migration for the given table |
--table | =VALUE or space | Generate an “alter” migration for the given table |
--uuid | flag | Use UUID primary key in the create template |
--soft-deletes | flag | Include deleted_at in the create template |
--dir | =VALUE or space | Output directory override (default database/migrations) |
Table names passed to --create / --table must match
[A-Za-z_][A-Za-z0-9_]*. Output:
database/migrations/<timestamp>_<name>.go.
vel make:migration create_posts --create=posts
vel make:migration add_slug_to_posts --table=postsOther make commands
All take a name argument and scaffold a file into the conventional
directory. Each also accepts --dir <path> to override that directory.
| Command | Output path |
|---|---|
vel make:middleware | internal/middleware/<name>.go |
vel make:event | internal/events/<name>.go |
vel make:listener | internal/listeners/<name>.go |
vel make:job | internal/jobs/<name>.go |
vel make:mail | internal/mail/<name>.go |
vel make:notification | internal/notifications/<name>.go |
vel make:resource | internal/resources/<name>.go |
vel make:policy | internal/policies/<name>.go |
vel make:provider | internal/providers/<name>.go |
vel make:command | internal/commands/<name>.go |
vel make:middleware RateLimit
vel make:listener SendWelcomeEmail
vel make:policy PostPolicyvel make:grpc:service
vel make:grpc:service <Name> [flags]Scaffolds a gRPC service end-to-end in one call:
api/proto/<leaf>/v1/<name>.proto- empty service blockapi/proto/buf.yaml+api/proto/buf.gen.yaml(first run only)internal/grpc/services/<name>.go-<Name>Serviceimpl with aNew<Name>Service()constructor and the<alias>.Unimplemented<Name>ServiceServerembedinternal/providers/grpc_provider.go- created on first call (unless--no-provider), then injected at// vel:grpc:importsand// vel:grpc:servicesmarkers on every subsequent call. The provider wires the service viavelgrpc.NewServer(...)andRegister<Name>ServiceServer(...).
| Flag | Default | Description |
|---|---|---|
--package | derived from <Name> | Directory leaf under api/proto/ and api/gen/go/ |
--proto-package | <leaf>.v1 | Full wire package, e.g. velship.admin.v1 |
--dir | internal/grpc/services | Go impl output directory |
--alias | <leaf>pb | Import alias for the generated proto package |
--proto-name | lower-cased <Name> base | Proto file base name (no extension) |
--impl-name | snake_case <Name> base | Go impl file base name (no extension) |
--no-provider | off | Skip provider scaffolding / wiring (proto + impl only) |
Name normalisation: vel make:grpc:service Foo, FooService, foo, and fooService all produce the Go type FooService with proto package foo.v1 and default import alias foopb. The proto file uses option go_package = "<module>/api/gen/go/<leaf>/v1;<leaf>v1" derived from the host project’s go.mod (so the generated package itself is named <leaf>v1, referenced through the foopb alias).
buf.yaml / buf.gen.yaml are written before the proto file, so a config-write failure leaves no partial scaffold on disk. The generated GRPCProvider does not hard-code WithReflection(true); the framework default (toggled by GRPC_REFLECTION env) reaches the file so the generated app boots cleanly in production.
If internal/providers/grpc_provider.go already exists without the marker comments (legacy hand-written provider), the command prints a manual wire snippet instead of mutating user code.
vel make:grpc:service Foo
vel make:grpc:service ChatService
vel make:grpc:service TemplateControl --package admin \
--proto-package velship.admin.v1 --dir internal/shared/grpc/services --no-providerAfter scaffolding, register providers.GRPCProvider{} in internal/app/bootstrap.go (printed as a hint on first run).
vel make:grpc:rpc
vel make:grpc:rpc <Service> <RPC> [--stream | --client-stream | --bidi]Appends a new rpc to an existing service’s .proto and a matching method stub on the Go impl. The service must already exist; run vel make:grpc:service <Name> first.
| Flag | Aliases | RPC shape produced |
|---|---|---|
| (none) | Unary: rpc X(XRequest) returns (XResponse) | |
--stream | --server-stream | Server-streaming: returns (stream XResponse) |
--client-stream | Client-streaming: (stream XRequest) returns (X) | |
--bidi | --bidirectional | Bidi: (stream XRequest) returns (stream X) |
Only one streaming flag may be set per invocation; combining them errors out.
The proto scanner walks the file with brace counting that respects // line comments, /* block */ comments, and "..." string literals at every position (header keyword, between keyword and name, between name and {, and inside the body). That means rpc-with-options blocks (grpc-gateway HTTP annotations) and commented-out draft headers do not corrupt insertion.
On the Go side, the generated method signature matches the RPC shape (for service Foo, impl type FooService, default proto alias foopb):
| Shape | Signature |
|---|---|
| Unary | func (s *FooService) X(ctx context.Context, req *foopb.XRequest) (*foopb.XResponse, error) |
| Server stream | func (s *FooService) X(req *foopb.XRequest, stream foopb.FooService_XServer) error |
| Client stream | func (s *FooService) X(stream foopb.FooService_XServer) error |
| Bidi | func (s *FooService) X(stream foopb.FooService_XServer) error |
context is added to the impl’s imports for unary only; streaming variants pull ctx from stream.Context() and do not need the import.
Idempotent: re-running with the same <Service> <RPC> pair detects the existing rpc and skips.
vel make:grpc:rpc Foo Hello
vel make:grpc:rpc Foo Tail --stream
vel make:grpc:rpc Foo Upload --client-stream
vel make:grpc:rpc Foo Chat --bidivel make:grpc:gen
vel make:grpc:genRuns buf generate inside api/proto. Streams buf’s stdout and stderr to your terminal so plugin errors are visible in real time. Fails with a clear message when:
api/proto/does not exist (runmake:grpc:servicefirst)bufis not onPATH(links to install docs)buf generateexits non-zero
vel make:grpc:gen
# cd api/proto && buf generate
# Generated Go code in api/gen/go/Help
vel help
vel --help
vel -hPrints a grouped list of every command.