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 alphaworks;denv fork alpha --name f1treats--nameas a positional and fails. This is Go'sflagpackage 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, thendeployment <id>: <status>. Afaileddeployment exits 1. Pass--wait=falseto print the202response 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.