Skip to content

CLI Reference

Griffen Fargo edited this page Aug 1, 2026 · 22 revisions

CLI Reference

Complete reference for every strut command, flag, and subcommand. Each command supports --help for inline usage (e.g. strut my-stack backup --help).

strut <stack> <command> [--env <env>] [options]

Global Flags

Flag Description
--env <name> Environment name (reads .<name>.env)
--services <profile> Service profile: messaging, ui, full
--json JSON output (where supported)
--dry-run Preview destructive operations without executing
--force-clean Allow git clean to delete untracked VPS files (bypass data-loss guard)
--confirm-data-move Proceed even when volume-defining vars changed (data may be lost)
--no-tui Disable the interactive TUI (since v0.19.0)
STRUT_NO_TUI=1 Env-var equivalent of --no-tui (since v0.19.0)
STRUT_PROJECT Override project root detection (env var)
STRUT_NO_UPDATE_CHECK=1 Suppress the version update nag (env var)

Top-Level Commands

These don't require a stack name:

Command Description
strut Interactive TUI picker (stack → command → env) when stdin is a tty (since v0.19.0)
strut --print Same as strut but prints the resolved command instead of running it (since v0.19.0)
strut init [--registry <type>] [--org <name>] Initialize a new project with strut.conf
strut list List all available stacks
strut list plugins [--json] List discovered project plugins (since v0.17.0)
strut help <plugin> Show a project plugin's help text (since v0.17.0)
strut scaffold <name> [--recipe <recipe>] Create a new stack from templates (optionally from a recipe, since v0.18.0)
strut scaffold list [--json] List available scaffold recipes (since v0.18.0)
strut sync [<host>|--all] [--env <name>] [--dry-run] [--force-clean] Sync VPS checkout with origin (fetch + reset). Resolves hosts via topology alias or env files. (since v0.29.0)
strut fleet status [--json] Git sync state (branch, ahead/behind, dirty, HEAD sha) across every [hosts] in topology (since v0.31.0)
strut webhook poll [--interval <sec>] [--branch <name>] [--stack <name>] [--once] Poll origin, auto-deploy stacks affected by new commits (since v0.32.0)
strut webhook serve [--port <N>] [--secret <hmac>] [--branch <name>] HTTP receiver for GitHub/GitLab push events (HMAC-verified) (since v0.32.0)
strut webhook install [--mode poll|serve] [--interval <sec>] [--port <N>] Generate a systemd unit for persistent webhook operation (since v0.32.0)
strut mcp serve Start the MCP server on stdio for AI agent integration (since v0.33.0)
strut mcp install [--host <editor>] Write MCP config for your editor (via agent-add, or Kiro-only jq fallback) (since v0.33.0)
strut upgrade Upgrade strut to latest version
strut --version Show installed version
strut skills [list|install] [--format <fmt>] AI agent context management
strut audit <host> [user] [key] [port] Audit a VPS
strut audit:list List past audits
strut audit:diff <host> [user] [key] [port] Audit a host and diff against its most recent stored audit (since v0.24.0)
strut audit:generate <name> --from <dir> Generate stack from audit
strut migrate <host> [user] [port] [key] [--yes] Run migration wizard
strut migrate:status Show migration status
strut monitoring <subcommand> Monitoring stack management
strut doctor [--check-vps] [--deep] [--json] [--fix] Diagnostic environment check (--deep runs a full preflight against every configured VPS — Docker, disk, memory, ports, sudo)
strut status-all [--env <name>] [--json] Dashboard showing every stack at once (since v0.11.0)
strut posture [--stack <name>] [--category <c>] [--fail-on <lvl>] [--json] Security/ops posture check (since v0.11.0)
strut group list|show|add|remove|<name> <cmd> Stack group dispatcher (since v0.15.0)
strut notify test <slack|discord|webhook> Send test notification (since v0.9.0)
strut completions <bash|zsh|fish> Print shell completion script (since v0.17.0)
strut init --completions Auto-install completions for current shell (since v0.17.0)

Per-Stack Commands

All require: strut <stack> <command> [--env <name>]

Deployment

Command Description
release [...] Alias for deploy --require-remote, kept for existing scripts
deploy [--services <profile>] [--pull-only] [--skip-validation] [--skip-health-gate] [--force-unlock] [--no-lock] [--blue-green|--standard] [--force-local] Deploy stack containers (concurrency-locked since v0.13.0; blue-green since v0.20.0; health-gated since v0.42.0)
rebuild [--no-cache] [--pull] Build images on target + deploy (since v0.22.0)
ship [--message <msg>] [-m <msg>] [--no-commit] [--no-push] [--no-cache] Commit, push, and rebuild on remote in one step (since v0.22.0)
stop [--volumes] [--timeout N] Stop running containers
update Pull latest strut code on VPS (no container restart)
diff [--json] Preview pending env/image changes vs VPS (since v0.13.0)
lock <status|release> [--force] [--remote|--local] Inspect/manage deploy concurrency locks (since v0.13.0)

