@ssh/wednesday
v0.2.0
Published
CLI tool that orchestrates git branches, PlanetScale database branches, and preview deployments
Readme
wednesday
CLI tool that orchestrates git branches, PlanetScale database branches, and preview deployments.
Features
- Branch Orchestration: Create feature branches with matching database branches in one command
- Database Branching: PlanetScale integration for isolated database environments per branch
- Local/Remote Toggle: Switch between local and remote databases instantly
- Preview Deployments: Deploy preview environments with Pulumi or Vercel
- Clean Teardown: Delete branches and all associated resources with one command
Installation
npm install -g @ssh/wednesday
# or
bunx @ssh/wednesday
# or
pnpm add -g @ssh/wednesdayThe CLI is available as wednesday (or wed for short).
Quick Start
# Initialize wednesday in your project
wednesday init
# Create a new feature branch (git + database)
wednesday create my-feature
# Switch between local and remote database
wednesday db local
wednesday db remote
# Deploy a preview environment
wednesday deploy
# Clean up when done
wednesday deleteCommands
wednesday init
Initialize wednesday in your project. Creates a wednesday.config.ts file with interactive prompts.
wednesday init
wednesday init --force # Overwrite existing configwednesday create [name]
Create a new feature branch with an optional matching database branch.
wednesday create my-feature
wednesday create # Interactive prompt for name
wednesday create --no-db # Skip database branch creation
wednesday create --db-only # Only create database branchwednesday switch [name]
Switch to an existing branch and update database connection.
wednesday switch my-feature
wednesday switch # Interactive branch selectionwednesday db
Manage which database local dev points at.
wednesday db local # Point DATABASE_URL at the configured local database
wednesday db remote # Point at the current git branch's PlanetScale branch
wednesday db remote staging # Point at a specific branch (used verbatim)
wednesday db remote --create # Create the branch off baseBranch if missing, then point at it
wednesday db list # List branches you can point at (alias: ls)
wednesday db delete [branch] # Delete a branch, current git branch's by default (alias: rm)remote [branch]— with no argument, the target is the current git branch mapped through the config'snaminghook, so it matches whatever your CI/preview pipeline names it. Pass an explicit[branch](e.g. one fromdb list) to use that name verbatim.--createforks it frombaseBranchwhen it doesn't exist.listmarks the branch matching your current git branch.deleteprompts for confirmation (skip with-f/--force) and refuses to deletebaseBranch.
wednesday deploy
Build Docker images and deploy a preview environment.
wednesday deploy
wednesday deploy --skip-build # Skip Docker build
wednesday deploy --skip-push # Skip pushing imageswednesday undeploy
Destroy preview environment (keeps git and database branches).
wednesday undeploy
wednesday undeploy --force # Skip confirmationwednesday delete [name]
Delete a branch and all associated resources.
wednesday delete my-feature
wednesday delete # Delete current branch
wednesday delete --keep-db # Keep database branch
wednesday delete --keep-preview # Keep preview deployment
wednesday delete --force # Skip confirmationwednesday promote [target]
Create a PlanetScale deploy request to promote schema changes.
wednesday promote staging
wednesday promote production
wednesday promote --dry-run # Show what would happenwednesday list
List all branches with their database and preview status.
wednesday list
wednesday ls # Alias
wednesday list --json # JSON outputwednesday status
Show current branch status including database and preview info.
wednesday status
wednesday status --json # JSON outputConfiguration
Create a wednesday.config.ts file in your project root:
import { defineConfig } from '@ssh/wednesday';
export default defineConfig({
// PlanetScale database branching
database: {
provider: 'planetscale',
org: 'your-org',
database: 'your-database',
baseBranch: 'main',
},
// Local database for development
local: {
url: 'postgres://postgres:postgres@localhost:5432/mydb',
},
// Preview deployments with Pulumi
preview: {
provider: 'pulumi',
stack: 'preview',
domain: 'preview.myapp.com',
},
// Docker image building
docker: {
registry: 'ghcr.io/your-org',
images: ['api', 'web'],
},
// Environment file to update
envFile: '.env.local',
});Configuration Options
| Option | Required | Description |
|--------|----------|-------------|
| database | No | PlanetScale configuration for database branching |
| database.provider | Yes | Currently only 'planetscale' is supported |
| database.org | Yes | PlanetScale organization name |
| database.database | Yes | PlanetScale database name |
| database.baseBranch | No | Production branch name (default: 'main') |
| database.naming | No | (gitBranch: string) => string mapping a git branch to its database branch name (default: sanitizeBranchName) — see Branch Naming |
| local | No | Local database configuration |
| local.url | Yes | Local database connection URL |
| preview | No | Preview deployment configuration |
| preview.provider | Yes | 'pulumi' or 'vercel' |
| preview.stack | Pulumi | Pulumi stack name prefix |
| preview.domain | Pulumi | Domain for preview URLs |
| preview.projectName | Vercel | Vercel project name (required if no projectId) |
| preview.projectId | Vercel | Vercel project ID (required if no projectName) |
| preview.teamId | No | Vercel team ID for team accounts |
| preview.framework | No | Vercel framework preset (auto-detected if not set) |
| docker | No | Docker configuration (required for Pulumi) |
| docker.registry | Yes | Docker registry URL (e.g., ghcr.io/org) |
| docker.images | Yes | Array of image names to build |
| envFile | No | Environment file to update (default: '.env.local') |
Branch Naming
By default the database branch name is derived from the current git branch with
sanitizeBranchName. If your CI or preview pipeline names its database branches with a
different rule, provide a naming function so your local branches converge on the
same database branch the pipeline uses — no manual coordination.
import { defineConfig } from '@ssh/wednesday';
// A project can import its own slug rule and inject it here.
import { previewEnvName } from '@your-scope/preview';
export default defineConfig({
database: {
provider: 'planetscale',
org: 'my-org',
database: 'my-db',
// git branch `feat/foo-bar` -> database branch `feat-foo-bar`
naming: previewEnvName,
},
});The hook receives the git branch (which may contain slashes) and returns the database
branch name. It is applied everywhere wednesday maps a git branch to a database branch
(create, switch, db, delete, deploy, promote, status, list).
Provider Setup
PlanetScale
Wednesday supports two authentication methods for PlanetScale:
Option 1: Service Tokens (recommended for CI/CD)
export PLANETSCALE_SERVICE_TOKEN_ID=your-token-id
export PLANETSCALE_SERVICE_TOKEN=your-tokenCreate a service token at: https://app.planetscale.com/<org>/settings/service-tokens
Option 2: CLI Authentication (recommended for local dev)
# Install pscale CLI
brew install planetscale/tap/pscale
# Authenticate
pscale auth loginPulumi
# Install Pulumi CLI
brew install pulumi
# Login to Pulumi backend
pulumi login
# Or use local backend
pulumi login --localVercel
Wednesday supports Vercel for preview deployments. Vercel handles building and hosting automatically—no Docker configuration needed.
Option 1: API Token (recommended for CI/CD)
export VERCEL_TOKEN=your-tokenCreate a token at: https://vercel.com/account/tokens
Option 2: CLI Authentication (recommended for local dev)
# Install Vercel CLI
npm install -g vercel
# Authenticate
vercel loginVercel Configuration Example
import { defineConfig } from '@ssh/wednesday';
export default defineConfig({
database: {
provider: 'planetscale',
org: 'your-org',
database: 'your-database',
baseBranch: 'main',
},
preview: {
provider: 'vercel',
projectName: 'my-app',
teamId: 'team_xxxxx', // Optional: for team accounts
framework: 'nextjs', // Optional: auto-detected
},
envFile: '.env.local',
});When deploying, wednesday automatically passes the DATABASE_URL from PlanetScale to your Vercel deployment.
Docker / GHCR
# Login to GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdinEnvironment Variables
| Variable | Description |
|----------|-------------|
| PLANETSCALE_SERVICE_TOKEN_ID | PlanetScale service token ID |
| PLANETSCALE_SERVICE_TOKEN | PlanetScale service token |
| VERCEL_TOKEN | Vercel API token |
| DATABASE_URL | Set automatically by wednesday |
Shell Completions
Wednesday supports shell completions for zsh, bash, and fish:
# Zsh (add to ~/.zshrc)
eval "$(wednesday completions zsh)"
# Bash (add to ~/.bashrc)
eval "$(wednesday completions bash)"
# Fish
wednesday completions fish > ~/.config/fish/completions/wednesday.fishProgrammatic Usage
import { defineConfig, loadConfig } from '@ssh/wednesday';
// Load configuration
const config = await loadConfig();
// Access providers
import { createDatabaseProvider } from '@ssh/wednesday';
const db = createDatabaseProvider(config);
await db.createBranch('my-feature');Troubleshooting
"Not a git repository"
Run wednesday from within a git repository root.
"wednesday.config.ts not found"
Run wednesday init to create a configuration file.
"PlanetScale authentication required"
Either:
- Set
PLANETSCALE_SERVICE_TOKENandPLANETSCALE_SERVICE_TOKEN_IDenvironment variables - Run
pscale auth loginto authenticate via CLI
"Pulumi not authenticated"
Run pulumi login to authenticate with Pulumi.
"Docker build failed"
Ensure Docker is installed and running. Check that Dockerfiles exist at docker/<image>/Dockerfile.
"Vercel authentication required"
Either:
- Set
VERCEL_TOKENenvironment variable - Run
vercel loginto authenticate via CLI
"Vercel project not found"
Ensure your projectName or projectId in the config matches an existing Vercel project. You can create a project by running vercel in your project directory first.
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT
