Docs · reference

denv CLI

Every denv command, subcommand, and flag, with the configuration the CLI reads.

The denv binary is a thin client over the REST API: every verb maps to one endpoint and prints the JSON response, indented. Errors print denv: <message> to stderr and exit 1; usage errors exit 2.

Invocation rules

  • Flags go before positional arguments. denv fork --name f1 alpha works; denv fork alpha --name f1 treats --name as a positional and fails. This is Go's flag package behaviour and applies to every command.
  • Subcommands (project create, env get, files put, …) take their own flags after the subcommand name.
  • Commands that start a deployment (deploy, fork, snapshot, verify, rollback) default to --wait, which polls the deployment and prints one line per phase as it changes, then deployment <id>: <status>. A failed deployment exits 1. Pass --wait=false to print the 202 response and return.
  • The HTTP client timeout is 5 minutes per request.

Configuration

Source Precedence Notes
DENV_API_KEY first A team API key (dak_…) or a user session token (dst_…).
DENV_SERVER first Base URL of the control plane. Default http://localhost:8080.
~/.config/denv/config.json fallback Written by denv login. Read only when DENV_API_KEY is unset. Its server is used only when DENV_SERVER is also unset.
XDG_CONFIG_HOME — When set, the config file is $XDG_CONFIG_HOME/denv/config.json.

The config file has three keys: server, api_key, team (the team id the key was approved for). It is written with mode 0600.

With no credential, any command prints denv: not signed in: run denv login or set DENV_API_KEY.

Commands

login

denv login [--server URL] [--no-browser]

Runs the device flow: asks the server for a code, prints the console URL and the user code, opens the browser at the verification_uri_complete URL unless --no-browser is given, then polls POST /v1/device/token every interval seconds until a key is issued or the code expires (15 minutes). On success it writes the config file and prints Signed in to team <name>. Key saved to <path>.

--server defaults to DENV_SERVER (or the saved server, or http://localhost:8080). This command parses its own two flags and ignores anything else.

whoami

denv whoami

GET /v1/me. Prints {team, teams[], user?}.

templates

denv templates [--kind K]

GET /v1/templates?kind=K. Prints the known kinds (rl-environment, agent) and the templates, each with its compose text.

init

denv init <kind|template> [--out compose.yaml]

Fetches the templates and writes the compose file of the first template whose name or kind matches the argument to --out (default compose.yaml). Refuses to overwrite an existing file (<out> exists; pass --out to write elsewhere). When the template has a warm command, prints the denv deploy … --warm invocation to use. Templates today: rl-environment-ops (kind rl-environment) and agent-runtime (kind agent).

project

denv project create [--kind K] [--source github:org/repo] <name>
denv project list
denv project envs <project>
Subcommand Endpoint Flags
create POST /v1/projects --kind (rl-environment, the default, or agent); --source free text, conventionally github:owner/repo
list GET /v1/projects —
envs GET /v1/projects/{project}/envs <project> is a name or an id

Creating a project also creates its alpha environment.

cloud

denv cloud connect <provider> [--name N] [--token T] [--server-type T] [--location L]
denv cloud list

connect posts {provider, name, config} to POST /v1/clouds, where config holds only the flags that were set, under the keys token, server_type, location. Providers compiled in: manual, hetzner, e2b, daytona. The provider validates the token before the cloud is recorded. For e2b and daytona the cloud becomes a driver host (a target) the next time targets are listed; see Targets. Those two providers are untested against the live provider.

list is GET /v1/clouds; secrets in config are returned as •••.

host

denv host list
denv host join-token

list is GET /v1/hosts (each host with a connected flag). join-token is POST /v1/join-tokens with an empty body; the response includes token (djt_…, single use, valid 1 hour), expires_in_sec, and command, a ready-to-paste install line.

deploy

denv deploy --project P [--env alpha] [-f compose.yaml] [--warm "cmd args"] [--wait]

Reads the compose file and posts {env, compose, warm} to POST /v1/projects/{project}/deploy. --project is required. --warm is split on whitespace into the warm command's argv. Prints the deployment id, then the phases.

env

denv env get <env>
denv env versions <env>
denv env deployments <env>
denv env destroy <env>

get, versions, deployments are the corresponding GET /v1/envs/{env}… routes. destroy is DELETE /v1/envs/{env}; it prints the destroy deployment and does not wait. <env> is always an environment id (env_…), never a name.

fork

denv fork [--name N] [--version V] <env>

POST /v1/envs/{env}/fork with {name, version}. --version defaults to the environment's current version; --name defaults to <env name>-fork-<n>. Waits by default.

snapshot

denv snapshot <env>

POST /v1/envs/{env}/snapshot. Captures live state as a new version of the same environment. Waits by default.

verify

denv verify [--resume] <env>

POST /v1/envs/{env}/verify with {resume}. Freezes the agent service, collects the declared paths, snapshots, forks, grades on the fork. Without --resume the agent service stays paused afterwards. The reward is in the verdict phase's evidence. See Deployments and Compose. Waits by default.

files

denv files put --service S <env> <local path> <container dir>
denv files get --service S <env> <container path> <local dir>

put tars the local file or directory (named by its base name) and uploads it with PUT /v1/envs/{env}/files?service=S&path=<container dir>; the archive is extracted into that directory. The archive limit is 32 MiB. get downloads <container path> as a tar via GET /v1/envs/{env}/files and extracts regular files and directories under <local dir>, printing <n> files written under <local dir>. --service is required for both.

rollback

denv rollback <env> <version>

POST /v1/envs/{env}/rollback with {version}. The version must be a healthy snapshot of that environment. Waits by default.

exec

denv exec --service S <env> -- <cmd...>

POST /v1/envs/{env}/exec with {service, cmd}. The -- separator is optional; everything after <env> is the argv. The server-side default timeout is 120 s. Prints {exit_code, stdout, stderr}. A non-zero exit code is not a CLI error.

deployment

denv deployment get <id>
denv deployment watch <id>

get prints {deployment, phases[]}. watch polls every 700 ms and prints phases as they change, as the --wait commands do.

events

denv events <subject>

GET /v1/events?subject=<subject> where the subject is env:<id>, dep:<id>, or host:<id>. Returns up to 200 events, newest first.

Not yet available

  • denv promote, denv prove, denv sheet, denv export, denv import: described in the blog, not in the binary.
  • Project names are accepted everywhere an id is for projects; environments and deployments require ids.