Monitoring & Status

Command Description
health [--json] Run health checks against services.conf
briefing [--json] One-call situation report: aggregates health, drift, image staleness, pending diff, and backup health into an overall posture (ok/warn/critical) plus prioritized actions. Exit code reflects posture (since v0.41.0)
preflight [--json] Deploy go/no-go verdict (GO/CAUTION/NO-GO) fusing pending diff, config drift, current health, and backup freshness, with reasons. Exits 0/1/2 (since v0.41.0)
logs [service] [--follow] [--since <dur>] View service logs
logs:download [service] [--since <dur>] Download logs to local filesystem (since v0.23.0)
logs:rotate Rotate log files on VPS (since v0.23.0)
status Show container status

Database Operations

Command Description
backup [postgres|neo4j|mysql|sqlite|all] Create backups
backup offsite <status|sync|list|restore <file>> Offsite backup sync to S3/R2/B2 (since v0.16.0)
restore <file> [--dry-run] [--target-env <env>] Restore from backup file. --dry-run (Postgres only, since v0.31.0) rehearses into a scratch DB, diffs row counts vs live, then drops it — never touches the live database
db:pull [type] [--download-only] [--file <name>] Pull backup from VPS, restore locally
db:push [type] [--upload-only] [--file <name>] Push local backup to VPS, restore remotely
db:schema [apply|verify|all] Apply or verify Postgres schema SQL
migrate [neo4j|postgres] [--status|--up|--down N] Run database migrations

Configuration Management

Command Description
validate Validate all config files against expected schemas
drift [detect|report|fix|auto-fix|history|images] Configuration drift detection. images [--json] (since v0.31.0) flags containers whose running image digest no longer matches what their tag currently resolves to on the registry
keys <subcommand> Key management (SSH, API, env, db, GitHub)
secrets push|pull|diff|validate Sync .env files to/from VPS (since v0.26.0)
secrets hydrate Resolve vault/exec/file references in .env.template → .env (since v0.27.0)
secrets status Show full secrets pipeline state for the stack (since v0.27.0)
secrets rotate [--restart] Re-hydrate → validate → push → optional container restart (since v0.27.0)
secrets template [--force] Reverse-engineer .env.template from existing .env (since v0.27.0)
secrets export --format <fmt> Export .env as docker-secret, k8s-secret, or env-json (since v0.27.0)
secrets lock [--backend age|gpg] Encrypt .env at rest (safe to commit) (since v0.27.0)
secrets unlock [--identity <file>] Decrypt .env.age/.env.gpg back to plaintext (since v0.27.0)
init-secrets [--force] [--dry-run] Generate .env from template with auto-secrets (since v0.25.0)
ssh:keygen [--name <label>] [--type <ed25519|rsa>] Generate deploy keypair + authorize on host (since v0.24.0)
ci:init [--provider <name>] [--repo <owner/repo>] [--key-name <label>] [--dry-run] [--yes] Bootstrap CI/CD secrets for the stack (since v0.27.0)
volumes [status|init|config] Volume management
domain <domain> <email> [--skip-ssl] Configure domain and SSL. Deploys also auto-provision Let's Encrypt certs when AUTO_SSL=true (default) and a domain is detected from a compose label or DOMAIN/DOMAINS/VIRTUAL_HOST (since v0.32.0) — see Domain and SSL
cert:renew [--dry-run] Renew Tailscale HTTPS certificates on a host (since v0.24.0)
cert:status Show certificate expiry dates (since v0.24.0)
rollback [--list] [--dry-run] Roll back to previous deploy snapshot (blue-green: flips active color, since v0.20.0)
rollback diff <ref_a> <ref_b> [--json] Diff images between two snapshots; refs: HEAD, HEAD~N, basename (since v0.16.0)
prune [--volumes] [--all] [--no-protect] Prune docker resources; --no-protect skips rollback-image protection (since v0.16.0)

Deploy Keys & CI Setup (since v0.27.0)

Command Description
ssh:keygen --name <name> Generate a deploy keypair and authorize the public key on the VPS host
ci:init --provider <provider> Bootstrap all CI secrets (SSH key, env vars) for the stack on the given provider (e.g. github)
ci:init --dry-run Preview which secrets would be set without writing anything

