Skip to content

Latest commit

 

History

History
473 lines (383 loc) · 15.7 KB

File metadata and controls

473 lines (383 loc) · 15.7 KB

qqd CLI Reference

Generated by qqd docs.

Usage

usage:
  qqd [--help]
  qqd help [command]
  qqd plan -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--output json] [services...]
  qqd init -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--force-unlock] [services...]
  qqd deploy -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--no-build] [--approve] [--dry-run] [--config-only] [--force-unlock] [services...]
  qqd build -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--force-unlock] [services...]
  qqd update -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--approve] [service[=version]...]
  qqd status -c <config> [-c <overlay>...] [-t <target>] [--output json]
  qqd logs -c <config> [-c <overlay>...] [-t <target>] [services...]
  qqd rollback -c <config> [-c <overlay>...] [-t <target>] [--force-unlock] [service]
  qqd history -c <config> [-c <overlay>...] [-t <target>]
  qqd stop -c <config> [-c <overlay>...] [-t <target>] [services...]
  qqd start -c <config> [-c <overlay>...] [-t <target>] [services...]
  qqd destroy -c <config> [-c <overlay>...] [-t <target>] [--force-unlock]
  qqd clean -c <config> [-c <overlay>...] [-t <target>]
  qqd doctor -c <config> [-c <overlay>...] [-t <target>]
  qqd validate -c <config> [-c <overlay>...]
  qqd convert -c <input> [-o <output>] [--format yaml|json|hocon]
  qqd migrate -c <config> --from <source> [--to podman] [--stack <name>] [--dry-run] [--yes]
  qqd import -f <docker-compose.yaml> [--env <.env>] [--format yaml|json|hocon] [--host <host>] [--user <user>] [--ssh-key <key>] [-o <output>]
  qqd man
  qqd docs [config] [--format markdown] [-o <path>]
  qqd manifest [--format json|md] [-o <path>]

Commands

  • plan: show deployment plan without executing
  • init: first-time setup on target(s)
  • deploy: idempotent deploy: build/pull missing images and apply changed services
  • build: build/pull images only, no deploy/restart
  • update: bump/set image version(s) and redeploy updated services
  • status: show service state/image/uptime on target(s)
  • logs: stream container logs
  • rollback: restore previous release (or rollback single service)
  • history: show deployment release history on target(s)
  • stop: stop service units
  • start: start service units
  • destroy: stop/disable units and remove generated unit files
  • clean: remove project containers and unused images from targets
  • doctor: check target environment for common problems
  • validate: check config for errors without deploying
  • convert: convert config between formats (yaml, json, hocon)
  • migrate: migrate a running Compose or Swarm stack to Podman-backed qqd
  • import: generate qqd config from a docker-compose.yaml
  • man: open installed manual page (same as man qqd)
  • docs: generate CLI or configuration documentation
  • manifest: emit the full qqd surface (commands, flags, config schema, pitfalls) for AI agents and tooling

plan

qqd plan -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--output json] [services...]

show deployment plan without executing

  • displays what deploy would do without making any changes
  • shows per-target breakdown of:
    • services that will be deployed
    • images and build actions
    • deployment mode (standard, slot-based, replicated)
    • risks (e.g. exposed-no-health, mutable-image-tag, caddy-tcp-passthrough)
  • use --output json for machine-readable output. The JSON shape is:
  • { project, runtime, proxy, sync, mode, targets[], risks[] }
  • where each risk has { level (info|warn|danger), code, message, target?, service? }
  • CI gates can fail when any risk has level="danger":
  • qqd plan -c app.yaml --output json | jq -e '.risks | map(select(.level=="danger")) | length == 0'

init

qqd init -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--force-unlock] [services...]

first-time setup on target(s)

  • first-time setup: clone repo, create dirs, build/pull images, install units, start
  • pipeline:
  • SSH to target
  • |-- mkdir -p <repo_dir>
    
  • |-- git clone <repo> (if not cloned yet)
    
  • |-- git fetch --all && git reset --hard origin/<branch>
    
  • |-- mkdir -p <dirs> (target directories)
    
  • |-- for each service:
    
  • |     image missing + has dockerfile --> build
    
  • |     image missing + no dockerfile  --> pull
    
  • |     image exists                   --> skip
    
  • |-- write unit files to systemd directory
    
  • |-- systemctl daemon-reload
    
  • |-- systemctl start <all units>
    
  • '-- verify: systemctl is-active <each unit>
    

deploy

qqd deploy -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--no-build] [--approve] [--dry-run] [--config-only] [--force-unlock] [services...]

