deeplo
Reference

CLI reference

deeplo commands, grouped by function.

deeplo is a single binary with two roles:

  • deeplo daemon — the long-running daemon: webhook listener, poller, deploy runner. In a native install this is run by systemd; in Docker it is the container's default command.
  • deeplo <cmd> — operator CLI for inspecting state, managing the install, and triggering runtime actions.

Commands are grouped by function:

GroupCommandsDaemon required?
Statestatus, runs, logs, health, versionNo (reads local files on native installs)
Controldaemon, reload, refreshYes
Localcheck, doctor, configNo
Systemservice, env, update, removeNo (native only)

For daemon environment variables, see Bootstrap config.


deeplo daemon

Starts the deployment daemon. Configured exclusively via DEEPLO_* environment variables.

deeplo daemon

In a native install, systemd manages this. In Docker, it is the container's default command. You do not normally need to run it directly.


deeplo status

Shows the latest recorded deployment state for each (project, host) pair.

On native installs, reads local state files directly — no daemon required. On Docker installs, queries the running daemon.

deeplo status

If no deployments have been recorded yet:

No deployments recorded yet.
Trigger one by pushing to a tracked branch, or wait for the poller.

Example:

$ deeplo status
PROJECT    HOST    STATUS   COMMIT    TRIGGER   STARTED
-------    ----    ------   ------    -------   -------
api        web-1   success  a3f2bc9   webhook   2026-04-14T15:30:00Z
api        web-2   success  a3f2bc9   poll      2026-04-14T15:30:01Z
worker     web-1   failed   8892eb0   webhook   2026-04-14T14:00:00Z

deeplo runs

Lists recent deploy runs, most recent first.

On native installs, reads local state files directly — no daemon required. On Docker installs, queries the running daemon.

deeplo runs [--limit N] [--project NAME]

Flags:

FlagDefaultDescription
--limit20Maximum number of runs to show
--projectFilter by project name

If no runs have been recorded yet:

No runs recorded yet.

Example:

$ deeplo runs --limit 5
ID                      PROJECT   HOST    STATUS   COMMIT    TRIGGER   STARTED
--                      -------   ----    ------   ------    -------   -------
1744660003-a3f2bc91     api       web-1   success  a3f2bc9   webhook   2026-04-14T15:30:00Z
1744659801-9d3e4f22     worker    web-1   failed   8892eb0   webhook   2026-04-14T14:00:00Z

Use the run ID with deeplo logs to see the full deploy log.


deeplo logs

Prints the full log for a specific deploy run.

On native installs, reads the log file directly — no daemon required. On Docker installs, fetches the log from the running daemon.

deeplo logs <run-id>

Example:

$ deeplo logs 1744660003-a3f2bc91
=== Deploy Run 1744660003-a3f2bc91 ===
Project:  api
Host:     web-1 (10.0.0.10)
Commit:   a3f2bc9...
...
[15:30:00Z] Fetching repository git@github.com:org/api.git
[15:30:02Z] Commit a3f2bc9 is available
[15:30:02Z] Connecting to web-1 (deploy@10.0.0.10:22)
[15:30:03Z] Running docker compose up in /srv/apps/api
[15:30:07Z] Deploy succeeded in 7.2s

deeplo health

Shows service health. On native installs, checks the systemd service state — never fails with a raw socket error. On Docker installs, pings the admin socket directly.

deeplo health

Exit code: 0 = service running (native) or daemon reachable (Docker); non-zero otherwise.

Example — native install, service running:

$ deeplo health
Service:  running
Enabled:  yes
Socket:   present
Daemon:   reachable
Version:  v0.2.0
Uptime:   4h32m15s

Example — native install, service stopped:

$ deeplo health
Service:  stopped
Enabled:  yes
Socket:   missing
Daemon:   not checked (socket missing)

Service is not running. To start:
  sudo systemctl start deeplo

Example — Docker, daemon reachable:

$ docker exec deeplo deeplo health
Daemon:   reachable
Version:  v0.2.0
Uptime:   4h32m15s

