Claude
Skills
Sign in
Back

generate-env-scripts

Included with Lifetime
$97 forever

Use when project needs isolated development environments for parallel feature work, or when adding new external services (databases, caches, message queues) that require environment isolation. ONE-TIME setup skill - clear context after use.

Generalscriptsassets

What this skill does


# Generate Environment Scripts

## Overview

**ONE-TIME SETUP SKILL** - Scans project infrastructure and guides creation of automation scripts (setup-env.sh, cleanup-env.sh, smoke-test.sh) for isolated development environments using git worktrees. **Core principle**: Establish isolation infrastructure once, then exit context. This is NOT for ongoing implementation work.

**CRITICAL**: After completing setup, **tell user to clear context** (`/clear` or restart session). This skill adds setup details that shouldn't persist into implementation conversations.

**Announce at start:** "i'm using generate-env-scripts skill to scan infrastructure and create isolation scripts"

## When to Use

**Use ONCE when**:
- New project needs parallel feature development capability
- Adding external services (database, cache, queue, storage) that need isolation
- Developers report environment conflicts (port collisions, data pollution)

**Re-run when**:
- Adding new external service (e.g., adding Redis to project that only had Postgres)
- Changing infrastructure (migrating from Docker to Kubernetes, adding Supabase)
- Isolation scripts break due to environment changes