idempotent deploy: build/pull missing images and apply changed services

  • idempotent: only builds/pulls missing images, only applies changed services
  • shows a plan and asks for confirmation before proceeding.
  • use --approve to skip the confirmation prompt (for CI/scripts).
  • use --dry-run to show the plan without executing any changes.
  • use --no-build to skip building dockerfile services (still pulls, updates config, restarts).
  • use --config-only to skip source sync and image build (only update config, env, expose, restart).
  • use --force-unlock to take the deploy lock even if another holder is recorded on the target
  • (only safe if you are sure no other deploy is in progress).
  • full deploy (no service args) removes services deleted from the config.
  • partial deploy (e.g. "qqd deploy server") leaves other services untouched.
  • pipeline:
  • SSH to target
  • |-- mkdir -p <repo_dir>
    
  • |-- git clone (if not cloned) or git fetch + reset
    
  • |-- mkdir -p <dirs>
    
  • |-- for each service:
    
  • |     image exists --> skip (no build, no restart)
    
  • |     image missing + has dockerfile --> build --> mark changed
    
  • |     image missing + no dockerfile  --> pull  --> mark changed
    
  • |-- if sync=upload + services have context: upload only context dirs
    
  • |     otherwise: upload/sync full project
    
  • |-- write unit files, daemon-reload
    
  • |-- remove stale unit files (full deploy: all removed services;
    
  • |     partial deploy: only replica/mode changes for targeted services)
    
  • |-- detect config changes (unit files + proxy container)
    
  • |-- systemctl start <all units>
    
  • |-- apply changed services (slot, rolling, or restart in place)
    
  • '-- verify: systemctl is-active <each unit>
    
  • if install/restart fails and a previous release exists,
  • qqd auto-rolls back to the last successful release.
  • hooks: pre_deploy and post_deploy run at deployment boundaries

build

qqd build -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--force-unlock] [services...]

build/pull images only, no deploy/restart

  • build/pull images without restarting any services
  • pipeline:
  • SSH to target
  • |-- git fetch + reset (sync source)
    
  • |-- mkdir -p <dirs>
    
  • |-- for each service:
    
  • |     image exists --> skip
    
  • |     has dockerfile --> build
    
  • |     no dockerfile  --> pull
    
  • '-- print summary of built/pulled images
    
  • no unit files are written, no services are restarted

update

qqd update -c <config> [-c <overlay>...] [-t <target>] [--rebuild] [--approve] [service[=version]...]

