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:
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:
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:
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:
- Create
just/<platform>/mod.just - Add
mod <platform> 'just/<platform>'to root justfile - Follow the structure of
just/gcp/mod.just - 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:
"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: