Skip to content

Just Command Runner Guide

Validibot uses Just as its command runner for managing local development and deployments across multiple platforms. Just is similar to Make but with a cleaner syntax, better error messages, and modern features like modules and imports.

Why Just?

We chose Just over alternatives (Make, shell scripts, Python scripts) because:

  • Simplicity: Clean, readable syntax without Make's arcane rules
  • Modules: Native support for organizing commands by platform/concern
  • Cross-platform: Works on macOS, Linux, and Windows
  • No dependencies: Single binary with no runtime requirements
  • Tab completion: Built-in shell completion for discoverability
  • Dry-run mode: Preview commands before executing them

Installation

# macOS
brew install just

# Linux (via Homebrew)
brew install just

# Linux (via cargo)
cargo install just

# Enable tab completion (add to ~/.zshrc or ~/.bashrc)
eval "$(just --completions zsh)"  # or bash/fish

File Structure

Our justfile setup uses a modular architecture to support multiple deployment platforms:

justfile              # Root orchestrator
just/
├── common.just       # Shared variables and helpers
├── local/
│   └── mod.just      # Community-only local dev (just local ...)
├── local-pro/
│   └── mod.just      # Community + validibot-pro local dev
├── local-cloud/
│   └── mod.just      # Community + pro + cloud local dev
├── gcp/
│   ├── mod.just      # Google Cloud Platform deployment
│   ├── django/
│   │   └── mod.just  # Django-only GCP ops (just gcp django ...)
│   └── mcp/          # (re-exposure of ../mcp so "just gcp mcp ..." works)
├── mcp/
│   └── mod.just      # MCP server build/deploy/secrets/logs/test
├── aws/
│   └── mod.just      # AWS deployment (stub - not implemented)
└── docker-compose/
    └── mod.just      # Docker Compose production deployment

Root Justfile

The root justfile serves as the orchestrator. It:

  • Sets global configuration (shell, dotenv settings)
  • Imports shared helpers (merged into root namespace)
  • Declares modules for each deployment target (namespaced)

Modules and submodules

Every platform-specific group of commands is a module. Deployment targets with multiple sub-areas (like GCP, which hosts the Django web service plus optionally the MCP server plus per-service secret management) use submodules for clean grouping:

just gcp deploy-all prod        # Umbrella: web + worker + scheduler + MCP
just gcp secrets prod           # Umbrella: pushes .django AND .mcp
just gcp django secrets prod    # Surgical: only .django → django-env
just gcp mcp deploy prod        # Surgical: only rebuild/redeploy MCP

The same mcp module is also mounted at the top level so just mcp ... works as an alias for just gcp mcp ... — useful for target-agnostic commands like just mcp test (local pytest).

Imports vs Modules

Two mechanisms for organizing recipes:

Feature Imports Modules
Syntax import 'path.just' mod name 'path'
Access Direct: just recipe Namespaced: just module recipe
Use case Shared helpers Platform-specific commands

Currently only just/common.just is imported at the root. All user- facing command groups (local, local-pro, local-cloud, gcp, mcp, docker-compose, aws) are modules so the target is explicit in every invocation.

Quick Reference

Local Development

These commands are imported directly (no prefix needed):

# Container lifecycle
just local up              # Start all local containers
just local down            # Stop containers
just local build           # Rebuild and restart
just local logs            # Follow all container logs
just local ps              # Show container status
just local restart         # Stop then start
just local clean           # Stop and remove volumes (deletes data!)

# Django commands
just local shell           # Bash shell in Django container
just local migrate         # Run database migrations
just local manage "cmd"    # Run any manage.py command

# Testing
just local test            # Run tests locally
just local test -k "name"  # Run specific tests
just local test-integration # Run integration tests with Docker

Google Cloud Platform

GCP commands require environment variables for your project configuration. Before running any just gcp command:

# Option 1: Source your config file (recommended)
source .envs/.production/.google-cloud/.just

# Option 2: Set variables manually
export GCP_PROJECT_ID="your-project-id"
export GCP_REGION="us-central1"

Copy .envs.example/.production/.google-cloud/.just to .envs/.production/.google-cloud/.just and fill in your values. This file is gitignored so your project details stay private.

Commands are prefixed with gcp:

# List all GCP commands
just --list gcp

# Deployment (web + worker)
just gcp deploy prod         # Hotfix path: web only
just gcp deploy-worker prod  # Hotfix path: worker only
just gcp deploy-all prod     # Full: web + worker + scheduler + MCP (if enabled)

# Operations
just gcp logs prod           # View logs
just gcp logs-follow prod    # Stream logs
just gcp status prod         # Check service status
just gcp status-all          # Status of all stages
just gcp open prod           # Open in browser

# Database & Django
just gcp migrate prod                  # Run migrations
just gcp setup-data prod               # Initialize data
just gcp management-cmd prod "shell"   # Run any command via a temp Cloud Run Job

# Secrets — umbrella and surgical paths
just gcp secrets prod                  # Umbrella: .django AND .mcp (when MCP enabled)
just gcp django secrets prod           # Surgical: only .django → django-env
just gcp mcp secrets prod              # Surgical: only .mcp → mcp-env

# Infrastructure
just gcp init-stage dev                # Create web/worker SAs + Cloud SQL, etc.
just gcp scheduler-setup dev           # Create scheduled jobs
just gcp lb-setup prod "example.com"   # Set up HTTPS load balancer

# Maintenance
just gcp maintenance-on dev            # Put in maintenance mode
just gcp maintenance-off dev           # Resume from maintenance

MCP server commands

When the deployment runs the MCP server (ENABLE_MCP_SERVER=true in the stage's .build file), it has its own Cloud Run service and lifecycle. The commands are submodule-scoped under gcp mcp:

just gcp mcp setup prod      # First-time: create MCP SA + IAM bindings
just gcp mcp build           # Build + push MCP image to Artifact Registry
just gcp mcp deploy prod     # Deploy MCP image to Cloud Run
just gcp mcp secrets prod    # Upload .mcp → mcp-env Secret Manager secret
just gcp mcp lb-add prod mcp.yourdomain.com  # Wire MCP into the LB
just gcp mcp logs prod       # Tail MCP service logs
just gcp mcp status prod     # MCP service URL + revision info
just gcp mcp test            # Run MCP pytest suite locally (no GCP calls)

Same module is also reachable as just mcp ... at the top level; just mcp test and just mcp test-e2e are the natural entry points for local test runs.

Docker Compose

Commands are prefixed with docker-compose:

# List all docker-compose commands
just --list docker-compose

# Deployment
just docker-compose bootstrap    # First-time self-host install
just docker-compose deploy       # Build and start all services
just docker-compose update       # Full update with backup

# Operations
just docker-compose status       # Check container status
just docker-compose logs         # Follow logs
just docker-compose health-check # Verify services are running

# Database
just docker-compose migrate              # Run migrations
just docker-compose backup-db            # Create database backup
just docker-compose restore-db file.gz   # Restore from backup

# Maintenance
just docker-compose maintenance-on       # Enter maintenance mode
just docker-compose maintenance-off      # Exit maintenance mode

AWS (Stub)

AWS support is planned but not yet implemented. Commands show helpful guidance:

just aws deploy prod    # Shows implementation guidance

Stages

All platforms support three deployment stages:

Stage Purpose Resource Naming
dev Development and testing *-dev suffix
staging Pre-production testing *-staging suffix
prod Production No suffix

Example resource names:

  • Dev: $GCP_APP_NAME-web-dev, $GCP_APP_NAME-db-dev
  • Prod: $GCP_APP_NAME-web, $GCP_APP_NAME-db

Common Patterns

Deploying Updates

# GCP: full-stack deploy (web + worker + scheduler + MCP when enabled)
just gcp deploy-all dev
just gcp verify-deployment-quick dev

# After testing on dev, promote to prod
just gcp deploy-all prod

# Hotfix path: web-only deploy, skips worker and MCP
just gcp deploy prod

# Docker Compose: Single command update
just docker-compose update

Migrations run automatically as part of deploy-all and deploy (gated by GCP_SKIP_MIGRATE=1 for hotfixes with no schema changes).

Viewing Logs

# GCP: Last 50 log entries
just gcp logs prod

# GCP: Stream logs in real-time
just gcp logs-follow prod

# Docker Compose: Follow container logs
just docker-compose logs

Running Django Commands

# Local development
just local manage "createsuperuser"
just local manage "shell_plus"

# GCP (creates temporary Cloud Run Job)
just gcp management-cmd prod "createsuperuser"

# Docker Compose
just docker-compose manage "createsuperuser"

Checking Status

# GCP: All stages at once
just gcp status-all

# GCP: Specific stage
just gcp status dev

# Docker Compose
just docker-compose health-check

Tips & Tricks

Preview Commands

See what a command will do without executing:

just --show gcp deploy
just --dry-run gcp deploy prod

List All Commands

just --list              # Root commands
just --list gcp          # GCP commands
just --list docker-compose   # Docker Compose commands

Run from Anywhere

Just automatically finds the justfile in parent directories:

cd validibot/core/
just local up  # Still works!

Environment Variables

Commands that need environment variables:

# GCP: Connect to Cloud SQL
DATABASE_PASSWORD='secret' just gcp local-to-gcp-shell dev

# Testing: E2E tests
E2E_TEST_API_URL=https://... just gcp test-e2e

Adding a New Platform

To add support for a new cloud platform:

  1. Create just/<platform>/mod.just
  2. Add mod <platform> 'just/<platform>' to root justfile
  3. Follow the structure of just/gcp/mod.just
  4. Implement the core commands: deploy, migrate, logs, status

See just/aws/mod.just for a template with detailed implementation notes.

Migrating from Old Commands

If you have scripts or muscle memory from the old flat justfile:

Old Command New Command
just gcp-deploy dev just gcp deploy dev
just gcp-logs prod just gcp logs prod
just gcp-status-all just gcp status-all
just gcp-migrate dev just gcp migrate dev
just gcp-secrets prod just gcp secrets prod

The new structure uses a space instead of a hyphen after the platform name.

Troubleshooting

"Module not found" Error

Ensure you're running Just version 1.31.0 or later:

just --version

"Recipe not found" Error

Check that you're using the correct prefix:

# Wrong: deployment commands need platform prefix
just deploy prod

# Correct: use the platform prefix
just gcp deploy prod

Tab Completion Not Working

Ensure you've added the completion to your shell profile:

# Add to ~/.zshrc
eval "$(just --completions zsh)"

# Then reload
source ~/.zshrc