CLI Reference — webda
The webda CLI launcher (packages/core/lib/bin/launcher.js) starts and manages a Webda application at runtime. It must be run from a directory containing a webda.config.json with @webda/core installed in node_modules.
Commands overview
webda <command> [options]
Commands:
webda serve Start the HTTP server
webda openapi Export the OpenAPI definition
webda debug Start dev server with debug dashboard
webda build Generate protobuf definition from operations
webda post Post operations (from blog-system: model-specific operations)
webda user User operations
webda publisher Publisher operations
webda testbean TestBean operations
Options:
-w, --watch Watch for changes, recompile and restart
--service Filter command to specific service(s), comma-separated
--help Show help
Note: Model-specific operation commands (like
post,user) are dynamically generated from the models and their@Operation()methods registered in the current project.
webda serve
Starts the application HTTP server in production mode.
webda serve
webda serve --port 8080 --bind 0.0.0.0
webda serve --watch # restart on file changes (requires @webda/compiler)
| Flag | Description |
|---|---|
--port <n> | Override the HTTP port |
--bind <host> | Bind address (default: 0.0.0.0) |
-w, --watch | Watch mode with auto-restart |
webda debug
Starts the application in development mode with the debug dashboard enabled. The debug dashboard provides a web UI for inspecting running services, requests, logs, and metrics.
webda debug
The debug server starts on port 18080 by default (configured in HttpServer.port).
webda openapi
Exports the generated OpenAPI 3.0 specification to stdout or a file.
# Print to stdout
webda openapi
# Write to a file
webda openapi --output ./openapi.json
# Include hidden routes
webda openapi --includeHidden --output ./openapi-full.json
| Flag | Description |
|---|---|
-o, --output <file> | Write to file instead of stdout |
--includeHidden | Include routes marked as hidden |
webda build
Generates protobuf definitions from model operations (for gRPC transport):
webda build
Model operation commands
For each model with @Operation() methods, the launcher generates a CLI subcommand. For example, in the blog-system:
webda user login --email alice@example.com --password secret
webda post publish --slug hello-world --destination twitter
webda publisher publishPost --slug hello-world
These commands invoke the corresponding @Operation() static or instance methods directly from the CLI, without starting the HTTP server.
Service commands (@Command)
serve, debug, migrate... are declared by services with the @Command decorator; the method parameters become the command options.
- Several providers: every configured service declaring the command runs it (
--service=<type or instance name>filters). The CLI accepts the union of their options and calls every handler with the same positional values, in the order of the merged options: providers must declare their shared parameters in the same order and with the same type.webdalogs a warning when they do not. - Inheritance: a subclass inherits the commands of its parent class (an application
Authenticationsubclass runsauth migrate). A subclass redeclaring the command is a second provider: exclude the parent one withwebda.cli.exclude(below), or the instance runs both.
Application command-line (webda.cli)
The webda.cli section of the application package.json configures its command-line:
"webda": {
"namespace": "Loopingz",
"cli": {
"name": "acp-loopingz-runner", // program name in --help, instead of "webda"
"defaultCommand": "serve", // run when the arguments name no command
"bin": "bin/acp-loopingz-runner.mjs", // generated executable, default bin/<name>.mjs
"include": ["serve", "login", "logout"], // only these commands (with their subcommands); absent: all
"exclude": ["Webda/HttpServer:serve", "migrate", "openapi"]
}
}
| Field | Applies to | Description |
|---|---|---|
name | generated executable (runCli) | Program name shown in --help; also names the executable. Defaults to the unscoped package name |
defaultCommand | generated executable (runCli) | Command inserted when the arguments name none (acp-loopingz-runner --port 3000 runs serve --port 3000); --help and --version alone still show the global help and version |
bin | webdac build | Path of the generated executable, relative to the package, default bin/<name>.mjs |
include | webda and the executable | Allow-list of commands, applied before exclude; a command keeps its subcommands ("config" keeps config encrypt, "task" keeps every task operation) |
exclude | webda and the executable | "Type:command" removes one provider of a command ("Webda/HttpServer:serve", or "HttpServer:serve"), "command" removes the command with its subcommands |
include and exclude apply to webda too, so webda and the application executable offer the same commands. An entry matching no command logs a warning. An excluded provider is not added to the configuration to run the command either.
They select the operation commands (@Operation, from .webda/operations.json) the same way. The operation RunnerAuth.Login is the command runnerauth login:
"runnerauth"selects the whole group,"runnerauth login"one operation. Operation names match in any case ("RunnerAuth"works too)."Type:command"only selects@Commandproviders, never an operation.- With
include, a group not listed is hidden from--helpand cannot be run:"include": ["serve", "login", "logout"]leaves no operation command. - An entry matching only an operation is not reported as unknown.
Replacing a framework command with a subclass, for example a serve taking a hub address:
class RunnerHttpServer extends HttpServer {
@Command("serve", { description: "Start the runner" })
async serve(bind: string = "127.0.0.1", port: number = 18080, connect: string = "wss://hub.example.com") {
// ...
}
}
With "exclude": ["Webda/HttpServer:serve"], acp-loopingz-runner --port 3000 --connect wss://other runs RunnerHttpServer.serve("127.0.0.1", 3000, "wss://other") once.
Generated executable
When webda.cli exists, webdac build writes the executable (mode 755, rewritten only when its content changes):
#!/usr/bin/env node
// Generated by webdac build from the "webda.cli" section of package.json: do not edit
import { fileURLToPath } from "node:url";
import { runCli } from "@webda/core/lib/bin/cli.js";
await runCli({ appPath: fileURLToPath(new URL("../", import.meta.url)) });
Declare it in the package.json bin field so npm installs it (webdac build warns when it is missing):
"bin": { "acp-loopingz-runner": "bin/acp-loopingz-runner.mjs" }
It runs the application from its package folder, whatever the current directory: relative ResourceService folders resolve from the application folder.
runCli
runCli(options?: { appPath?: string; argv?: string[]; defaultCommand?: string; name?: string }): Promise<void>, exported by @webda/core/lib/bin/cli.js
| Option | Default | Description |
|---|---|---|
appPath | WEBDA_APP_PATH, then . | Application folder (package.json, webda.module.json, .webda/) |
argv | process.argv.slice(2) | Arguments to parse |
defaultCommand | webda.cli.defaultCommand | Command inserted when the arguments name none |
name | webda.cli.name, then webda | Program name in --help |
The process exits when the command completes. Importing the module does not start the CLI.
Global options
| Flag | Description |
|---|---|
--version | Show version number |
-w, --watch | Watch for changes, recompile and restart |
--service <names> | Filter command to specific service(s), comma-separated |
--help | Show help |
Compile cache
The launcher enables the Node compile cache (Node >= 22.1)
for the CLI: the compiled code of the loaded modules is kept in .webda/compile-cache, so the next starts skip the
compilation of the unchanged modules (about 8% of the blog-system cold boot, 13% of the framework import). Node
invalidates the entries of modified files.
NODE_COMPILE_CACHE=<folder>uses another folder.WEBDA_COMPILE_CACHE=false(orNODE_DISABLE_COMPILE_CACHE=1) disables it.- Running
node node_modules/@webda/core/lib/bin/cli.jsdirectly (the default container entrypoint) does not enable it: setNODE_COMPILE_CACHEin the environment to use it there.
Verify
# Run from the blog-system project
cd sample-apps/blog-system
node ../../packages/core/lib/bin/launcher.js --help
Output:
webda <command> [options]
Commands:
webda serve Start the HTTP server
webda openapi Export the OpenAPI definition
webda debug Start dev server with debug dashboard
webda build Generate protobuf definition from operations
webda post Post operations
webda user User operations
webda publisher Publisher operations
webda testbean TestBean operations
Options:
--version Show version number [boolean]
-w, --watch Watch for changes, recompile and restart (requires
@webda/compiler) [boolean] [default: false]
--service Filter command to specific service(s), comma-separated [string]
--help Show help [boolean]
See also
- Architecture — what the launcher starts under the hood
- Services — services that the launcher initializes
- Routing — how HTTP routes are registered
- @webda/compiler CLI —
webdac buildfor TypeScript compilation