Skip to content

Hop3 Cheat Sheet

A quick reference for Hop3 users.

Mental Model

Hop3 is a single-server PaaS (Platform as a Service). Think of it as:

Your Code  →  hop3 deploy  →  Running App on Your Server

Key concepts:

  1. Apps are deployable units. Each app has a name, source code, config, and runtime.
  2. Configuration comes from three layers (lowest to highest priority):
  3. Defaults (provided by Hop3)
  4. Procfile (convention, Heroku-compatible)
  5. hop3.toml (full configuration)
  6. Addons are backing services (databases, caches) that attach to apps.
  7. Environment variables configure runtime behavior.
  8. The CLI talks to the server via JSON-RPC; most commands run remotely.

Quick Reference: Commands

Setup & Authentication

# First time: initialize connection and create admin
hop3 init --ssh root@hop3.example.com

# Log in to existing server
hop3 login --ssh root@hop3.example.com

# Check who you're logged in as
hop3 auth whoami

# Get version
hop3 version

Context Management (Multiple Servers)

# Add server contexts
hop3 context add staging --server ssh://root@staging.example.com
hop3 context add production --server ssh://root@prod.example.com --protected

# List contexts (* = current)
hop3 context list

# Show current context and source
hop3 context current

# Switch context (safe - prints export command)
hop3 context use production
# Output: export HOP3_CONTEXT=production

# Switch context for this project (run from inside the project tree;
# writes .hop3-local.toml, auto-gitignored — ADR 042)
cd myproject/
hop3 context use staging

# Switch context globally (affects all terminals - use with caution!)
hop3 context use production --global

# Use context for single command
hop3 --context production apps

# Remove context
hop3 context remove old-staging

Context priority (highest to lowest): 1. --context flag 2. HOP3_CONTEXT environment variable 3. .hop3-local.toml [current].context (per project checkout, ADR 042) 4. Global config

Application Lifecycle

# Create app from git repository
hop3 app launch <git-url> <app-name>

# Deploy (from project directory)
hop3 deploy <app-name>

# Deploy from a specific directory
hop3 deploy <app-name> /path/to/app

# Check status
hop3 app status <app>

# View logs (streaming)
hop3 app logs <app>

# Build logs
hop3 app build-logs <app>

# Start / Stop / Restart
hop3 app start <app>
hop3 app stop <app>
hop3 app restart <app>

# List all apps
hop3 apps

# Destroy app (requires confirmation)
hop3 app destroy <app>

# Scriptable destroy — no prompt, still safe
hop3 app destroy oldapp --confirm=oldapp

Sticky App (implicit --app)

Most app-scoped commands don't need --app if one is resolvable from the current shell or directory.

# Bind an app to the current context
hop3 use myapp
hop3 app logs          # no positional needed
hop3 app restart
hop3 config show

# Or set for a single shell
export HOP3_APP=myapp

# Or drop a .hop3-app file in your project
echo myapp > .hop3-app

# Debug the chain
hop3 --why logs

Resolution order: --app$HOP3_APP.hop3-apphop3.toml [cli].app → context default. See CLI Reference: App Resolution.

Configuration / Environment

# View all env vars
hop3 config show <app>

# Get single var
hop3 config get <app> VAR_NAME

# Set vars (one or multiple)
hop3 config set <app> VAR1=value1 VAR2=value2

# Remove var
hop3 config unset <app> VAR_NAME

# Live runtime config
hop3 config live <app>

# Migrate Procfile to hop3.toml
hop3 config migrate procfile /path/to/app --dry-run

Addons (Backing Services)

hop3 addons                           # List addons (alias for `addon list`)
hop3 addon create postgres my-db     # Create addon
hop3 addon attach my-db --app <app>  # Attach (sets DATABASE_URL)
hop3 addon detach my-db --app <app>  # Detach from app
hop3 addon show my-db                # Addon info
hop3 addon destroy my-db             # Destroy addon

See CLI Reference: Services for complete documentation.

Backups