**Don't use for**:
- Actually creating worktrees (use project's generated script via `setup-isolated-env:activate-worktree-env`)
- Ongoing feature development (that's what generated scripts are for)
- Debugging existing isolation setup (read project's scripts instead)

## Quick Reference

| Component | Purpose | Location |
|-----------|---------|----------|
| checklist.sh | Detect infrastructure and validate prerequisites | Skill `./scripts/` directory |
| setup-env.sh | Project-generated script for creating isolated environments | `<worktree_scripts>` (user-chosen location) |
| cleanup-env.sh | Remove isolated environment and cleanup resources | `<worktree_scripts>` (user-chosen location) |
| smoke-test.sh | Verify connectivity after setup | `<worktree_scripts>` (user-chosen location) |

## Implementation

### Step 1: Run Infrastructure Detection

**Always start with checklist** to understand project infrastructure:

```bash
# Run from PROJECT ROOT using absolute path
"${CLAUDE_PLUGIN_ROOT}/skills/generate-env-scripts/scripts/checklist.sh"
```

**CRITICAL**: Run checklist.sh **from your project root directory**, not from the skill directory. The script needs to scan project files (docker-compose.yml, .env.example, src/ directories).

**Note**: Script location will be chosen in Step 2. Examples below use `<worktree_scripts>` to represent the chosen location.

**Checklist detects**:
- Container orchestration (Docker Compose, Kubernetes, Supabase, etc.)
- Environment templates (`.env.example`, `.env.local.example`, etc.)
- External services (databases, caches, queues, storage)
- Hardcoded service URLs that break isolation

**If checklist fails**: Stop. Ask user to resolve prerequisites (missing env template, no containerization, etc.)

**If hardcoded URLs found**: Document them. Guide user to refactor BEFORE creating isolation scripts.

### Step 2: Determine Script Location

**Goal**: Detect existing worktree conventions, then confirm or choose script location.

#### 2a: Scan Existing Worktrees

**Always scan first** before suggesting anything:

```bash
# List all existing worktrees (skip main worktree - first line)
git worktree list --porcelain | grep "^worktree" | tail -n +2 | awk '{print $2}'
```

**From results, detect**:
1. **Worktree directory** — where are they stored? (`.worktrees/`, `worktrees/`, `../feature-branches/`, etc.)
2. **Script location** — look for existing automation scripts:

```bash
# Check common script locations relative to project root
ls .worktrees_scripts/ 2>/dev/null
ls scripts/ 2>/dev/null
ls worktree_scripts/ 2>/dev/null
```

**If existing worktrees and scripts found** → present detected convention and ask to confirm:

> Detected: worktrees in `.worktrees/`, scripts in `.worktrees_scripts/`
> Use this convention? [Y/n]

**If existing worktrees but no scripts found** → note the worktree directory, then proceed to 2b for script location only.

**If no existing worktrees** → proceed to 2b.

#### 2b: Choose Location (when not detected)

**Suggest options and ask user to decide:**

| Option | Path | Recommended when |
|--------|------|-----------------|
| A (default) | `.worktrees_scripts/` | Project uses `.worktrees/` for worktrees |
| B | `scripts/` | Project already has a `scripts/` directory |
| C | Custom path | User has specific preference |

```bash
# Option A (default)
mkdir -p .worktrees_scripts

# Option B
mkdir -p scripts
```

**Replace `<worktree_scripts>` with chosen location throughout remaining steps.**

### Step 3: Guide Creation of setup-env.sh

**DO NOT copy-paste** the example from `assets/`. Instead, **guide user to create** project-specific script based on detected infrastructure.

**Framework-agnostic template structure**:

```bash
#!/usr/bin/env bash
set -euo pipefail

# 1. Check prerequisites (adapt from checklist.sh)
check_prerequisites() {
    # Verify infrastructure is running
    # Check environment template exists
}

# 2. Get environment name (branch name or custom)
get_environment_name() {
    # Prompt user or detect from git branch
}

# 3. Allocate unique resources
allocate_resources() {
    # Scan existing environments for port ranges
    # Increment by fixed offset (10, 100, etc.)
    # Assign unique database/cache identifiers
}

# 4. Create isolated environment
create_environment() {
    # Create git worktree at .worktrees/{env-name}
    # Copy environment template to .env.local
}

# 5. Update environment configuration
update_configuration() {
    # Set unique ports (PORT, API_PORT, etc.)
    # Set unique database connection (DATABASE_URL)
    # Set unique cache namespace (REDIS_DB, CACHE_PREFIX, etc.)
    # Update CORS origins, webhook URLs
}

# 6. Provision isolated resources
provision_resources() {
    # Create database (project-specific command)
    # Initialize cache namespace
    # Create storage buckets
}

# 7. Run migrations
run_migrations() {
    # Execute database migrations (project-specific)
    # Seed initial data if needed
}

# 8. Display summary
display_summary() {
    # Show environment details
    # Provide cleanup commands
}
```

**Adapt based on detected infrastructure**:

| Infrastructure | Database Creation | Cache Isolation |
|---------------|------------------|-----------------|
| Docker Compose | `docker compose exec db createdb {name}` | Redis DB 0-15 |
| Supabase | `supabase db execute --sql "CREATE DATABASE {name}"` | Redis DB 0-15 |
| Kubernetes | `kubectl exec deployment/db -- createdb {name}` | Redis DB 0-15 |
| Managed DB (RDS, Cloud SQL) | Manual or API call | Cache key prefixes |

**Port allocation strategy** (framework agnostic):
- Main environment: Base ports (e.g., 3000, 3001)
- Environment 1: Base + offset (e.g., 3010, 3011)
- Environment 2: Base + offset * 2 (e.g., 3020, 3021)
- Choose offset: 10, 100, or 1000 depending on service count

### Step 3.5: Framework-Specific Port Configuration

**CRITICAL**: Before writing setup scripts, ensure application code reads ports from environment variables.

**Run framework detection**:
```bash
"${CLAUDE_PLUGIN_ROOT}/skills/generate-env-scripts/scripts/detect-framework.sh"
```

**Common framework patterns**:

#### Vite Projects
```typescript
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    port: Number(process.env.PORT) || 5001,
  },
});

// package.json - REMOVE hardcoded port
"dev": "vite dev --host"  // NOT: "vite dev --port 5001"
```

#### Next.js Projects
```bash
# Next.js reads PORT automatically
# package.json - ensure no hardcoded port
"dev": "next dev"  # NOT: "next dev -p 3000"
```

#### Express/Elysia/Bun
```typescript
// src/index.ts
const PORT = Number(process.env.PORT) || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
```

**Verification**: Check checklist.sh output f

Related in General