CLI Commands
This page documents the full envgo command-line interface. Every flag, its short
form, its default value, and its exact behaviour is listed below.
Command syntax
envgo [subcommand] [flags] [arguments]Starting the server
envGo has two modes, selected by --config or .env:
| Invocation | Mode | What it does |
|---|---|---|
envgo | — | Prints help and exits. No server is started |
envgo run | Local | Static file server + /proxy with session token, reads HOST/PORT from .env |
envgo run dev / envgo dev | Local (dev) | Same as run, and always opens a browser |
envgo -e .env | Local | Server with flags only — .env supplies variables, but not HOST/PORT |
envgo --config routes.json | Public | Fixed routes at /api/<name>, no token handshake |
MODE_PUBLIC=true envgo run | Public | Same as --config, but via .env (CONFIG optional) |
Commands
| Command | Description |
|---|---|
envgo | Print help and exit — a bare envgo never starts a server |
envgo run | Start the server and read HOST/PORT from .env |
envgo run dev | Start in dev mode (implies --browser) |
envgo dev | Alias for envgo run dev |
envgo run update | Check for and install the latest envGo release in place |
envgo cache clear | Broadcast a hard reload to all connected dev-server browser tabs |
envgo init | Create a starter project in the current directory |
envgo init -name myapp | Create the starter project in a new myapp/ directory |
envgo deploy | Generate Caddyfile, nginx.conf, Dockerfile |
envgo -v | Print version and exit |
envgo -h | Show help and exit |
Flags
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--port | -p | int | 8080 | Port to listen on |
--host | string | 127.0.0.1 | Interface to bind. Keep 127.0.0.1 for local-only access | |
--dir | -d | string | . | Web root directory to serve |
--env | -e | string | .env | Path to the .env file |
--allow | -a | string | (empty) | Comma-separated outbound host allowlist |
--config | -c | string | (empty) | Path to routes JSON. Setting it enables public mode |
--dashboard | -D | bool | false | Enable the metadata dashboard in public mode |
--tls | bool | false | Serve HTTPS with an auto-generated self-signed certificate | |
--browser | -b | bool | false | Open the browser automatically after start |
--qr | bool | false | Bind all interfaces and print a scannable QR code of the LAN URL | |
--qr-format | string | ansi | QR output: ansi (terminal) or png (terminal + PNG file). Requires --qr. | |
--debug | bool | false | Verbose logging | |
--name | string | (empty) | Project name for envgo init (empty = current directory) | |
-o | string | (empty) | Output directory for envgo deploy (default: ./deploy) | |
--version | -v | bool | false | Print version and exit |
--help | -h | bool | false | Show help and exit |
Behaviour details
Port fallback
If the requested port is already in use, envGo tries the next 19 ports
(8080 → 8081 → … → 8099) before giving up. The address actually bound is
printed at startup, so check the log if you do not get the port you asked for.
Sharing with a phone: --qr
--qr answers “how do I open this on my phone?” — it binds every interface so
other devices on the same Wi-Fi can reach the server, then prints a QR code that
encodes the LAN address.
envgo run dev --qr[envGo] --qr: binding all interfaces so other devices on this network can connect
[envGo] envGo running -> http://127.0.0.1:8080/
[envGo] envGo network -> http://192.168.1.20:8080 (same network only)
Scan with a phone on the same network to open: http://192.168.1.20:8080
█▀▀▀▀▀█ ▀▀ ▄█ ▀ █▀▀▀▀▀█
█ ███ █ ▀█▀▀▄█▀▄ █ ███ █
█ ▀▀▀ █ ▄▄ █▀▀ █ █ ▀▀▀ █
▀▀▀▀▀▀▀ ▀ ▀▄█ ▀ ▀ ▀▀▀▀▀▀▀
█ █▄▄▄▀▀▄▄▄▄▄▄██ ▄▄▀ ▄▀▄█
▀▄█ █ ▀▄▄▄▄ ▄ ▀██▀█ ██▀ ▀
▀ ▀▄██▀ ▀▀▄▀ ▄█▄▀▀█ ▄█
▀▀█▀▀█▀▀ ██▀ ▀▀▀▀ ▄ ▀▀▀ ▀
▀▀▀ ▀▀▀▄ ▀▀█ █▄█▀▀▀█ ▄▀▄
█▀▀▀▀▀█ ▀▀▄▄█▀▀ █ ▀ █▀ ▀
█ ███ █ █▄ ▀▄█▀█▀▀███▄█
█ ▀▀▀ █ ▀▄█▀▀▀▀▄█ ██ ▀▀
▀▀▀▀▀▀▀ ▀ ▀▀ ▀▀▀ ▀ ▀ ▀

