CLI commands
This site documents the stable v2.0.0 release. The CLI output below uses that published version.
VextJS provides the vext command line tool, covering the complete life cycle of project creation, development, construction and deployment.
Installation
The vext CLI is installed with the vextjs package, no additional installation is required:
After installation, it can be called in the following ways:
Command overview
vext create — Create a project
Interactively create new VextJS projects and automatically generate project skeleton and configuration files. The default template is fullstack-react; API-only scaffolding remains available through --template api --frontend none. The full-stack starter opens with a server-rendered Vext launchpad that you can edit immediately, including a visible Vext Guide link and a local API documentation entry at /docs. Its default configuration enables OpenAPI, so that local entry is live after both vext dev and production vext start; API-only projects remain opt-in.
Usage
Options
Example
The command accepts exactly one project name. Extra positional arguments fail before any target directory is created. If automatic dependency installation fails, create exits non-zero and keeps the generated files; run cd <project-name> followed by npm install to retry. Generated TypeScript full-stack projects include NodeNext-compatible mappings for the built-in @frontend, @pages, @components, @styles, and @assets aliases.
Generated directory structure
Type directory boundaries
The tree above is the default TypeScript full-stack starter. Its src/types/** folders have separate owners:
In TypeScript projects, vext typegen writes only
src/types/generated/**; it does not replace application-owned files in
shared/** or frontend/**. JavaScript create/dev/typegen flows do not create
that public TypeScript tree; their tooling declarations remain under
.vext/types.
The scaffold does not reserve src/types/server/**. Keep a type that is private to one route or service next to that server owner; create src/types/server/services/** only when your application has a real shared backend service boundary. Runtime enum/constant values belong owner-near or under src/constants/services/**, not under src/types/**; see Project structure.
The starter deliberately does not create root or directory-level placeholder README.md files. Generated user source is English-first in both TypeScript and JavaScript, for full-stack and API-only templates; files under explicit locale directories are the only language-content exception. Conventional directories such as src/middlewares/, src/plugins/, src/locales/, and the canonical src/preload/ remain supported and are created when you add real source files. The legacy project-root preload/ directory is not scaffolded.
For the default fullstack starter, public/vext-mark.svg is a transparent navigation mark and public/favicon.svg is a contrast-safe favicon variant. They share the same V geometry; the app shell uses the former, and both are copied with the rest of public/ assets.
After creation is complete:
Visit http://localhost:3000 and you should see the React client. API routes are available at /api/hello and /api/health.
vext create directly generates src/config/local.ts as an empty VextConfigOverride and src/config/bootstrap.ts with providers: []. The defaults have no logger, provider, external connection, or other business side effect. local.ts is excluded by .gitignore and may be absent after clone; bootstrap.ts is tracked and can later register a provider through defineBootstrapConfig().
vext dev — development mode
Start the project in development mode, supporting file monitoring and smart hot reloading.
Usage
vext dev does not support positional arguments. Value options such as --root, --port, --host, --config, --poll-interval, --debounce, --startup-profile-json, and --port-conflict must be followed by a non-option value; numeric options require complete integers, so prefixes such as 3000x and 50x fail.
Options
Port conflict policy
error: direct failure (default)prompt: Ask the parent process how to handle it in TTY environmentkill: Try to kill the process occupying the portnext: automatically selects the next available port
Start log tiering
By default, vext dev only prints the listening address and total startup time, and then prints the necessary results during cold restart / hot reload. vext dev --startup-profile will output a human-readable startup summary and detailed events; the summary is main/preflight, main/preload, pre-worker-bootstrap, compile, config, i18n, database, plugins, middleware, services, routes, openapi, listen, onReady Classification in other stages; unnamed empty windows that exceed the threshold will be entered into profile JSON in the form of gap.*.
--startup-profile-json <path> only writes JSON files and will not automatically print summary or details; if you need to output both at the same time, you can combine --startup-profile --startup-profile-json <path>.
If you need life cycle troubleshooting details, you can enable:
Example
Hot reload strategy
vext dev provides a three-layer hot reload strategy and automatically selects the optimal method:
See the Hot Reload chapter for details.
Frontend files under src/frontend/** and static assets under public/** trigger a frontend rebuild message. React pages, layouts, and shared components use Fast Refresh by default; they do not require a backend cold restart unless mixed with backend changes.
package.json script
vext build — Build the project
Compile TypeScript source code into JavaScript to generate a production-usable dist/ directory; tool products such as typegen and route manifest will be refreshed before building. When frontend is enabled, vext build also bundles the browser client into dist/client/.
Usage
Options
The CLI flag remains opt-in for an existing project. New TypeScript starters
set their generated package.json build script to vext build --typecheck, so
npm run build includes semantic checking by default. JavaScript starters use
vext build without invoking TypeScript.
Production CLI builds minify backend output by default. Use --no-minify for readable local output, or set VEXT_BUILD_MINIFY=false when the opt-out is controlled by the environment. Frontend production minification still follows frontend.build.minify.
Example
Build behavior
- Refresh
.vext/types/*.generated.d.ts,.vext/manifest/services.json, and.vext/manifest/routes.jsonfirst; TypeScript projects also refreshsrc/types/generated/index.d.ts - When
--typecheckis enabled, execute the project-localtsc --noEmitafter refreshing generated products; missing local TypeScript fails with an actionable error and never falls back to network resolution - Use esbuild for server compilation and frontend bundling
- Positional arguments are not supported; value options such as
--outdirand--configrequire a non-option value - The output directory defaults to
dist/ - Maintain source code directory structure
.jsand.js.mapfiles are generated by default; declaration files will not be generated indist/- Repeated builds automatically remove stale backend outputs left by deleted or renamed server source files;
--cleanclears the entire output directory first - Destructive cleanup fails closed when the resolved output is the project root, source root, or their parent; frontend output, asset directory, naming patterns, and server outfile must also remain inside their declared build boundary
- When frontend is enabled,
dist/client/index.html,manifest.json,deploy-manifest.json,size-report.json, static assets, and client contract artifacts are generated - When
--upload-assetsis used, Vext readsdist/client/deploy-manifest.jsonand uploads only changed static assets by sha256 andfrontend.deploy.upload.stateFile
package.json script
vext dev: Load.tsfiles directly fromsrc/, compile on-the-fly through esbuild, support hot reloadingvext build: compilesrc/todist/, load production mode fromdist/:::
vext deploy assets — Upload frontend static assets
Read dist/client/deploy-manifest.json and upload JavaScript, CSS, images, fonts, and copied public/** resources to the configured target. The first built-in adapters are filesystem and mock; cloud vendors can be connected through a custom deploy adapter.
Usage
vext deploy assets does not support positional arguments. Value options such as --manifest, --adapter, --target-dir, --prefix, and --state-file must be followed by a non-option value, for example --manifest dist/client/deploy-manifest.json; --manifest --dry-run fails as a missing-value error.
Options
Example
On the second run, Vext reads frontend.deploy.upload.stateFile and compares each uploadKey sha256. Unchanged JavaScript, CSS, images, fonts, and stable public files are skipped instead of uploaded again. index.html and source maps are not part of the default deploy manifest because Vext still renders HTML from the server path and keeps source maps out of CDN publishing by default.
vext typegen — Generate declarations and perform service dependency diagnostics (experimental)
Provide generated declarations for app.services and app.extend() / defineAppExtensions<{ ... }>() in plugins, and perform tooling-only service dependency checks.
Usage
vext typegen does not accept positional arguments. Unknown arguments fail fast with an actionable diagnostic. Value options such as --root / -C require a non-option value; --root --json is rejected instead of treating --json as a path.
Options
Products
For TypeScript projects, src/types/generated/** is the only src/types/**
location written by vext typegen. JavaScript projects keep the hidden
.vext/types products but receive no public .d.ts shim. The full-stack
starter's shared/** and frontend/** folders are application-owned
contracts; see Generated directory structure
for their roles and template-specific availability.
Example
Applicable Boundary
typegenas a whole still belongs to the tooling-only capability and will not enter the main runtime path ofvext start;vext devwill automatically execute basictypegenin preflight,vext buildwill also refresh generated declarations and manifests before optional typecheck and compilation;- TypeScript semantic diagnostics are output asynchronously after ready / reload by default; if you want to block startup or reload like the old behavior, you can use
--strict-preflightorVEXT_DEV_STRICT_PREFLIGHT=1; - TS projects give priority to output high-quality types, JS projects allow regression to
import(...).default/unknown, but the command itself is still available; --write-manifestwill write the service index,app.extend()/defineAppExtensions<{ ... }>()aggregation results and service dependency graph summary into.vext/manifest/services.json;- More examples of generated declarations can be viewed in conjunction with the Services and Plugins documentation.
vext doctor routes — Static routing diagnosis (experimental)
Scan the static route metadata in src/routes/, output diagnostics such as duplicate routes, missing docs.summary, automatic inference of operationId, etc., and save the results to the inspect/manifest product.
Usage
Value options such as --root / -C require a non-option value; --root --json is rejected instead of treating --json as a path.
Targets
Options
Product positioning
Example
Current boundary
- Route manifests carry a fingerprint and source-file inventory. By default Doctor reuses a manifest only when it matches current route sources; stale manifests are rebuilt.
--manifest-onlyis an explicit snapshot read and cannot be combined with--refreshor--write-manifest. - The current route manifest and services manifest are still maintained hierarchically and are not merged into a single overall manifest;
- When
docs.operationIdis missing, the doctor will give anauto-operation-idinformation prompt according to the runtime behavior instead of false warning; - The routing side is still in charge of
doctor routes --write-manifest; the service side is in charge oftypegen --write-manifest.
vext start — Start production mode
Start the project in production mode. TypeScript projects load compiled code from the dist/ directory and need to execute vext build first; if there is no valid build product, the command will fail directly and prompt you to use vext build or use vext dev during development.
Usage
vext start does not support positional arguments. Value options such as --port, --host, --config, --port-conflict, and --startup-profile-json must be followed by a non-option value.
Options
Example
Default command
When no command is passed, vext executes start by default:
Cluster mode
If cluster is enabled in the configuration, vext start will automatically enter Cluster mode, and the Master process will manage multiple Worker processes:
Or enable via environment variable:
Preload (Preload) automatic injection
vext start and vext dev will automatically parse two types of preload sources:
vext.preloaddeclared in the installed dependency package- canonical
src/preload/in the application project
These scripts will be injected uniformly through --import before the child process is started. For example, @devcodex/opentelemetry can use the package-level vext.preload to automatically initialize the OpenTelemetry SDK before loading the application code; the application project itself can place a script in src/preload/ to bridge the pre-launch environment. Project-level preload rules:
- The canonical directory is
src/preload/ - Non-recursive scan
- Project-level preload is executed first, and package-level preload is executed later.
.mjs/.jsdirect injection.ts/.mtswill be compiled into.vext/preload/*.mjsbefore startup and then injected- If the files in
src/preload/change undervext dev, cold restart will be triggered. - Project-root
preload/is a temporary compatibility fallback that emits a migration warning. Do not place supported preload files in both directories: Vext fails fast rather than running scripts twice.
See Preload for details.
Configuring Provider during startup
If src/config/bootstrap.ts exists in the project, vext start / vext dev will execute the bootstrap config provider declared in it before configuring validate / freeze, and merge the patch returned by the provider into the final configuration. The priority is: default < config profile < local < provider < CLI.
In Cluster mode, the Master will pass the current round of provider patches to the Worker for reuse, preventing the Master/Worker from seeing different remote configurations in the same startup cycle.
package.json script
:::tip Config profile selection
vext start, vext build, and vext deploy assets default to the production profile. vext dev defaults to the development profile. To select a custom profile:
- CLI argument:
vext start --config sg-sit - Environment variable:
VEXT_CONFIG=sg-sit vext start
The profile name maps to src/config/{profile}.ts and, after build, dist/config/{profile}.js.
Pass --config at most once per command. start, dev, build, and deploy assets reject duplicate occurrences instead of silently using the last value.
vext stop — stop the service
Stop a running Cluster mode service. Send a stop signal by reading the PID file.
Usage
vext stop does not support positional arguments. --pid-file must be followed by a non-option path value.
Options
Example
vext stop is only available in Cluster mode. In single-process mode, just use Ctrl+C or send SIGTERM signal to shut down gracefully.
vext reload — rolling restart
Triggers a zero-downtime rolling restart in Cluster mode. Restart Worker processes one by one to ensure that the service is always available.
Usage
vext reload does not support positional arguments. --pid-file must be followed by a non-option path value.
Options
Example
Rolling restart process
After the code is updated, execute vext build + vext reload to complete the version update without downtime. Suitable for production environments requiring high availability.
vext status — View running status
View the service running status in Cluster mode, including information about the Master process and each Worker process.
Usage
vext status does not support positional arguments. Value options such as --pid-file, --port, and --host must be followed by a non-option value.
Options
Example
Output example
Global options
All commands support the following global options:
Recommended package.json script
FAQ
vext start reports error "dist/ not found"
You need to execute vext build first to compile the TypeScript code. vext start loads compiled JavaScript files from dist/.
If frontend is enabled, vext start also requires dist/client/index.html.
Should I use vext dev or vext start when developing?
Daily development uses vext dev, which directly loads TypeScript files under src/ and supports hot reloading without manual compilation. vext start is used in production environments.
How to specify Node.js version?
VextJS requires Node.js >= 20.19.0. It is recommended to create a .node-version or .nvmrc file in the project root directory to specify the version:
vext stop / vext reload / vext status not working?
These three commands are only available in Cluster mode. Make sure cluster.enabled: true is enabled in the configuration or the VEXT_CLUSTER=1 environment variable is used, and the service is started via vext start.
Next step
- Learn the details of the three-layer strategy of Hot Reload
- Configure the Frontend guide
- Learn the complete configuration of Cluster multi-process
- View options such as ports and logs in Configuration
- Explore the conventions of Project Structure