bump/set image version(s) and redeploy updated services

  • with no services: auto-bumps all buildable services (those with a dockerfile)
  • with services: bumps or sets versions for the listed services
  • pipeline:
  • LOCAL: read config file
  • |-- for each service to update:
    
  • |     auto-bump: increment rightmost number (1.44 -> 1.45, 0.1-b7 -> 0.1-b8)
    
  • |     explicit:  set to provided version (server=2.0)
    
  • |-- rewrite image tags in config file in-place
    
  • '-- print updated versions
    
  • then run DEPLOY for the updated services only:
  • SSH to target
    
  •   |-- git fetch + reset
    
  •   |-- build/pull new image versions (old versions still exist, new ones don't)
    
  •   |-- write unit files, daemon-reload
    
  •   |-- restart updated services
    
  •   |-- verify
    
  •   '-- on failure: auto-rollback to previous release (if available)
    

status

qqd status -c <config> [-c <overlay>...] [-t <target>] [--output json]

show service state/image/uptime on target(s)

  • check connectivity and print service status for each target
  • use --output json for machine-readable JSON output
  • output format: image (YYYY-MM-DD HH:MM:SS UTC, up Xh Ym)
  • pipeline:
  • SSH to target
  • |-- ls <unit directory> (connectivity check + slot detection)
    
  • '-- batched query for all services:
    
  •       |-- systemctl is-active <unit>
    
  •       '-- <runtime> inspect <container> (image name, creation time)
    

logs

qqd logs -c <config> [-c <overlay>...] [-t <target>] [services...]

stream container logs

  • stream last 200 lines and follow new output
  • without service args, streams all services
  • replicated services stream all replicas
  • multiple containers are prefixed with the container name
  • pipeline:
  • SSH to target
  • '-- <runtime> logs --tail 200 -f <container> (per container, in parallel)
    

rollback

qqd rollback -c <config> [-c <overlay>...] [-t <target>] [--force-unlock] [service]

restore previous release (or rollback single service)

  • rolls back to the previous release on the target
  • with a service name, rolls back only that service
  • without a service name, rolls back all services to the previous release
  • the previous release's images are pulled if not already on the target
  • the rollback is saved as a new release in the history
  • note: deploy and update auto-rollback on failure when a previous
  • release exists. this command is for manual rollback.

history

qqd history -c <config> [-c <overlay>...] [-t <target>]

show deployment release history on target(s)

  • lists recent releases stored on each target
  • shows release ID, timestamp, and service images
  • the most recent release is marked with →

stop

qqd stop -c <config> [-c <overlay>...] [-t <target>] [services...]

stop service units

  • stop selected or all service units (preserves unit files and images)
  • pipeline:
  • SSH to target
  • '-- systemctl stop <service units>
    

start

qqd start -c <config> [-c <overlay>...] [-t <target>] [services...]

start service units

  • start previously stopped service units
  • pipeline:
  • SSH to target
  • |-- systemctl start <network unit>
    
  • '-- systemctl start <service units>
    

destroy

qqd destroy -c <config> [-c <overlay>...] [-t <target>] [--force-unlock]

stop/disable units and remove generated unit files

  • fully remove project from target (images are NOT removed)
  • pipeline:
  • SSH to target
  • |-- stop all units (systemctl stop, tolerates missing)
    
  • |-- disable all units (systemctl disable)
    
  • |-- remove unit files
    
  • |-- clean up proxy config (~/.config/qqd/<project>/)
    
  • '-- reload systemd daemon
    

clean

qqd clean -c <config> [-c <overlay>...] [-t <target>]

remove project containers and unused images from targets

  • removes stopped containers and stale images associated with the project
  • pipeline:
  • SSH to target
  • |-- list and remove containers matching <project>-*
    
  • |-- list and remove images matching <project>-*
    
  • '-- prune dangling (<none>) images
    

doctor

qqd doctor -c <config> [-c <overlay>...] [-t <target>]

check target environment for common problems

  • runs diagnostic checks on deployment targets
  • checks:
    • SSH connectivity
    • Podman availability
    • systemd session
    • unit directory exists
    • disk space
    • user lingering (Podman only)

validate

qqd validate -c <config> [-c <overlay>...]

check config for errors without deploying

  • validates the configuration file for common errors
  • checks:
    • service references in depends_on
    • circular dependency detection
    • port range validation
    • TLS configuration completeness
    • health check port inference
    • build strategy requirements
    • mutable image tag warnings

convert

qqd convert -c <input> [-o <output>] [--format yaml|json|hocon]

convert config between formats (yaml, json, hocon)

  • reads a qqd config file and outputs it in a different format
  • format is auto-detected from output file extension, or set with --format
  • without -o, prints to stdout

migrate

qqd migrate -c <config> --from <source> [--to podman] [--stack <name>] [--dry-run] [--yes]

migrate a running Compose or Swarm stack to Podman-backed qqd

  • --from compose stop docker-compose stack, deploy with qqd
  • --from swarm stop docker swarm stack, leave swarm, deploy with qqd
  • --to is optional and must be podman (the only supported runtime)
  • --stack sets the compose/swarm stack name (defaults to project name)
  • --dry-run prints every destructive action without executing it. recommended
  •       for the FIRST run on any production-like target.
    
  • --yes (or -y) skips the destructive-action confirmation prompt. only use
  •       when you have already validated the migration with --dry-run.
    
  • images are transferred from Docker to Podman automatically
  • volume ownership is fixed when migrating to rootless podman
  • safety notes:
    • swarm migration runs docker swarm leave --force. if this node is part
  • of a multi-node swarm, the entire swarm is affected, not just this stack.
    
    • migrating to podman runs sudo chown -R on every service volume host path.
  • if other workloads use the same paths, they will be affected too.
    
    • docker network prune -f is invoked, which removes ALL unused networks
  • on the host, not just those in your project.
    
  • examples:
  • qqd migrate -c app.yaml --from compose --stack my-stack --dry-run
  • qqd migrate -c app.yaml --from swarm --stack my-stack --to podman --yes

import

qqd import -f <docker-compose.yaml> [--env <.env>] [--format yaml|json|hocon] [--host <host>] [--user <user>] [--ssh-key <key>] [-o <output>]

generate qqd config from a docker-compose.yaml

  • parses a docker-compose.yaml and generates a qqd config file
  • supports: services, images, build contexts, volumes, environment, ports, depends_on, commands
  • env vars from --env file are expanded (${VAR:-default} syntax)
  • output format is auto-detected from extension, or set with --format (yaml, json, hocon)
  • after generating, review the config and deploy:
  • qqd import -f docker-compose.yaml --host 192.0.2.10 --user ec2-user -o app.yaml
  • qqd deploy -c app.yaml

man

qqd man

open installed manual page (same as man qqd)

  • opens the qqd manual page with your local man command

docs

qqd docs [config] [--format markdown] [-o <path>]

generate CLI or configuration documentation

  • without arguments: prints CLI command reference
  • with 'config': prints full configuration reference (all fields, types, defaults)
  • default format is markdown
  • by default output is stdout; use -o to write a file

manifest

qqd manifest [--format json|md] [-o <path>]

emit the full qqd surface (commands, flags, config schema, pitfalls) for AI agents and tooling

  • prints a single structured document covering every command, flag,
  • config field, output format, lifecycle backend, and known pitfall.
  • the JSON shape is stable across patch releases — use it as the
  • entry point for any agent that drives qqd.
  • primary sources:
    • commands <- commandSpecs() in this file
    • common flags <- commonFlagRegistry() in manifest.go
    • config <- reflection over qqd:-tagged structs in types.go
    • guidance <- curated registries in manifest.go
  • prefer this over qqd docs when consuming programmatically.