Using CLI
You can run srvx with your preferred runtime without installation:
npx srvx
pnpx srvx
yarn dlx srvx
deno -A npm:srvx
bunx --bun 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.
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
--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. /about → about.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:
import { serve } from "srvx";
import { serveStatic } from "srvx/static";
serve({
middleware: [serveStatic({ dir: "public" })],
fetch: () => new Response("Not found", { status: 404 }),
});