CLI Reference

The kodo CLI lets you manage sites, domains, backups, cron, and SSH access from your terminal. Everything available in the API is available through the CLI.

Installation

Download the latest binary for your platform from the releases page, or build from source:

$ go install github.com/koddrio/kodo@latest

Configuration

The CLI reads configuration from three sources, in order of precedence:

  1. Command-line flags (--secret)
  2. Environment variables (KODO_SECRET)
  3. Config file at ~/.kodo.yaml
# ~/.kodo.yaml
secret: your-api-token
org: org_7mRk2

Authentication

The recommended way to authenticate is through the login command, which opens a browser flow and saves your token to ~/.kodo.yaml:

$ kodo auth login
Opening browser for authentication...
 Logged in as [email protected]

$ kodo auth whoami
[email protected] (acme)

For automation and CI, you can also authenticate via environment variables or CLI flags:

# Environment variable
$ export KODO_SECRET=your-api-token

# Or CLI flag (overrides everything else)
$ kodo --secret your-api-token org list

Precedence: CLI flag > environment variable > ~/.kodo.yaml

kodo org list

List organizations you belong to. The active org is marked with a checkmark.

$ kodo org list

  ID                   NAME
  ———————————————
  org_7mRk2              acme        
  org_9xPq4              widgets

kodo org use <name>

Switch the active organization. New sites will be created in this org.

$ kodo org use widgets
 Active org: widgets

kodo site create

Create a new WordPress site. Optionally provision from a YAML blueprint.

$ kodo site create --region lhr

  Site ID          site_4kR9x2mNpQw
  URL              https://happy-panda-042.koddrio.site
  Admin user       [email protected]
  Admin password   kX9mR2pL4qNw

! Save the admin password — it won't be shown again.

  Provisioning...
  - Creating containers
  - Installing WordPress
 Site is ready.

With a blueprint:

$ kodo site create --from blueprint.yml --region dca

Flags: --region (default: dca), --from (path to YAML blueprint)

kodo site list

List all sites in the active organization.

$ kodo site list

  ID                                      STATUS
  ———————————————————
  site_4kR9x2mNpQw                          active
  site_8nQp3wXy2Rs                          active

kodo site get <site> [key]

Get site details, a config section, or a specific value. Sites can be addressed by ID, internal domain, or custom domain.

# Full site details
$ kodo site get site_4kR9x2mNpQw

# A config section
$ kodo site get mysite.com php
  php.version          8.4
  php.workers          4
  php.memory           256

# A single value
$ kodo site get mysite.com php.workers
4

# Full config as YAML
$ kodo site get mysite.com --yaml

kodo site set <site> <key> <value>

Update a single config value. Changes that affect containers will trigger an update job.

$ kodo site set mysite.com php.workers 8
 php.workers = 8
  Applying...
 Done.

kodo site default <site> <key>

Reset a config value to its default.

$ kodo site default mysite.com php.workers
 php.workers = 4 (default)

kodo site edit <site>

Open the site config in your $EDITOR as YAML. Save and close to apply changes. You can also edit domains and cron entries inline.

$ kodo site edit mysite.com
# Opens $EDITOR with:
php:
  version: "8.4"
  workers: 8
  memory: 256

cache:
  driver: redis
  memory: 128

domains:
  - name: mysite.com
    primary: true
  - name: www.mysite.com

cron:
  - schedule: "*/5 * * * *"
    command: wp cron event run --due-now

Internal keys (purge_key, cache.salt, etc.) are hidden. Cron entry IDs are stripped. Adding/removing domains triggers DNS verification.

kodo site apply <site> -f <file>

Apply a YAML config file to a site. Only changed values are sent to the API.

$ kodo site apply mysite.com -f config.yaml
 php.workers = 8
 php.memory = 512
  Applying...
 Done.

kodo site destroy <site>

Destroy a site and all its data. Prompts for confirmation unless --yes is passed.

$ kodo site destroy mysite.com --yes
  Destroying...
 Site destroyed.

kodo domain list <site>

List all domains attached to a site.

$ kodo domain list mysite.com

  STATUS        PRIMARY     NAME
  ————————————————————
  active                   mysite.com
  active                    www.mysite.com

kodo domain add <site> <domain>

Add a custom domain. The CLI waits for DNS and TLS verification to complete.