Registry Credentials (since v0.27.0)

Command Description
keys rotate-registry [--registry <url>] [--hosts <list>] Rotate Docker registry pull credentials across VPS hosts
keys registry-status [--registry <url>] [--json] Show per-host registry auth state

VPS Access

Command Description
shell SSH to VPS (interactive)
exec <command> Execute single command on VPS
remote:init [--host <h>] [--user <u>] [--key <k>] [--repo <url>] Bootstrap strut on a remote VPS (since v0.21.0)
provision [--script <path>] [--verify] [--dry-run] Run one-time provisioning script on host (since v0.23.0)

Gateway Management (since v0.24.0)

Command Description
gateway deploy --host <alias> Deploy Caddyfile to a host and reload Caddy
gateway status --host <alias> Show Caddy service status
gateway reload --host <alias> Reload Caddy without deploying new config
gateway validate Validate local Caddyfile syntax

Certificate Management (since v0.24.0)

Command Description
cert:renew [--dry-run] Renew Tailscale HTTPS cert and reload Caddy
cert:status Show certificate subject, issuer, and expiry

Deploy Keys & CI (since v0.27.0)

Command Description
ssh:keygen [--name <label>] [--type <ed25519|rsa>] Generate deploy keypair and authorize it on the target host
ci:init [--provider <name>] [--repo <owner/repo>] [--key-name <label>] [--dry-run] [--yes] Bootstrap CI/CD secrets for the stack

ci:init options:

Flag Description
--provider <name> CI provider: github (default), gitlab, manual
--repo <owner/repo> Target repo (default: auto-detect from git remote)
--key-name <label> Deploy key name (default: ci)
--dry-run Show what secrets would be set without executing
--yes Push secrets without confirmation (requires gh/glab CLI)

Secret categories discovered:

Category Meaning
AUTO Derived from strut.conf topology (host, user, port, deploy dir)
KEY Deploy key file (from ssh:keygen)
ENV Value read from the stack's .env file or ci_secrets manifest
MANUAL Requires human input (prints instructions)

ci_secrets manifest: If stacks/<stack>/ci_secrets exists, each line names an env var to include. Otherwise ci:init uses heuristics (vars matching *API_URL*, *API_TOKEN*, etc.).

Debugging

Command Description
debug exec <service> <command> Execute command in container
debug shell <service> Open interactive shell in container
debug port-forward <service> <local>:<remote> Forward port from container
debug copy <service> <source> <dest> Copy files to/from container
debug snapshot <service> Create container snapshot
debug inspect-env <service> Show environment variables
debug stats <service> Show real-time resource usage

Local Development

Command Description
local start [--services <profile>] Start stack locally
local stop Stop local stack
local reset Reset local environment
local sync-env --from <env> Sync env vars from production
local sync-db --from <env> [target] [--anonymize] Sync database from production
local logs [--follow] Tail local logs
local test Run local smoke tests

Monitoring Commands

strut monitoring deploy                              # Deploy monitoring stack
strut monitoring add-target <stack> [env]             # Add stack to monitoring
strut monitoring remove-target <stack>                # Remove from monitoring
strut monitoring alert-channel add <type> [options]   # Configure alerts
strut monitoring alert-channel test [type]            # Test alert delivery
strut monitoring status [--json]                      # Show monitoring status

Stack Groups (since v0.15.0)

Groups are declared in groups.conf (INI-style) and run a strut command across every stack in the group.

strut group list                                           # List all groups
strut group show <name>                                    # List members of a group
strut group add <name> <stack>                             # Append a stack
strut group remove <name> <stack>                          # Remove a stack
strut group <name> <command> [--env <env>] [--stop-on-error] [--json]
strut group <name> logs [--follow] [--since <dur>] [--grep <pat>] [--service <svc>]

group <name> logs multiplexes logs across every member with a colored [stack] prefix. All other commands shell out to strut <stack> <command> per member and collect pass/fail. See Stack Groups.

Notifications (since v0.9.0)

strut notify test slack            # Send a test event to SLACK_WEBHOOK
strut notify test discord
strut notify test webhook

Providers are configured in notifications.conf at the project root. See Notifications.

Service Profiles

Profile Description
(none) Core services (default compose file)
gdrive Core + Google Drive ingestion
messaging Core + messaging service
ui Core + UI service
full All services

Examples

# Deploy to wherever the stack lives
strut my-app deploy --env prod

# Preview before deploying
strut my-app deploy --env prod --dry-run