deeplo version

Prints the CLI version and, if the daemon is reachable, its version too.

deeplo version

Example — daemon running:

$ deeplo version
deeplo:  v0.2.0
daemon:  v0.2.0

Example — daemon not running:

$ deeplo version
deeplo:  v0.2.0
daemon:  not reachable

deeplo reload

Asks the daemon to re-read its managed config immediately. Requires the daemon to be running.

deeplo reload
  • In local mode: re-reads the config file from disk.
  • In git mode: fetches the latest commit from the config repo.

If the config is unchanged, the daemon does nothing (not an error). If the config is invalid, the daemon rejects it and keeps the current config; the error is returned to the CLI.


deeplo refresh

Asks the daemon to SSH into all configured hosts and run docker compose ps for each project, returning the live container state. Requires the daemon to be running.

deeplo refresh

If no hosts are configured:

No hosts configured.

Example:

$ deeplo refresh
PROJECT   HOST    SERVICE   STATE     STATUS
-------   ----    -------   -----     ------
api       web-1   api       running   Up 3 hours
api       web-1   redis     running   Up 3 hours
worker    web-1   worker    exited    Exited (1) 2 hours ago

deeplo check

Validates the config file offline. Does not require the daemon to be running.

deeplo check [--config FILE] [--probe-hosts]

Flags:

FlagDefaultDescription
--config/etc/deeplo/config.ymlPath to the config file
--probe-hostsfalseDial each host over SSH and verify connectivity

SSH settings for --probe-hosts are read from bootstrap environment variables (DEEPLO_SSH_KEY_FILE, DEEPLO_SSH_PORT, etc.).

Exit codes: 0 = success, non-zero = load, validation, or probe failure

Example — valid config:

$ deeplo check --config /etc/deeplo/config.yml
Config OK: /etc/deeplo/config.yml (version 1, 2 host(s), 1 repo(s), 3 project(s))

Example — errors:

$ deeplo check --config config.yml
ERROR  repos[0].url              url is required
ERROR  projects[0].targets[0]   target "missing-host" does not reference a known host
Config INVALID: 2 error(s), 0 warning(s) in config.yml

Example — probe hosts:

$ deeplo check --config config.yml --probe-hosts
Config OK: config.yml (version 1, 2 host(s), 1 repo(s), 2 project(s))
PROBE OK    web-1     10.0.0.10
PROBE FAIL  web-2     dial tcp 10.0.0.11:22: connection refused
1 host(s) unreachable

deeplo doctor

Runs a local diagnostic and reports pass/fail for key conditions. Does not modify files or restart services. Works in both native and Docker environments.

deeplo doctor

Checks performed:

CheckNotes
config fileexists and is readable
daemonadmin socket reachable
env filenative installs only
unit filenative installs only
service enablednative installs only
service runningnative installs only
SSH key configuredDEEPLO_SSH_KEY_FILE is set
SSH key file existsthe referenced file is present

Systemd-specific checks are skipped automatically when running in Docker or any non-systemd environment.

Exit code is non-zero if any check fails.


deeplo config

Commands for working with the managed config file. The config file path is read from DEEPLO_CONFIG_FILE (default: /etc/deeplo/config.yml). Available on all install types.

deeplo config path    Print the path to the config file
deeplo config edit    Open the config file in an editor

deeplo config edit selects the editor automatically:

  • If the file is writable by the current user, opens it with $VISUAL > $EDITOR > vi.
  • If the file is not writable (e.g. root-owned on a native install), uses sudoedit — you are never left with a read-only buffer.

After the editor exits successfully, the command prints the file path and next steps. The daemon is not automatically reloaded.

Example output (root-owned file):

Opening /etc/deeplo/config.yml with sudoedit...
[editor opens]
Edited /etc/deeplo/config.yml

Next steps:
  deeplo check          validate your changes
  deeplo reload         apply changes without restarting the daemon
  deeplo service restart  or restart the service if needed

deeplo service (native installs only)