$ kodo domain add mysite.com shop.example.com --primary
  Name             shop.example.com
  Status           pending

  Waiting for DNS and TLS verification...
  - pending-dns
  - pending-tls
  - active
 Domain is active.
 Domain set as primary.

Flags: --primary (make this the primary domain after activation)

kodo domain set-primary <site> <domain>

Change the primary domain for a site. The domain must be active.

$ kodo domain set-primary mysite.com shop.example.com
 Done.

kodo domain remove <site> <domain>

Remove a custom domain. Internal domains cannot be removed.

$ kodo domain remove mysite.com www.mysite.com --yes
 Domain removal queued.

kodo backup list <site>

List backups for a site, sorted by date.

$ kodo backup list mysite.com

  ID              STATUS      SIZE      DATE
  ——————————————————————
  bkp_3xRm8       finished    245M      2026-04-06 08:00
  bkp_2wQn7       finished    244M      2026-04-05 08:00

kodo backup create <site>

Create a new backup. Waits for the backup job to complete.

$ kodo backup create mysite.com
  Backup ID        bkp_4yTp9
  Creating...
 Backup created.

kodo backup restore <site> <backup>

Restore from a backup. Use latest or a specific backup ID. Choose what to restore with --type.

# Restore everything
$ kodo backup restore mysite.com latest --type full

# Restore database only
$ kodo backup restore mysite.com latest --type database

# Restore files only
$ kodo backup restore mysite.com bkp_3xRm8 --type files

Types: full (default), database, files

kodo backup export <site> <backup>

Export a backup as a downloadable archive. Returns a signed URL.

$ kodo backup export mysite.com latest --type full
  Exporting...
 Download URL:
  https://backups.koddrio.com/...

kodo cron list <site>

List cron jobs for a site.

$ kodo cron list mysite.com

  ID              SCHEDULE          COMMAND
  —————————————————————————————
  cron_8xRm3      */5 * * * *       wp cron event run --due-now
  cron_2wQn7      0 0 * * *         wp cache flush

kodo cron add <site> <schedule> <command>

Add a cron job. Accepts standard cron syntax or named schedules: hourly, daily, weekly.

$ kodo cron add mysite.com daily "wp cache flush"
 Cron added: 0 0 * * * — wp cache flush
  Applying...
 Done.

$ kodo cron add mysite.com "*/10 * * * *" "wp option get home"

kodo cron remove <site> <cron_id>

Remove a cron job by ID.

$ kodo cron remove mysite.com cron_2wQn7
  Applying...
 Done.

Sending email

Every site can send email out of the box. WordPress wp_mail() — and everything built on it, like password resets, notifications, and WooCommerce receipts — is wired to a managed relay with no setup required. By default, mail is sent from noreply@<your-site>.koddrio.site.

$ kodo wp mysite.com eval 'wp_mail("[email protected]", "test", "it works");'

Custom SMTP relay

To send from your own domain — through SendGrid, Mailgun, Amazon SES, Google Workspace, or any SMTP provider — set the mail.* config. Set mail.mode to relay last: it requires the host, username, from address, and password to already be set.

$ kodo site set mysite.com mail.host smtp.sendgrid.net
$ kodo site set mysite.com mail.port 587
$ kodo site set mysite.com mail.username apikey
$ kodo site set mysite.com mail.password 'SG.xxxxxxxx'
$ kodo site set mysite.com mail.from [email protected]
$ kodo site set mysite.com mail.mode relay

The password is write-only — it is stored encrypted and never shown by kodo site get. Relays connect over STARTTLS on port 587 or 25; implicit-TLS port 465 is not supported. Make sure your from address is an authorized sending identity with your provider, or the provider will reject the message.

Revert to the built-in relay at any time:

$ kodo site set mysite.com mail.mode builtin

Delivery is asynchronous: wp_mail() returns once the message is queued, so a provider rejection surfaces as a bounce rather than a failed call. Check your provider's activity log if a test message doesn't arrive.

kodo ssh <site> [command]

Open an SSH shell to a site, or run a single command. Requires an SSH key added to your account.

# Interactive shell
$ kodo ssh mysite.com
neo@mysite:~$

# Run a command
$ kodo ssh mysite.com ls
logs  public_html

# Print the SSH command (useful for scripts)
$ kodo ssh mysite.com --print
ssh -p 22 [email protected]

kodo wp <site> [args]

Run WP-CLI commands on a site. Shorthand for kodo ssh <site> wp [args].

