CLI Examples
title: CLI Examples audience: Developer difficulty: Beginner estimated_read_time: 6 min prerequisites:
- CLI installed
- Access to env.cat service related_pages:
- ./envcat-get.md
- ../recipes/onboard-new-dev.md
Real-world examples of using envcat in different scenarios.
Daily Development
Morning Workflow
Load secrets into your shell for the day:
cd ~/projects/my-app
eval "$(envcat get --api-base https://env.cat --bundle dev/api)"
npm run dev
Verify secrets loaded:
echo $DATABASE_URL
# postgres://localhost:5432/myapp
echo $API_KEY
# sk_test_abc123xyz
Multiple Projects
Switch between projects easily:
# Project 1
cd ~/projects/api
eval "$(envcat get --bundle dev/api)"
npm run dev
# Project 2 (new terminal)
cd ~/projects/frontend
eval "$(envcat get --bundle dev/frontend)"
npm run dev
Temporary Secrets
Load secrets for a single command:
(eval "$(envcat get --bundle dev/api)" && npm run seed)
Benefits:
- Secrets only available during
npm run seed - Parent shell unaffected
- Automatic cleanup
Environment Management
Development → Staging → Production
Separate bundles for each environment:
# Development
eval "$(envcat get --bundle dev/api)"
npm run dev
# Staging (new terminal/tab)
eval "$(envcat get --bundle staging/api)"
npm start
# Production (new terminal/tab)
eval "$(envcat get --bundle prod/api)"
npm start
Feature Branch Environments
Separate bundles for feature branches:
# Main branch
git checkout main
eval "$(envcat get --bundle dev/api-main)"
# Feature branch
git checkout feature/new-auth
eval "$(envcat get --bundle dev/api-feature-auth)"
Docker & Containers
Docker Compose
Generate .env for Docker Compose:
# Get secrets
envcat get --bundle dev/api --file .env
# Start services
docker-compose up
# Cleanup
rm .env
docker-compose.yml:
version: '3.9'
services:
api:
build: .
env_file:
- .env
ports:
- "3000:3000"
Dockerfile Build Args
Pass secrets as build args:
# Get secrets to .env
envcat get --bundle ci/build --file .env
# Read into build args
source .env
# Build with args
docker build \
--build-arg NPM_TOKEN=$NPM_TOKEN \
--build-arg API_KEY=$API_KEY \
-t myapp:latest .
Docker Run
Run container with secrets:
# Get secrets
envcat get --bundle prod/api --file .env
# Run with env file
docker run --env-file .env myapp:latest
# Cleanup
rm .env
Freelance / Client Switching
Multiple Clients
Organize by client:
# Client A
cd ~/clients/acme-corp
eval "$(envcat get --bundle client-acme/api)"
# Client B
cd ~/clients/globex
eval "$(envcat get --bundle client-globex/api)"
Per-Project Bundles
Structure:
bundles:
- client-acme/api
- client-acme/frontend
- client-acme/database
- client-globex/api
- client-globex/backend
Usage:
cd ~/clients/acme-corp/api
eval "$(envcat get --bundle client-acme/api)"
cd ~/clients/acme-corp/frontend
eval "$(envcat get --bundle client-acme/frontend)"
Testing
Integration Tests
Load production-like secrets for testing:
# Get prod database (read-only credentials)
envcat get --bundle test/integration --keys DATABASE_URL,REDIS_URL --file .env.test
# Run tests
npm run test:integration
# Cleanup
rm .env.test
Specific Keys Only
Only request what you need:
# Only database for tests
eval "$(envcat get --bundle prod/api --keys DATABASE_URL)"
npm run test:db
CI/CD Testing
GitHub Actions:
name: Integration Tests
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install envcat
run: curl -fsSL https://env.cat/cli/install.sh | sh
- name: Get test secrets
run: |
envcat get --bundle ci/tests --file .env
source .env
- name: Run tests
run: npm run test:integration
Shell Integration
Bash Alias
Add to ~/.bashrc:
alias load-secrets='eval "$(envcat get --api-base https://env.cat --bundle dev/api)"'
Usage:
cd ~/projects/my-app
load-secrets
npm run dev
Fish Function
Add to ~/.config/fish/functions/secrets.fish:
function secrets
envcat get --api-base https://env.cat --bundle dev/api --format fish | source
end
Usage:
cd ~/projects/my-app
secrets
npm run dev
Direnv Integration
.envrc:
#!/bin/bash
# Load secrets when entering directory
eval "$(envcat get --bundle dev/api)"
Usage:
cd ~/projects/my-app
# direnv automatically loads secrets
direnv: loading ~/projects/my-app/.envrc
✓ Approved! Received 3 variable(s)
direnv: export +DATABASE_URL +API_KEY +PORT
Scripting
Conditional Loading
Load different bundles based on branch:
#!/bin/bash
BRANCH=$(git branch --show-current)
if [ "$BRANCH" = "main" ]; then
eval "$(envcat get --bundle prod/api)"
elif [ "$BRANCH" = "staging" ]; then
eval "$(envcat get --bundle staging/api)"
else
eval "$(envcat get --bundle dev/api)"
fi
npm start
Error Handling
Check if secrets loaded successfully:
#!/bin/bash
if envcat get --bundle dev/api --file .env; then
echo "✓ Secrets loaded"
source .env
npm start
else
echo "✗ Failed to load secrets (exit code: $?)"
exit 1
fi
Automated Deployment
Deployment script:
#!/bin/bash
set -e
# Get production secrets
echo "Loading production secrets..."
envcat get --bundle prod/api --file .env
# Build
echo "Building application..."
docker build -t myapp:latest .
# Deploy
echo "Deploying to production..."
docker run --env-file .env myapp:latest
# Cleanup
rm .env
echo "✓ Deployed successfully"
Advanced Patterns
Layered Secrets
Combine base + environment secrets:
#!/bin/bash
# Base secrets (shared across environments)
envcat get --bundle shared/base --file .env.base
# Environment-specific secrets
envcat get --bundle prod/api --file .env.prod
# Merge (prod overrides base)
cat .env.base .env.prod > .env
# Cleanup
rm .env.base .env.prod
# Use merged .env
source .env
npm start
Secret Rotation
Automated secret refresh:
#!/bin/bash
# Cron job runs every 6 hours
# 0 */6 * * * /home/user/scripts/refresh-secrets.sh
# Get latest secrets
envcat get --bundle prod/api --file /etc/myapp/.env
# Reload application
systemctl reload myapp
echo "$(date): Secrets refreshed" >> /var/log/myapp/secrets.log
Backup Before Update
Backup .env before overwriting:
#!/bin/bash
# Backup existing .env
if [ -f .env ]; then
cp .env .env.backup.$(date +%Y%m%d-%H%M%S)
fi
# Get new secrets
envcat get --bundle dev/api --file .env
echo "✓ Secrets updated (backup saved)"
Platform-Specific
Heroku Alternative
Use envcat instead of Heroku config vars:
# Get secrets
envcat get --bundle prod/heroku --file .env
# Deploy to Heroku with .env
heroku config:set $(cat .env | xargs)
# Cleanup
rm .env
AWS Lambda
Deploy Lambda with secrets:
# Get secrets
envcat get --bundle prod/lambda --file .env
# Convert to Lambda environment variables JSON
cat .env | jq -R 'split("=") | {(.[0]): .[1]}' | jq -s 'add' > env.json
# Deploy
aws lambda update-function-configuration \
--function-name my-function \
--environment "Variables=$(cat env.json)"
# Cleanup
rm .env env.json
Kubernetes Secrets
Create Kubernetes secret from envcat:
# Get secrets
envcat get --bundle prod/k8s --file .env
# Create Kubernetes secret
kubectl create secret generic app-secrets --from-env-file=.env
# Cleanup
rm .env
Deployment YAML:
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- secretRef:
name: app-secrets
Security Patterns
Minimal Exposure
Only request keys you need:
# Bad: Request entire bundle
eval "$(envcat get --bundle prod/api)"
# Good: Request specific keys
eval "$(envcat get --bundle prod/api --keys DATABASE_URL,API_KEY)"
Time-Limited Access
Load secrets only for specific task:
# Load secrets in subshell
(
eval "$(envcat get --bundle prod/api)"
npm run migrate
)
# Secrets no longer available
echo $DATABASE_URL
# (empty)
Audit Logging
Log secret access:
#!/bin/bash
# Log access
echo "$(date): $(whoami) loaded secrets for bundle: $1" >> ~/.envcat-audit.log
# Load secrets
eval "$(envcat get --bundle $1)"
Usage:
source load-secrets.sh dev/api
Git Safety
Never commit .env files:
# Add to .gitignore
echo ".env" >> .gitignore
echo ".env.*" >> .gitignore
echo "!.env.example" >> .gitignore
git add .gitignore
git commit -m "Add .env to gitignore"
Create .env.example template:
# Get secrets to .env
envcat get --bundle dev/api --file .env
# Create template (values masked)
sed 's/=.*/=/' .env > .env.example
# Commit template
git add .env.example
git commit -m "Add .env.example template"
Troubleshooting Examples
Debug Mode
See what's happening:
# Enable verbose output (future feature)
envcat get --bundle dev/api --verbose
# Or check exit code
envcat get --bundle dev/api --file .env
echo "Exit code: $?"
Dry Run
Preview without approving (future feature):
envcat get --bundle dev/api --dry-run
# Shows: Would request 5 keys from bundle 'dev/api'
# Keys: DATABASE_URL, REDIS_URL, API_KEY, PORT, DEBUG
Retry on Failure
Auto-retry on network errors:
#!/bin/bash
MAX_RETRIES=3
RETRY_COUNT=0
until envcat get --bundle dev/api --file .env; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
echo "Failed after $MAX_RETRIES attempts"
exit 1
fi
echo "Retry $RETRY_COUNT/$MAX_RETRIES..."
sleep 5
done
echo "✓ Secrets loaded"
See Also
- envcat get - Complete flag reference
- Output Formats - Format comparison
- Installation - Install envcat
- Troubleshooting - Common issues