# Deploy with all services
strut my-app deploy --env prod --services full

# Ship: commit, push, and rebuild on remote
strut my-app ship --env prod -m "fix dashboard layout"
strut my-app ship --env prod --no-commit             # skip commit, just push + rebuild

# Build images on remote (without local git flow)
strut my-app rebuild --env prod --no-cache

# Health check with JSON output
strut my-app health --env prod --json

# Follow logs for a specific service
strut my-app logs api --follow --env prod

# Backup all databases
strut my-app backup all --env prod

# Pull production database locally
strut my-app db:pull --env prod

# Check for config drift
strut my-app drift detect --env prod

# Rotate database passwords
strut my-app keys db:rotate postgres --env prod

# Configure domain with SSL
strut my-app domain api.example.com admin@example.com --env prod

# Secrets management
strut my-app init-secrets --env prod             # Generate .env from template
strut my-app secrets push --env prod             # Upload .env to VPS
strut my-app secrets pull --env prod             # Download .env from VPS
strut my-app secrets diff --env prod             # Compare local vs remote
strut my-app secrets hydrate --env prod          # Resolve vault/exec/file refs → .env
strut my-app secrets status --env prod           # Show secrets pipeline state
strut my-app secrets rotate --env prod --restart # Full rotate + container restart
strut my-app secrets template --env prod         # Reverse-engineer .env.template
strut my-app secrets export --format k8s-secret  # Export as Kubernetes Secret manifest
strut my-app secrets lock --env prod             # Encrypt .env at rest (age/gpg)
strut my-app secrets unlock --env prod           # Decrypt to plaintext for editing

# Registry credential rotation
strut my-app keys rotate-registry --registry ghcr.io
strut my-app keys registry-status --json

# Deploy keys & CI setup
strut my-app ssh:keygen --name ci                # Generate deploy keypair
strut my-app ci:init                             # Print CI secrets checklist
strut my-app ci:init --provider github --yes     # Push secrets via gh CLI
strut my-app ci:init --dry-run                   # Preview what would be set
strut my-app ci:init --repo gfargo/my-app        # Explicit repo target

# Certificate management
strut harbor cert:renew                           # Renew Tailscale cert
strut harbor cert:status                          # Check cert expiry

# Gateway management
strut gateway deploy --host harbor               # Deploy Caddyfile to host
strut gateway status --host harbor               # Check Caddy status
strut gateway validate                           # Validate local Caddyfile syntax

# Provisioning
strut harbor provision                            # Run provision script
strut harbor provision --verify                   # Verify only

# List all stacks
strut list

# Create a new stack
strut scaffold my-new-app

# Cross-stack dashboard
strut status-all --env prod
strut status-all --env prod --json

# Security/ops posture audit (CI-friendly exit codes)
strut posture
strut posture --category secrets --fail-on warn --json

# Preview deploy changes vs VPS
strut my-stack diff --env prod

# Blue-green deploy (zero-downtime swap)
strut my-stack deploy --env prod --blue-green
strut my-stack deploy --env prod --blue-green --dry-run
strut my-stack rollback --env prod                 # flips back to drained color

# Diff two rollback snapshots
strut my-stack rollback diff HEAD~1 HEAD
strut my-stack rollback diff 20260420-091500 HEAD --json

# Group operations
strut group list
strut group vps-1 deploy --env prod
strut group vps-1 logs --follow

# Deploy keys & CI setup
strut my-stack ssh:keygen --name ci              # Generate deploy keypair + authorize on host
strut my-stack ci:init --provider github         # Bootstrap all CI secrets for the stack
strut my-stack ci:init --dry-run                 # Preview what secrets would be set

# Offsite backup sync
strut my-stack backup offsite status --env prod
strut my-stack backup offsite sync --env prod
strut my-stack backup offsite list --env prod

# Non-destructive restore rehearsal (Postgres) — never touches the live DB
strut my-stack restore backups/postgres-20260701.sql --env prod --dry-run

# Fleet sync state across every configured host
strut fleet status
strut fleet status --json

# Stale image-digest detection (mutable tag moved on the registry since deploy)
strut my-stack drift images --env prod --json

# Webhook push-to-deploy
strut webhook poll --once                                    # single check, e.g. from cron
strut webhook serve --port 9876 --secret "$WEBHOOK_SECRET"   # HTTP receiver
strut webhook install --mode poll > strut-webhook.service    # generate a systemd unit

# MCP server for AI agent integration
strut mcp install --host cursor       # write MCP config for a specific editor
strut mcp install                     # interactive editor picker

Clone this wiki locally