The gebweb CLI
The gebweb binary is the developer interface to the framework. It
scaffolds projects, runs them with hot-reload, builds release
binaries, prints the routes table, emits boilerplate files, runs
schema migrations, and drives the background-job + messaging worker.
Install
Install the Geblang toolchain first, then download a gebweb CLI archive for
your platform from the Gebweb releases.
Extract the binary and put it on your PATH. With Go installed, you can install
the CLI from its module instead:
go install github.com/dwgebler/gebweb/cmd/[email protected]
The CLI and the framework package install separately. gebweb shells out to
geblang, so keep both binaries on your PATH. After gebweb new myapp, run
geblang install github.com/dwgebler/[email protected] inside myapp so the
generated project's import gebweb; resolves. See
Getting started for the full sequence.
gebweb new [<name>]
Interactive project wizard. Run with no flags, it prompts for the project
name, type, database, Docker, and port; pass any of them as flags to skip
the matching prompt, or --yes (or pipe stdin) to take defaults
non-interactively.
gebweb new # fully interactive
gebweb new blog --type app --db sqlite --yes
gebweb new api --type api --db postgres --docker --port 9000 --yes
Options:
--type app|api app: server-rendered (templates + asset pipeline);
api: JSON-only. Default app.
--db <driver> sqlite (default) | postgres | pgvector | mysql.
--docker Also generate a Dockerfile and compose.yaml.
--port <port> Port wired into .env / Docker. Default 8080.
--yes, -y Accept defaults for unspecified options (no prompts).
It scaffolds a buildable entry (src/main.gb, a module exporting main),
a .env (with GEBWEB_PORT and the DB DSN), a sample controller + model +
repository, a TestClient suite, and a .gitignore. An app project also
gets a templates/page.html and a CSS/TS asset wired through the asset
pipeline; with --docker it adds a Dockerfile and compose.yaml (with the
matching DB service). Install the framework package inside the new project
before running gebweb dev or gebweb build.
gebweb dev
Runs the project with hot-reload. The CLI watches src/
recursively via fsnotify; when a .gb or .yaml file changes, it
sends SIGTERM to the running child, waits up to 2 s for it to
exit cleanly, and starts a new one. Burst saves are coalesced via
a 200 ms debounce.
cd myapp
geblang install github.com/dwgebler/[email protected]
gebweb dev
By default, the entry point is src/main.gb. Override with
--entry. When the project has an assets: block, gebweb dev
compiles the asset entry points once (unminified) before starting
so the dev server serves them from disk.
gebweb build
Processes assets/templates and wraps geblang build for the bundling step:
gebweb build # builds ./build/app
gebweb build --out dist/myapp
gebweb build --no-minify # skip minification
gebweb build --no-sass # skip SASS when dart-sass is absent
gebweb build --no-swagger # skip embedding SwaggerUI assets
By default, the entry point is src/main.gb and the output is
./build/app. Both can be overridden with --entry and --out.
With an assets: block in geblang.yaml, the asset entry points are
compiled and minified (JS/TS/JSX/CSS via esbuild, SASS via dart-sass),
HTML templates are minified, and the compiled output, templates/, and
public/ are embedded in the binary so it is self-contained. The app
resolves them at run time via sys.bundleDir(). See the
asset pipeline chapter for the full config.
gebweb build --docker also generates a Dockerfile and compose.yaml after
building (see gebweb docker below).
gebweb docker
Generates a Dockerfile and compose.yaml for the project:
gebweb docker # sqlite, port 8080
gebweb docker --db postgres
gebweb docker --db pgvector --port 9000
gebweb docker --force # overwrite existing files
The Dockerfile copies the host-built binary (gebweb build) into a
gcr.io/distroless/static-debian12 image (ca-certificates and tzdata
included) and wires GEBWEB_PORT. The compose file runs the app service with
the port and .env wired in, plus an optional database service:
sqlite(default): no DB service; a named volume persists the database file.postgres:postgres:16with a healthcheck and named volume.pgvector:pgvector/pgvector:pg16(postgres with the vector extension).mysql:mysql:8with a healthcheck and named volume.
Existing Dockerfile / compose.yaml are left untouched unless --force is
given, so your edits are safe. The same flags work on gebweb build --docker,
which builds the binary first and then generates the files.
gebweb routes
Runs the app with GEBWEB_PRINT_ROUTES=1 set. The framework
detects the variable on startup and prints the routes table
before serving. To format a table in your own code, use
gebweb.formatRouteTable(gebweb.routes(app)).
$ gebweb routes
GET /
GET /hello/{who}
gebweb generate <kind> <Name>
Emits boilerplate under src/:
gebweb generate controller User # src/user_controller.gb
gebweb generate dto User # src/user_dto.gb
gebweb generate repository User # src/user_repository.gb
gebweb generate resource Widget # full bundle: controller + dto + repository + test
Each kind drops a small idiomatic scaffold ready to be filled in. The CLI refuses to overwrite an existing file.
gebweb generate client <spec> <Name>
Generates a typed HTTP-client class from an OpenAPI 3.x spec. Accepts
YAML or JSON (JSON is parsed as the YAML subset it is). The output is
a single self-contained src/<name>_client.gb file with:
- One exported data class per
components/schemas/*object (Pet,NewPet, ...). Schema fields become typed Geblang fields; the schema'srequiredlist controls nullability (non-required becomes?type). - A
<Name>Clientclass wrapping the stdlibhttpmodule. The constructor takes a base URL plus an optionalauthconfig dict. One method per operation; each builds the URL (path interpolation from path params, query string from query params), the headers (auth + per-operation overrides), and the body (json.stringifyof typed DTOs), callshttp.requestWithOptions, and decodes the response into the schema-declared return type viajson.parseorjson.parseAs. - Auth: covers the four common security schemes from
components/ securitySchemes. The constructor'sauthdict accepts:bearerToken(HTTP bearer),basicUser+basicPassword(HTTP basic), andapiKey(apiKey scheme, automatically routed to the configured header / query parameter / cookie). OAuth2 / OIDC bindings are treated as a bearer-token holder for v1. - A 4xx / 5xx response raises
RuntimeErrorwith the HTTP method, path, status, and response body so callers cantry/catchcleanly.
Example:
# spec.yaml from your vendor
gebweb generate client spec.yaml Petstore # writes src/petstore_client.gb
# in code
import gebweb;
import petstore_client as petstore;
let client = petstore.PetstoreClient("https://api.example.com/v1", {
"bearerToken": gebweb.getParameter(app, "petstore.token") as string
});
let pets = client.listPets(20, "house");
let pet = client.getPet("p-42");
let made = client.createPet(petstore.NewPet());
Regenerate from the source spec; the generated file carries a "do not edit" header. The CLI refuses to overwrite an existing file, so delete the old output first when re-running.
gebweb migrate <create|up|down|status>
Applies versioned SQL migrations to the database in DATABASE_URL.
See Database migrations for the file format
and the full subcommand reference.
gebweb migrate create add_users # writes migrations/<timestamp>_add_users.sql
gebweb migrate up # applies all pending
gebweb migrate down --steps 1 # rolls back the most recent
gebweb migrate status # prints applied / pending
gebweb secrets <init|edit|set|get|list>
Manages an encrypted secrets file for use with
gebweb.useSecrets(app, gebweb.encryptedFileSecrets()). The
vault stores name -> value pairs that YAML %secret(name)%
markers resolve to.
gebweb secrets init # one-off, creates key + empty vault
gebweb secrets set stripe.key sk_live_abc
gebweb secrets get stripe.key
gebweb secrets list
gebweb secrets edit # opens $EDITOR on plaintext
See services.yaml for the wiring on the app side.
gebweb worker
Runs the background-job and messaging worker loops. Re-runs
src/main.gb with GEBWEB_RUN=worker in the environment; your
main.gb branches on it and calls gebweb.runWorker(app) and / or
gebweb.runMessageWorker(app) instead of gebweb.serve(...). See
Background jobs and
Message brokers.
gebweb worker # drain everything
gebweb worker --job email --job sms # only email + sms job names
gebweb worker --handle orders # only the orders messaging handle
gebweb worker --jobs-only # skip messaging
gebweb worker --messaging-only --handle audit
# only the audit messaging loop
Filtering flags translate into env vars
(GEBWEB_WORKER_JOBS / GEBWEB_WORKER_HANDLES /
GEBWEB_WORKER_KIND) that gebweb.runWorker and
gebweb.runMessageWorker honour automatically; main.gb does not
need to plumb anything through. Different worker processes can
specialise on different work pools (e.g. one server runs email
jobs, another runs image-resize jobs) by composing these flags.
Run multiple workers in parallel by starting gebweb worker in
multiple processes - job-row claims are atomic and messaging
brokers handle the consumer fan-out themselves.
Pass --help to any subcommand for its full options.
When to use each
| Command | Workflow |
|---|---|
gebweb new |
One-off; scaffold a new project. |
gebweb dev |
Inner loop; restarts on save. |
gebweb build |
Release; bundles a self-contained binary. |
gebweb docker |
Release; generate Dockerfile + compose.yaml. |
gebweb routes |
CI / debugging; static dump of the routes table. |
gebweb generate |
Boilerplate; emit a new class skeleton. |
gebweb migrate |
Schema versioning; apply / roll back SQL. |
gebweb worker |
Long-running; drain the background-job queue. |
gebweb secrets |
One-off; manage the encrypted secrets file (see services.yaml). |
Claude Code skill
Gebweb ships a Claude Code skill that equips Claude to build and operate Gebweb
applications: controllers and routing decorators, parameter binding, dependency
injection, views, validation, repositories and @ApiResource, auth, and the
gebweb CLI commands documented above. It pairs with the geblang language
skill.
The skill is bundled at .claude/skills/gebweb/ (a SKILL.md plus reference
files for the app-authoring surface and the CLI/testing workflow). Claude Code
loads it automatically as a project skill inside a checkout of this repo; to use
it elsewhere, copy it into your user skills directory:
cp -r .claude/skills/gebweb ~/.claude/skills/gebweb