$ kodo wp mysite.com plugin list
$ kodo wp mysite.com option get home
$ kodo wp mysite.com cache flush

kodo db <site> [query]

Open an interactive MySQL session or run a query.

# Interactive
$ kodo db mysite.com

# Run a query
$ kodo db mysite.com "SELECT count(*) FROM wp_posts"

kodo ssh-key list

List your SSH keys.

$ kodo ssh-key list

  ID              LABEL
  ————————————————
  sshk_3xRm8      macbook-pro
  sshk_2wQn7      ci-server

kodo ssh-key add <key>

Add an SSH public key. Accepts a key string or a path to a .pub file. The label is auto-extracted from the key comment.

# From file
$ kodo ssh-key add ~/.ssh/id_ed25519.pub

# With custom label
$ kodo ssh-key add --label "deploy key" ~/.ssh/id_ed25519.pub

The CLI rejects private keys and duplicate keys with clear error messages.

kodo ssh-key remove <key_id>

Remove an SSH key. Access is revoked immediately.

$ kodo ssh-key remove sshk_3xRm8
 Key removed.

kodo site ssh-key list <site>

List SSH keys attached to a single site. Site-attached keys grant shell access to that one site only — useful for giving a collaborator (a customer's developer, a freelance agency, a CI runner) access to one site without adding them to your organization.

$ kodo site ssh-key list mysite.com

  ID              LABEL
  ————————————————
  sshk_8Yp4q      alice@agency
  sshk_5Lm2r      ci-deploy

kodo site ssh-key add <site> <key>

Attach an SSH public key to a site. Accepts a key string or a path to a .pub file. The holder of the matching private key can SSH into this site only; they get no access to other sites in your organization and no organization membership.

# From file
$ kodo site ssh-key add mysite.com ~/alice.pub --label "alice@agency"

kodo site ssh-key remove <site> <key_id>

Remove a site-attached key. Access is revoked immediately.

$ kodo site ssh-key remove mysite.com sshk_8Yp4q
 SSH key removed.

kodo logs <site> [file]

View site logs. Defaults to the last 50 lines of all log files.

# All logs
$ kodo logs mysite.com

# Follow in real-time
$ kodo logs mysite.com -f

# Specific log file
$ kodo logs mysite.com access.log
$ kodo logs mysite.com php-errors.log
$ kodo logs mysite.com cron.log

# Last 100 lines, follow
$ kodo logs mysite.com access.log -f -n 100

Flags: -f (follow), -n (number of lines)

Log files: access.log (nginx), error.log (nginx errors), php-errors.log, cron.log

Blueprints

Blueprints are YAML files that define a site's configuration and setup commands. Use them with kodo site create --from to provision preconfigured sites.

# agency-woo-blueprint.yml
php:
  version: "8.4"
  workers: 8
  memory: 256

cache:
  driver: redis
  memory: 128

environment:
  WP_ENVIRONMENT_TYPE: production

backups:
  frequency: hourly
  retention: 30

run:
  - wp plugin install woocommerce --activate
  - wp plugin install wp-redis --activate
  - wp theme install your-agency-theme --activate

The run section executes commands in order after WordPress is installed. If a command fails, execution stops.

Nested YAML config is flattened to dot-notation: php.version, cache.driver, etc.

Config keys

Available config keys for site set, site edit, and blueprints:

Key Default Values
php.version8.38.2, 8.3, 8.4
php.workers42 to 32
php.memory25664, 128, 256, 512, 1024 (MB)
php.max_execution_time301 to 90 (seconds)
php.upload_max_filesize642 to 1024 (MB)
php.post_max_size642 to 1024 (MB)
database.memory512128, 256, 512, 1024, 2048, 4096, 8192 (MB)
cache.drivernonenone, redis
cache.memory12864, 128, 256, 512, 1024 (MB)
storage.size1010 to 400 (GB)
backups.frequencydailyhourly, daily, weekly, disabled
backups.retention301 to 365 (days)
mail.modebuiltinbuiltin, relay
mail.hostSMTP relay hostname (relay mode)
mail.port5871 to 65535
mail.usernameSMTP username (relay mode)
mail.fromFrom address (relay mode)
mail.passwordSMTP password (write-only, encrypted)
environment.*Custom environment variables

Memory values accept M and G suffixes: kodo site set mysite.com php.memory 512M

Missing something? Let us know or check the API reference for the full list of endpoints.