From daily-carry
Complete guide for using OtterStack - a Git-driven Docker Compose deployment tool with zero-downtime deployments. Use when deploying Docker Compose apps, managing projects, configuring environment variables, or troubleshooting deployments. Triggers on "how to use otterstack", "otterstack commands", "deploy with otterstack", "otterstack project", "otterstack env", or questions about OtterStack usage.
npx claudepluginhub jayteealao/agent-skills --plugin daily-carryThis skill uses the workspace's default tool permissions.
Complete reference for using OtterStack - a deployment orchestration tool for Docker Compose applications with zero-downtime deployments via Traefik priority-based routing.
Verifies tests pass on completed feature branch, presents options to merge locally, create GitHub PR, keep as-is or discard; executes choice and cleans up worktree.
Guides root cause investigation for bugs, test failures, unexpected behavior, performance issues, and build failures before proposing fixes.
Writes implementation plans from specs for multi-step tasks, mapping files and breaking into TDD bite-sized steps before coding.
Complete reference for using OtterStack - a deployment orchestration tool for Docker Compose applications with zero-downtime deployments via Traefik priority-based routing.
OtterStack is a Git-driven deployment orchestrator for Docker Compose applications running on a single VPS. It provides:
go build ./cmd/otterstack
./otterstack version
Local repository:
otterstack project add myapp /srv/myapp
Remote repository:
otterstack project add myapp https://github.com/user/repo.git
With Traefik zero-downtime routing:
otterstack project add myapp https://github.com/user/repo.git --traefik-routing
Custom compose file:
otterstack project add myapp /srv/myapp --compose-file docker-compose.prod.yml
OtterStack now has smart environment variable management with auto-discovery!
Option 1: Auto-discovery during project add
# Create .env.<project-name> in current directory
echo "DATABASE_URL=postgres://localhost/mydb" > .env.myapp
echo "API_KEY=secret123" >> .env.myapp
# Add project - OtterStack will auto-discover and load the file
otterstack project add myapp /srv/myapp
# Prompts interactively for any missing variables
Option 2: Set variables manually
otterstack env set myapp DATABASE_URL=postgres://localhost/mydb
otterstack env set myapp API_KEY=secret DEBUG=false
Option 3: Load from file
otterstack env load myapp .env.production
Option 4: Interactive scan (for existing projects)
otterstack env scan myapp
# Scans compose file, prompts for missing variables
List variables:
otterstack env list myapp
otterstack env list myapp --show-values # Show actual values
Get specific variable:
otterstack env get myapp DATABASE_URL
Remove variables:
otterstack env unset myapp DEBUG
Deploy default branch:
otterstack deploy myapp
Deploy specific ref:
otterstack deploy myapp --ref feature/new-ui
otterstack deploy myapp --ref v1.2.3
otterstack deploy myapp --ref a1b2c3d4
Force deploy (skip validations - use carefully!):
otterstack deploy myapp --force
List all projects:
otterstack project list
View project details:
otterstack status myapp
Check deployment history:
otterstack deployments myapp
Remove project:
otterstack project remove myapp
Force remove (skip confirmation):
otterstack project remove myapp --force
OtterStack automatically detects variable types from names:
| Pattern | Type | Validation |
|---|---|---|
DATABASE_URL, API_ENDPOINT | URL | Must have scheme (https://) |
ADMIN_EMAIL, SUPPORT_EMAIL | Valid email format | |
HTTP_PORT, DB_PORT | Port | 1-65535 |
WORKER_COUNT, MAX_CONNECTIONS, TIMEOUT | Integer | Valid number |
DEBUG_ENABLED, FEATURE_FLAG, USE_SSL | Boolean | Yes/No dialog |
| Everything else | String | Basic validation |
When you run env scan or project add, OtterStack:
${VAR} references.env.example for documentationOtterStack parses these Docker Compose formats:
services:
web:
environment:
- DATABASE_URL=${DATABASE_URL} # Required
- API_URL=${API_URL:-https://api.example.com} # Optional with default
- SECRET_KEY=${SECRET_KEY:?Secret key required} # Required with error message
- DEBUG=$DEBUG # Simple form
services:
web:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`myapp.example.com`)"
--traefik-routing flag1. [Old Containers Serving] → Priority: 100
2. [Start New Containers] → No Traefik labels yet
3. [Health Check] → Wait up to 5 minutes
4. [Apply Priority Labels] → New: 200, Old: 100
5. [Traffic Switches] → Traefik routes to higher priority
6. [Stop Old Containers] → Deployment complete
If health checks fail at step 3, old containers keep serving traffic.
Without Traefik:
With Traefik:
# Add project
otterstack project add <name> <repo-path-or-url> [flags]
--compose-file string Path to compose file (default: docker-compose.yml)
--traefik-routing Enable zero-downtime Traefik routing
# List projects
otterstack project list
# Remove project
otterstack project remove <name> [--force]
# View project status
otterstack status <name>
# Set variables
otterstack env set <project> KEY=VALUE [KEY=VALUE...]
# Get variable
otterstack env get <project> [KEY]
# List variables
otterstack env list <project> [--show-values]
# Load from file
otterstack env load <project> <file>
# Interactive scan
otterstack env scan <project>
# Remove variables
otterstack env unset <project> KEY [KEY...]
# Deploy
otterstack deploy <project> [flags]
--ref string Git ref to deploy (commit, branch, tag)
--force Skip validation checks
# View deployment history
otterstack deployments <project>
--config string Config file (default: $HOME/.otterstack.yaml)
--data-dir string Data directory (default: $HOME/.otterstack)
--verbose Verbose output
--help Show help
--version Show version
# 1. Create .env file
cat > .env.myapp <<EOF
DATABASE_URL=postgres://user:pass@localhost/mydb
REDIS_URL=redis://localhost:6379
API_KEY=your-secret-key
EOF
# 2. Add project (auto-discovers .env.myapp)
otterstack project add myapp https://github.com/user/repo.git --traefik-routing
# 3. Verify configuration
otterstack env list myapp
# 4. Deploy
otterstack deploy myapp
# Option 1: Interactive scan
otterstack env scan myapp
# Option 2: Manual set
otterstack env set myapp NEW_VAR=value
# Option 3: Load from file
otterstack env load myapp .env.new
# Deploy feature branch
otterstack deploy myapp --ref feature/new-ui
# Check status
otterstack status myapp
# If good, merge to main and deploy
git checkout main
git merge feature/new-ui
git push
otterstack deploy myapp --ref main
# Deploy previous commit
otterstack deploy myapp --ref HEAD~1
# Or deploy specific commit
otterstack deploy myapp --ref a1b2c3d
# Update variable
otterstack env set myapp API_KEY=new-key
# Redeploy for changes to take effect
otterstack deploy myapp
OtterStack validates environment variables before starting deployment:
$ otterstack deploy myapp
Validating environment variables...
❌ ERROR: Missing required environment variables
The following variables are required but not set:
DATABASE_URL
• Required by: web, worker
• Error: Database connection required
API_KEY
• Required by: web
To fix this, you can:
1. Set variables individually:
otterstack env set myapp DATABASE_URL=<value>
otterstack env set myapp API_KEY=<value>
2. Use interactive scan:
otterstack env scan myapp
3. Load from file:
otterstack env load myapp .env.myapp
Error: missing required environment variables
This prevents wasted deployment attempts with incomplete configuration!
# List all projects
otterstack project list
# Verify project name matches exactly
Another deployment is in progress or a previous one failed:
# Wait for deployment to finish, or if stuck:
rm ~/.otterstack/locks/<project>.lock
# Then retry
otterstack deploy myapp
# Scan for missing variables
otterstack env scan myapp
# Or check what's missing
otterstack env list myapp
Containers didn't become healthy within 5 minutes:
# Check container logs
docker compose -f /path/to/worktree/docker-compose.yml logs
# Check container status
docker compose -f /path/to/worktree/docker-compose.yml ps
# Fix issues, then redeploy
otterstack deploy myapp
# Verify compose file path
cat ~/.otterstack/projects.db | grep compose_file
# Update if wrong
# (Currently requires manual DB edit - future feature)
# Verify variables are set
otterstack env list myapp --show-values
# Check compose file syntax
grep -E '\$\{[A-Z_]+\}' docker-compose.yml
# Redeploy after setting variables
otterstack deploy myapp
.env.<project-name> files during initial setupenv scan to catch missing variables early.env.example for documentation${VAR} syntax for environment variables${VAR:-default} when possiblecontainer_name (breaks worktree isolation)env_file (OtterStack manages env vars)--traefik-routing for production appsgit tag v1.0.0--force in production unless necessaryOtterStack creates git worktrees for each deployment:
# Worktrees are stored at:
~/.otterstack/worktrees/<project>/<commit-hash>/
# Each worktree is isolated with its own:
# - Git checkout
# - Docker Compose state
# - Environment file
Old worktrees are cleaned up based on retention policy:
You can interact with deployed containers directly:
# Find worktree path
WORKTREE=$(ls -t ~/.otterstack/worktrees/myapp | head -1)
# Use docker compose directly
docker compose -f ~/.otterstack/worktrees/myapp/$WORKTREE/docker-compose.yml logs
docker compose -f ~/.otterstack/worktrees/myapp/$WORKTREE/docker-compose.yml exec web bash
Compose file health check example:
services:
web:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
.env.<project-name> filesenv scan command.env.example generation# General help
otterstack --help
# Command-specific help
otterstack project --help
otterstack env --help
otterstack deploy --help
# Version info
otterstack version
README.md - Overview and quick startIMPROVEMENTS.md - Proposed enhancements based on deployment experienceTROUBLESHOOTING.md - Common issues and solutions.claude/plans/enhanced-env-var-management.md - Implementation plan for env var featuresOtterStack makes Docker Compose deployments simple and safe:
project addenv scan or auto-discoverydeployThe enhanced environment variable management ensures you never deploy with missing configuration, and the interactive prompts make setup a breeze!
This skill is referenced during Phase 4: Setup and Phase 5: Deployment of the /deploy-otterstack command.
The orchestration command uses this skill's documentation to execute OtterStack commands in three modes:
When the orchestration command needs to set up a new project:
Check if project exists:
# Local
otterstack project list | grep -q "^${PROJECT_NAME}$"
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack project list | grep -q '^${PROJECT_NAME}$'"
Add project if missing (local):
otterstack project add ${PROJECT_NAME} /path/to/repo --traefik-routing
Add project if missing (remote/VPS):
# Get remote git URL
REPO_URL=$(git config --get remote.origin.url)
# Add to VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack project add ${PROJECT_NAME} ${REPO_URL} --traefik-routing"
When the orchestration command configures environment variables:
Auto-load from .env file if exists:
if [ -f ".env.${PROJECT_NAME}" ]; then
# Local
otterstack env load ${PROJECT_NAME} .env.${PROJECT_NAME}
# VPS
scp .env.${PROJECT_NAME} archivist@194.163.189.144:/tmp/
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env load ${PROJECT_NAME} /tmp/.env.${PROJECT_NAME}"
fi
Interactive scan for missing variables:
# Local
otterstack env scan ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env scan ${PROJECT_NAME}"
Validate all required vars are set:
# Local
otterstack env list ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env list ${PROJECT_NAME}"
Set individual variables:
# Local
otterstack env set ${PROJECT_NAME} DATABASE_URL="postgres://..."
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env set ${PROJECT_NAME} DATABASE_URL='postgres://...'"
When the orchestration command executes deployment:
Deploy with verbose output for monitoring:
# Local
otterstack deploy ${PROJECT_NAME} -v
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} -v"
Monitor deployment stages: The orchestration command watches for these sequential stages:
Check deployment status:
# Local
otterstack status ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack status ${PROJECT_NAME}"
View deployment history:
# Local
otterstack deployments ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deployments ${PROJECT_NAME}"
Commands used by /deploy-otterstack:
Pre-flight checks:
# Verify OtterStack is installed
which otterstack || command -v otterstack
# VPS: Test SSH connection
ssh -o ConnectTimeout=5 archivist@194.163.189.144 "echo 'SSH OK'"
# VPS: Verify OtterStack on VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack --version"
Project existence check:
# Returns exit code 0 if exists, 1 if not
otterstack project list | grep -q "^${PROJECT_NAME}$" && echo "exists" || echo "missing"
Quick deployment status:
otterstack status ${PROJECT_NAME} 2>&1
Force redeploy if lock stuck:
# Local
rm ~/.otterstack/locks/${PROJECT_NAME}.lock
otterstack deploy ${PROJECT_NAME} -v
# VPS
ssh archivist@194.163.189.144 "rm ~/.otterstack/locks/${PROJECT_NAME}.lock"
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} -v"
Get previous deployment SHA (for rollback):
# Local
otterstack deployments ${PROJECT_NAME} | tail -2 | head -1 | awk '{print $2}'
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deployments ${PROJECT_NAME} | tail -2 | head -1 | awk '{print \$2}'"
Deploy specific ref (rollback):
# Local
otterstack deploy ${PROJECT_NAME} --ref ${PREVIOUS_SHA} -v
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} --ref ${PREVIOUS_SHA} -v"
The orchestration command maintains these variables that inform OtterStack commands:
PROJECT_NAME - Name of the project being deployedDEPLOYMENT_TARGET - "local" or "vps"SSH_PREFIX - Empty for local, "ssh archivist@194.163.189.144" for VPSOTTERSTACK_CMD - "otterstack" for local, "~/OtterStack/otterstack" for VPSREPO_PATH - Local repository pathREPO_URL - Git repository URL (for VPS)Commands are constructed as:
${SSH_PREFIX} ${OTTERSTACK_CMD} [subcommand] [args]
The orchestration command handles these OtterStack error scenarios:
| Error | OtterStack Message | Orchestration Action |
|---|---|---|
| Missing env vars | "variable X is not set" | Run env scan or prompt user |
| Project not found | "project not found" | Add project with project add |
| Lock held | "deployment in progress" | Wait or remove stale lock |
| Validation failed | "compose validation failed" | Invoke debug-vps-deployment |
| Health check failed | "container unhealthy" | Invoke debug-vps-deployment |
/deploy-otterstack - Full orchestration command that uses this skill in Phases 4 and 5