hop3 backup create <app>           # Create backup
hop3 backup list <app>             # List backups
hop3 backup info <backup-id>       # Backup details
hop3 backup restore <backup-id>    # Restore
hop3 app restart <app>             # Restart after restore
hop3 backup destroy <backup-id>     # Delete backup

See Backup and Restore Guide for complete documentation.

Process Scaling

# View processes
hop3 ps <app>

# Scale (web=2, worker=1)
hop3 ps scale <app> web=2 worker=1

System & Admin

# System info
hop3 system info
hop3 system status
hop3 system uptime

# List all server processes
hop3 system ps

# Server logs
hop3 system logs

# User management (admin only)
hop3 user list
hop3 user add <username> <email> --password-file ./pw.txt
hop3 user set-password <username> --stdin   # pipe new password in
hop3 user disable <username>
hop3 user enable <username>
hop3 user grant-admin <username>
hop3 user remove <username> --confirm=<username>

Help

# General help
hop3 help

# All commands
hop3 help --all

# Help for specific command
hop3 <command> --help

CLI Flags

Flag Effect
--json JSON output (for scripting; includes error.exit_code)
--quiet / -q Suppress non-essential output
--verbose / -v More detail (stackable: -vv = debug)
-y / --yes / --force Skip confirmations
--confirm=<name> Scriptable typed-name confirmation (safer than --yes)
--no-input Refuse to prompt; fail fast with a hint
--context <name> / -c Use a specific server context
--app <name> / -a Override the resolved app
--why Print app/context/alias resolution trace to stderr
--no-alias Bypass the alias table (run the typed command literally)
--help / -h Show help

Exit codes (ADR 036 D16)

Code Meaning
0 Success
1 Generic error
2 Usage / syntax error
3 Resolution error (app / context not found)
4 Authentication
5 Authorization
6 Conflict (already exists)
7 Network / server error
8 Deployment failure
9 Plugin error
10 Confirmation declined or non-tty blocked
130 Interrupted (SIGINT)

Scripting examples

# Get app state in JSON (with structured exit-code on error)
hop3 app status myapp --json | jq '.data.state'

# Safer scripted destroy: typed-name match + still runs safety checks
hop3 app destroy myapp --confirm=myapp

# CI: refuse to block on prompts — fail fast with instructions
hop3 user add alice alice@ex.com --password-file ./pw --no-input

# Distinguish "user declined" from other failures
hop3 app destroy myapp
case $? in
  0)  echo "destroyed" ;;
  10) echo "declined or non-tty" ;;
  3)  echo "no such app" ;;
  *)  echo "other error" ;;
esac

Helpful diagnostics

# Why did the CLI pick that app / context?
hop3 --why logs

# What aliases are active?
hop3 aliases

# What commands were meant? (Levenshtein suggestion)
hop3 deplo myapp   # -> "Did you mean 'deploy'?"

Configuration Files

Procfile (Simple / Heroku-compatible)

Location: Procfile in project root.

web: gunicorn app:app --workers 4
worker: celery -A myapp worker
prebuild: pip install -r requirements.txt
prerun: python manage.py migrate
Key Purpose
web Main process (receives HTTP traffic)
worker Background worker
prebuild Runs before build
prerun Runs before start

hop3.toml (Full Configuration)

Location: hop3.toml in project root (or src/hop3.toml).

[metadata]
id = "myapp"
version = "1.0.0"
title = "My Application"

[build]
before-build = "pip install -r requirements.txt"
build = "npm run build"
test = "pytest"
packages = ["nodejs", "gcc"]

[run]
start = "gunicorn app:app --workers 4"
before-run = "python manage.py migrate"
packages = ["postgresql-client"]

[env]
LOG_LEVEL = "info"

[port]
web = 8000

[healthcheck]
path = "/health/"
timeout = 30
interval = 60

[backup]
enabled = true
schedule = "0 2 * * *"
retention = 7

[[provider]]
name = "postgres"
plan = "standard"

Key Sections