Convenience wrappers around systemctl for the deeplo systemd unit. Only available on native systemd installs.

deeplo service status     Show the deeplo service status
deeplo service start      Start the service
deeplo service stop       Stop the service
deeplo service restart    Restart the service
deeplo service enable     Enable the service to start on boot
deeplo service disable    Disable the service from starting on boot
deeplo service logs       Show service logs (via journalctl)

Privilege model: status and logs run as the current user. Mutating commands (start, stop, restart, enable, disable) require root; when not running as root they prepend sudo automatically.

deeplo service logs flags:

FlagDefaultDescription
--follow / -ffalseStream live log output
--lines / -n50Number of recent lines to show (0 = all)

deeplo env (native installs only)

Commands for working with the deeplo env file (/etc/deeplo/deeplo.env). Not available in Docker deployments.

deeplo env path    Print the path to the env file
deeplo env edit    Open the env file via sudoedit

deeplo env edit always uses sudoedit (the env file is root-owned). After a successful edit it prints the file path and a reminder to restart the service for env changes to take effect.


deeplo update (native installs only)

Downloads and installs the latest deeplo release. Restarts the daemon if it was running before the update.

deeplo update [--version TAG]

Flags:

FlagDefaultDescription
--versionVersion to install (default: latest release)

Example — update to latest:

$ deeplo update
Fetching latest version...
Updating deeplo to v0.3.0...
Downloading deeplo v0.3.0 (linux/amd64)...
  ✓ Installed binary to /usr/local/bin/deeplo
Restarting deeplo service...
  ✓ Restarted deeplo

deeplo updated to v0.3.0

Example — install a specific version:

deeplo update --version v0.2.1

Fails clearly with an error on Docker or non-systemd hosts.


deeplo remove (native installs only)

Removes the deeplo binary and systemd service from this host. Config and data are preserved by default.

deeplo remove [--purge] [--yes]

Flags:

FlagDefaultDescription
--purgefalseAlso remove /etc/deeplo, /var/lib/deeplo, and the deeplo system user
--yesfalseSkip the confirmation prompt

Example — standard remove:

$ deeplo remove
This will stop and remove the deeplo service and binary.
Continue? [y/N] y
Removing deeplo...
  ✓ Stopped deeplo
  ✓ Removed /etc/systemd/system/deeplo.service
  ✓ Removed /usr/local/bin/deeplo

deeplo removeed. Config and data preserved.
  Config: /etc/deeplo
  Data:   /var/lib/deeplo

To also remove config and data: deeplo remove --purge

Example — full purge:

deeplo remove --purge --yes

Fails clearly with an error on Docker or non-systemd hosts.


Shell completion

deeplo completion bash
deeplo completion zsh
deeplo completion fish
deeplo completion powershell

Install bash completion (system-wide):

deeplo completion bash | sudo tee /etc/bash_completion.d/deeplo > /dev/null

Install zsh completion:

deeplo completion zsh > "${fpath[1]}/_deeplo"

Install fish completion:

deeplo completion fish > ~/.config/fish/completions/deeplo.fish

Common workflows

Validate config before restarting:

deeplo check

Check SSH connectivity:

deeplo check --probe-hosts

Show service health:

deeplo health

Run full local diagnostic:

deeplo doctor

View what's deployed:

deeplo status

Inspect live runtime state:

deeplo refresh

Apply a config change without restarting:

deeplo config edit
deeplo check
deeplo reload

Debug a failed deploy:

deeplo runs --limit 10
deeplo logs <run-id>

Tail daemon logs (systemd):

deeplo service logs --follow

Tail daemon logs (Docker):

docker compose logs -f

Advanced: admin socket

Some commands communicate with the running daemon over a Unix socket at /run/deeplo/deeplo.sock. This is an internal transport detail. State inspection commands (status, runs, logs) read local files directly on native installs and only use the socket as a fallback.

If you need to override the socket path (e.g. for testing or non-standard installs), pass --socket <path> to any command that contacts the daemon. This flag is intentionally omitted from normal help output.

On this page