Using CLI

Use the srvx CLI command to easily start a development or production server.

You can run srvx with your preferred runtime without installation:

npx srvx

Usage

srvx   - Universal Server.

SERVE MODE

# srvx serve [options]
$ srvx serve --entry ./server.ts    # Start development server
$ srvx serve --prod                 # Start production  server
$ srvx serve --port=8080            # Listen on port 8080
$ srvx serve --host=localhost       # Bind to localhost only
$ srvx serve --static=./dist        # Serve static files (no entry needed)
$ srvx serve --import=jiti/register # Enable [jiti](https://github.com/unjs/jiti) loader
$ srvx serve --tls --cert=cert.pem --key=key.pem  # Enable TLS (HTTPS/HTTP2)

FETCH MODE

# srvx fetch|curl [options] [url]
$ srvx fetch                  # Fetch from default entry
$ srvx fetch /api/users       # Fetch a specific URL/path
$ srvx fetch --entry ./server.ts /api/users # Fetch using a specific entry
$ srvx fetch -X POST /api/users # POST request
$ srvx fetch -H "Content-Type: application/json" /api # With headers
$ srvx fetch -d '{"name":"foo"}' /api # With request body
$ srvx fetch -v /api/users    # Verbose output (show headers)
$ echo '{"name":"foo"}' | srvx fetch -d @- /api # Body from stdin

COMMON OPTIONS

  --entry <file>           Server entry file to use
  --dir <dir>              Working directory for resolving entry file
  -h, --help               Show this help message
  --version                Show server and runtime versions

SERVE OPTIONS

  -p, --port <port>        Port to listen on (default: 3000)
  --host, --hostname <host>  Host to bind to (default: all interfaces)
  -s, --static <dir>       Serve static files from the specified directory (default: public)
  --prod                   Run in production mode (no watch, no debug)
  --import <loader>        ES module to preload
  --tls                    Enable TLS (HTTPS/HTTP2)
  --cert <file>            TLS certificate file
  --key  <file>            TLS private key file

FETCH OPTIONS

  -X, --method <method>    HTTP method (default: GET, or POST if body is provided; --request is a curl alias)
  -H, --header <header>    Add header (format: "Name: Value", can be used multiple times)
  -d, --data <data>        Request body (use @- for stdin, @file for file)
  --host <host>            Host for a schemeless URL/path (default: localhost)
  --tls                    Use https for a schemeless URL/path
  -v, --verbose            Show request and response headers

  Exits with code 22 on a non-2xx response (like curl --fail).

ENVIRONMENT

  PORT                     Default port to listen on
  HOST                     Default host to bind to
  NODE_ENV                 Set to production for production mode.

Port and host precedence

The port and host are resolved with the following precedence (highest first):

CLI flag (--port / --host / --hostname)

Module option (port / hostname exported from your server entry)

Environment variable (PORT / HOST)

Default (3000 / all interfaces)

Exit codes

In fetch mode, srvx fetch exits with code 22 for any non-2xx response, and 0 for a 2xx response.

This diverges from curl, which exits 0 regardless of the HTTP status unless you pass --fail. With srvx fetch the non-2xx exit is the default, so no extra flag is needed to make a failing request fail your script.

Runtime notes

The --import flag preloads an ES module (e.g. a loader like jiti/register). It is applied on Node.js and Bun only — on Deno it is silently ignored, since Deno does not support Node's --import preload flag.

Serving static files

The CLI can serve a directory of static files, similar to serve. No server entry is required — point --static at any folder:

npx srvx --static ./dist

If --static is omitted, srvx serves files from a public/ directory when one exists. When both a server entry and a static directory are present, static files take priority and unmatched requests fall through to your handler.

Static serving includes automatic index.html resolution, .html extension fallback (e.g. /aboutabout.html), common MIME types, gzip/Brotli compression, and path-traversal protection.

srvx/static is Node-API-only — it uses node:fs and node:zlib internally, so despite the runtime-neutral name it only works on runtimes with Node.js compatibility (Node, Deno, Bun).

For programmatic usage, import the serveStatic middleware:

server.ts
import { serve } from "srvx";
import { serveStatic } from "srvx/static";

serve({
  middleware: [serveStatic({ dir: "public" })],
  fetch: () => new Response("Not found", { status: 404 }),
});