Section Purpose
[metadata] App ID, version, title, author
[build] Build commands, packages
[run] Start command, runtime setup
[env] Default environment variables
[port] Port mappings
[healthcheck] Health monitoring
[backup] Automated backup config
[[provider]] Required services (postgres, redis)

See hop3.toml Reference for complete documentation.

Precedence

  1. hop3.toml values override Procfile
  2. Non-conflicting values are merged
  3. You can use both together

Common Workflows

Deploy a New App

# 1. Create project with hop3.toml or Procfile
cd myapp

# 2. Initialize hop3 (first time)
hop3 init --ssh root@hop3.example.com

# 3. Deploy (app-name is required)
hop3 deploy myapp

# 4. Check status
hop3 app status myapp

Update an Existing App

# 1. Make code changes
# 2. (Optional) Create backup first
hop3 backup create myapp

# 3. Deploy
hop3 deploy myapp

# 4. If something breaks, restore
hop3 backup restore <backup-id>
hop3 app restart myapp

Add a Database

# 1. Create the addon
hop3 addon create postgres myapp-db

# 2. Attach to app (sets DATABASE_URL)
hop3 addon attach myapp-db --app myapp

# 3. Restart to pick up new env var
hop3 app restart myapp

Debug a Problem

# Check app status
hop3 app status myapp

# View logs
hop3 app logs myapp

# Build logs
hop3 app build-logs myapp

# Full debug info
hop3 app debug myapp

# Check environment
hop3 config show myapp

Scale for Traffic

# Scale web workers
hop3 ps scale myapp web=4

# Add background workers
hop3 ps scale myapp worker=2

Best Practices

Configuration

  • Don't hardcode secrets in hop3.toml or Procfile
  • For app-internal random secrets (SECRET_KEY, APP_KEY, …), declare KEY = { generate = "hex", length = 32 } in [env] — generated once on first deploy, persisted, never committed
  • Use hop3 config set for externally-supplied secrets (API keys, passwords)
  • Keep hop3.toml in version control (without secrets)
  • Use [env] for non-sensitive defaults only

Deployment

  • Back up before deploying to production: hop3 backup create <app>
  • Test locally first when possible
  • Use --dry-run when available
  • Check logs after deploy: hop3 app logs <app>

Backups

  • Back up before deploying to production: hop3 backup create <app>
  • Enable automated backups in hop3.toml:
    [backup]
    enabled = true
    schedule = "0 2 * * *"  # Daily at 2 AM
    
  • Test restore procedures periodically
  • See Backup and Restore Guide for retention policies

Environment Variables

  • Restart after changing config: hop3 app restart <app>
  • Use consistent naming: DATABASE_URL, REDIS_URL, SECRET_KEY
  • Keep production and development configs separate

Working with Multiple Servers

  • Mark production as protected: hop3 context add production --server ... --protected
  • Use environment variable for safety: export HOP3_CONTEXT=staging in your shell
  • Per-project contexts (ADR 042): cd into the project tree and run hop3 context use <name> — the project-scoped verb writes .hop3-local.toml and adds it to .gitignore automatically. The legacy --local flag was retired in Step 7.
  • Avoid global context switches: Don't use --global for production contexts
  • Create shell aliases:
    alias hop3-prod='HOP3_CONTEXT=production hop3'
    alias hop3-staging='HOP3_CONTEXT=staging hop3'
    

Process Management

  • Start with web=1, scale as needed
  • Monitor with hop3 app logs and hop3 app status
  • Use health checks to catch failures early

Quick Heroku → Hop3 Translation

Heroku Hop3
heroku create hop3 app launch <repo> <name>
git push heroku main hop3 deploy
heroku config set hop3 config set
heroku addon create heroku-postgresql hop3 addon create postgres
heroku logs -t hop3 app logs
heroku ps hop3 ps
heroku restart hop3 app restart
heroku destroy hop3 app destroy

Getting Help

hop3 help              # General help
hop3 help --all        # All commands
hop3 <command> --help  # Help for specific command