envgo —qr-format png.Key details:
- Both URLs are printed.
localis for this machine,networkis the one to scan. The QR always encodes the LAN address — never127.0.0.1, which is meaningless from a phone. - Only the host changes. The port is whatever
.envor--portresolved to. --qrworks with or withoutrun dev.envgo -e .env --qris fine; the subcommand is not required.- You do not need to pass
--host.--qroverrides a127.0.0.1default. If you did set--hostto a specific non-loopback address, envGo leaves it alone.
--qr-format
| Value | Result |
|---|---|
ansi (default) | Prints the QR to the terminal using block characters |
png | Prints the QR to the terminal and writes qrcode_<ip>_<port>.png in the current directory |
envgo run dev --qr --qr-format png# ...terminal QR...# [envGo] QR code also written to qrcode_192.168.1.20_8080.pngUse png when your terminal mangles the block characters — SSH sessions, some
Windows consoles, and CI logs commonly do. It adds a PNG file; it never
suppresses the terminal QR, so the command always shows something. Only the
literal value png (any case) writes a file; anything else — including a typo
like --qr-format image — simply prints to the terminal instead of erroring.
--qr-format needs --qr. On its own envGo warns that no QR will be produced
rather than silently ignoring the flag.
The QR is rendered by an encoder built into the binary (no dependency, no network call), so it works fully offline.
HOST, PORT, and MODE_PUBLIC from .env
HOST/PORT are only read when you use envgo run or envgo run dev, and only if
you did not override them on the command line:
HOSTis used only when--hostis still at its default127.0.0.1PORTis used only when--portis still at its default8080
Both uppercase (HOST) and lowercase (host) keys are accepted. A leading colon
in PORT is stripped, so PORT=:3000 works.
MODE_PUBLIC / CONFIG are read on every start, when --config is not given:
MODE_PUBLIC=true/1/yes/public→ public mode (looks forenvgo.routes.jsonorroutes.json)MODE_PUBLIC=false/0/no/local→ local mode- Aliases:
MODE,PUBLIC_MODE,ENVGO_MODE(same values) CONFIG/ENVGO_CONFIG/ROUTES= explicit path (wins overMODE_PUBLIC), relative paths resolved against.envdir and--dir- Flag
--configalways wins over.env
Example:
MODE_PUBLIC=true# or CONFIG=custom/myroutes.jsonenvgo run dev # no flag needed — reads MODE_PUBLIC from .envWith plain envgo --config … --port 8080, .env is not consulted for
HOST/PORT. This trips people up when editing .env to change the port of a
systemd service — pass --port explicitly there instead.
Security default: no --allow means no proxy
If --allow is empty and you are not in public mode, envGo prints a warning
and disables the proxy entirely:
[envGo] WARN no --allow set: proxy is DISABLED for security. Use -a/--allow host1,host2This is deliberate SSRF protection. Host matching accepts exact hosts and
subdomains, so --allow openai.com also permits api.openai.com.
.env vs .env.example check
At startup envGo compares key names in the file given by --env against
.env.example in the same directory and prints a warning per mismatch:
- a key in
.envbut not in.env.example→warning - a key in
.env.examplebut not in.env→hint
Values are never compared.
Public mode disables the local endpoints
When --config is set or MODE_PUBLIC=true / CONFIG in .env enables public mode, /proxy, /__envgo_token, the legacy /__env/* path
and the dashboard are all disabled (the last one unless you also pass
--dashboard). Only /api/<name> plus static files are served.
Shutdown
SIGINT (Ctrl-C) and SIGTERM trigger a graceful shutdown with a 3-second
drain timeout, so in-flight responses get a chance to finish. This is what
systemctl stop envgo sends.
Examples
All examples below use placeholder values — replace them with your own.
# Start a local server with an explicit directory, env file, and allowlistenvgo --dir . --env .env --allow httpbin.org
# Dev mode: reads HOST/PORT from .env and opens the browserenvgo run dev
# Open it on your phone: bind the LAN interface and print a scannable QR codeenvgo run dev --qr
# Same, but write the QR to a PNG file instead of the terminalenvgo run dev --qr --qr-format png
# Dev mode with verbose logging (flag AFTER the subcommand)envgo run dev --debug
# Different port, restricted allowlist, auto-open browserenvgo -p 3000 -d . -e .env -a api.openai.com -b
# Public mode: fixed routes, no token handshake (via flag)envgo --config envgo.routes.json --env .env --dir . --host 127.0.0.1 --port 8080
# Public mode via .env (no flag) — set MODE_PUBLIC=true or CONFIG=envgo.routes.json in .envenvgo run dev
# Public mode with the dashboard enabled (for debugging only)envgo --config envgo.routes.json --env .env --dashboard
# HTTPS with a self-signed certificateenvgo --tls --dir . --env .env --allow api.openai.com
# Create a starter projectenvgo initenvgo init -name myapp
# Generate deployment configsenvgo deploy -o ./deploy
# Update envgo in placeenvgo run update
# Force a hard reload in every dev-server browser tabenvgo cache clear
# Show help (what a bare `envgo` does)envgoenvgo deploy -o ./deploy writes three files: Caddyfile, nginx.conf, and
Dockerfile. See Docker Deployment for how to use
them.
What envgo init creates
Running envgo init writes five files into the target directory:
| File | Contents |
|---|---|
.env | MY_SECRET=change-me, HOST=127.0.0.1, PORT=8080, # MODE_PUBLIC=false, # CONFIG=envgo.routes.json (mode 0600, commented by default) |
.env.example | The same placeholder content |
index.html | Minimal page with <div id="MY_SECRET"></div> and /__env.js |
.gitignore | Ignores .env, *.key, *.secret |
README.md | Generated quick-start notes |
Also note that .env and .env.example are written with identical content, so
the generated .env holds a placeholder, not a real secret. Edit .env before
running.
Next steps
- Sharing with your phone —
--qrand LAN access in detail - Configuration — routes JSON reference for public mode
- Threat Model — what each guard protects against
- Local Mode — development workflow
- Public Mode — production gateway