>_devkit
deploy-pipeline
skills/deploy-pipeline/

references/cli.md

The Dokploy CLI

The pipeline never uses this. Deploys go through the webhook, as described in runtime.md. The CLI is for the other half of the job: asking a running server what it has, and changing it by hand when a pipeline is not the right tool.

Keep the two straight. If a deploy can be triggered by a push, it should be. The CLI is for inspection, one-off administration, and the things there is no hook for.

Install

There is no standalone binary. It ships only as an npm package, @dokploy/cli, with engines: node >=18, so a Node runtime is a hard prerequisite even if the box runs nothing else in Node.

npm install -g @dokploy/cli
dokploy --help

Userland install, no root, on a box with no Node at all:

# Node LTS into ~/.local, verified against the published checksums
NV=v24.18.0
curl -sLO "https://nodejs.org/dist/$NV/node-$NV-linux-x64.tar.xz"
curl -sL  "https://nodejs.org/dist/$NV/SHASUMS256.txt" | sha256sum -c --ignore-missing
mkdir -p ~/.local/node
tar xJf "node-$NV-linux-x64.tar.xz" -C ~/.local/node --strip-components=1
ln -sfn ~/.local/node/bin/{node,npm,npx} ~/.local/bin/

npm install -g @dokploy/cli
ln -sfn ~/.local/node/bin/dokploy ~/.local/bin/dokploy

Everything lands under ~/.local, so removing it is rm -rf ~/.local/node and the symlinks. Nothing touches system packages.

Authenticating

The API key comes from the Dokploy dashboard, not from a password:

dokploy auth -u https://dokploy.<domain> -t <api-key>

Both flags are optional and prompted for if omitted. -u is the panel origin with no path; the client appends /api itself.

Where the token lives, and why that matters

Not in ~/.config. dist/client.js resolves its config relative to its own location:

const configPath = path.join(__dirname, "..", "config.json");

so the credentials land inside the installed package:

<npm-prefix>/lib/node_modules/@dokploy/cli/config.json

Two consequences, both of which will bite:

  • Upgrading logs you out. npm update -g @dokploy/cli, or any reinstall,

replaces that directory and takes the token with it. Re-run dokploy auth after every upgrade, and do not be surprised when a version bump appears to break authentication.

  • npm creates it world-readable. It arrives 0644, sometimes 0664, holding

a plaintext API key with full control of the panel. Fix it, every time you authenticate:

``sh chmod 600 "$(npm root -g)/@dokploy/cli/config.json" ``

Prefer environment variables

readAuthConfig() checks the environment before the file, and env wins when both a URL and a token are present:

VariableMeaning
DOKPLOY_URLpanel origin, no path
DOKPLOY_API_KEYAPI key. DOKPLOY_AUTH_TOKEN is accepted as an alias

This survives upgrades, keeps the secret out of a file that npm owns, and is the only sane option in CI. Both must be set; one alone falls back to the file.

One trap: the CLI auto-loads .env from the current working directory on every invocation. A project-local .env that happens to define DOKPLOY_* will silently retarget the CLI at a different server. Existing process environment takes precedence, so exporting the values yourself is the way to be sure which server you are talking to.

Command names come from the API, not from a CLI designer

The command tree is generated from the server's tRPC routes, so the verbs are API method names rather than the nouns a CLI would normally use. There is no list:

dokploy project all           # not "project list"
dokploy project one --help
dokploy project home-stats

camelCase routes become kebab-case commands. When a guess fails, ask the binary rather than reasoning about it:

dokploy --help                # top-level groups
dokploy <group> --help        # the real verbs

A quick check that auth works end to end, and the first thing to run after setting it up:

dokploy project all

--version lies

It prints a stale hardcoded string (0.3.0 at the time of writing) that has no relationship to the installed release. The package is fine; the literal in the bundle is wrong. For the real version:

npm ls -g --depth=0 @dokploy/cli

Do not use dokploy --version to decide whether an upgrade landed.

The API underneath

Useful when the CLI has no command for what you need. Every call is tRPC over HTTP with the key in a header:

BASE    <url>/api
GET     /trpc/<endpoint>?input=<url-encoded-json>
POST    /trpc/<endpoint>     body: {"json": <payload>}
HEADER  x-api-key: <api-key>

Responses unwrap from result.data.json. So a bare curl equivalent of project all is:

curl -s -H "x-api-key: $DOKPLOY_API_KEY" \
  "$DOKPLOY_URL/api/trpc/project.all" | jq '.result.data.json'

That is the escape hatch when a generated command is missing or broken.

Maintainability

The CLI is not a deployment path. Anything you do with it by hand is invisible to git log, which is the whole point of the branch-is-an-environment model. If you find yourself running dokploy commands to get a release out, the pipeline is missing something. Fix the pipeline.

Treat the API key like PROMOTE_TOKEN. It is full panel control in a file that npm will happily overwrite, so it needs the same rotation story as every other secret: write down what it is for, and rotate it on a schedule rather than after an incident.

Pin what you depend on. The command surface is generated from the server's routes, so a server upgrade can rename a command with no CLI release at all. Scripts that wrap dokploy should be treated as coupled to the panel version, not to the CLI version.