Skip to main content
ClaudeWave
Skill355 repo starsupdated today

gen-env

The gen-env skill creates or reviews a command that enables running multiple isolated instances of a project simultaneously on localhost by establishing a unique workspace identity that controls port allocation, Docker volumes, networks, container names, and browser cookie domains. Use it when developing features in parallel worktrees, testing multiple versions concurrently, or preventing data corruption and authentication conflicts between independent local environments.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/aiskillstore/marketplace /tmp/gen-env && cp -r /tmp/gen-env/skills/0xbigboss/gen-env ~/.claude/skills/gen-env
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# gen-env Skill

Generate or review a `gen-env` command that enables running **multiple isolated instances** of a project on localhost simultaneously (e.g., multiple worktrees, feature branches, or versions).

## The Problem

Without isolation, multiple instances of the same project:
- Fight for hardcoded ports (3000, 5432, 8080)
- Share Docker volumes → data corruption
- Share browser cookies/localStorage → auth confusion
- Have ambiguous container names → can't tell which is which
- Risk catastrophic cleanup → `docker down -v` nukes everything

## The Solution: Instance Identity

Everything flows from a **workspace name**:

```
name = "feature-x"
         ↓
┌─────────────────────────────────────────────────────┐
│ COMPOSE_PROJECT_NAME = localnet-feature-x           │
│ DOCKER_NETWORK       = localnet-feature-x           │
│ VOLUME_PREFIX        = localnet-feature-x           │
│ CONTAINER_PREFIX     = localnet-feature-x-          │
│ TILT_HOST            = feature-x.localhost          │
│ Ports                = dynamically allocated        │
│ URLs                 = derived from host + ports    │
└─────────────────────────────────────────────────────┘
```

## Isolation Dimensions

### 1. Port Isolation
Each instance gets unique ports from ephemeral range (49152-65535).

### 2. Data Isolation
Docker Compose project name controls volume naming:
- Instance A: `localnet-main_postgres_data`
- Instance B: `localnet-feature-x_postgres_data`

No cross-contamination. Independent databases.

### 3. Network Isolation
Separate Docker networks per instance. Containers reference each other by service name without collision.

### 4. Browser State Isolation
**Critical**: Different ports on `localhost` still share cookies!

```
http://localhost:3000  ─┐
                        ├─ SAME cookies, localStorage
http://localhost:3001  ─┘
```

Solution: subdomain isolation via `*.localhost`:
```
http://main.localhost:3000      ─ separate cookies
http://feature-x.localhost:3001 ─ separate cookies
```

Chrome/Edge treat `*.localhost` as `127.0.0.1` automatically. No `/etc/hosts` needed.

### 5. Auth Isolation
Each instance can have its own auth realm/audience, preventing token confusion.

### 6. Resource Naming
Clear prefixes on containers, volumes, Tilt resources, logs → know exactly which instance you're looking at.

## Implementation Checklist

When creating or reviewing gen-env:

**Identity & Naming:**
- [ ] Requires `--name <workspace>` argument
- [ ] Validates name (alphanumeric + dashes, max 63 chars for DNS)
- [ ] Generates `COMPOSE_PROJECT_NAME` from name
- [ ] Generates `DOCKER_NETWORK`, `VOLUME_PREFIX`, `CONTAINER_PREFIX`
- [ ] Generates `*_HOST` for browser isolation (`name.localhost`)

**Port Allocation:**
- [ ] Allocates from ephemeral range (49152-65535)
- [ ] Checks port availability before assignment
- [ ] Uses short timeout (100ms) for CI compatibility
- [ ] Handles IPv6-disabled environments gracefully

**Persistence:**
- [ ] Lockfile stores name + ports (`.gen-env.lock`)
- [ ] Reuses ports when lockfile exists and name matches
- [ ] `--force` regenerates all
- [ ] `--clean` removes generated files

**Output:**
- [ ] Generates `.localnet.env` (or project-specific name)
- [ ] Clear header with generation timestamp
- [ ] All derived URLs use correct host + port

**Integration:**
- [ ] Script added to PATH via `.envrc`
- [ ] Generated env sourced by `.envrc`
- [ ] Works with Docker Compose (`--env-file`)
- [ ] Works with Tilt (Starlark reads env file)

## Generated Environment Structure

```bash
# .localnet.env - generated by gen-env
# Instance: feature-x
# Generated: 2024-01-15T10:30:00Z

# === Instance Identity ===
WORKSPACE_NAME=feature-x
COMPOSE_NAME=localnet-feature-x
COMPOSE_PROJECT_NAME=localnet-feature-x
DOCKER_NETWORK=localnet-feature-x
VOLUME_PREFIX=localnet-feature-x
CONTAINER_PREFIX=localnet-feature-x-

# === Host (for browser isolation) ===
APP_HOST=feature-x.localhost
TILT_HOST=feature-x.localhost

# === Allocated Ports ===
POSTGRES_PORT=51234
REDIS_PORT=51235
API_PORT=51236
WEB_PORT=51237
# ... more ports

# === Derived URLs ===
DATABASE_URL=postgres://user:pass@localhost:51234/dev
WEB_URL=http://feature-x.localhost:51237
API_URL=http://feature-x.localhost:51236
```

## direnv Integration

```bash
# .envrc
PATH_add bin  # or scripts

dotenv_if_exists .localnet.env
```

## Reference Implementation (TypeScript/Bun)

See @IMPLEMENTATION.md for full implementation.

Key types:

```typescript
interface InstanceConfig {
  name: string;                    // Workspace identity
  composeName: string;             // Docker Compose project name
  dockerNetwork: string;           // Docker network name
  volumePrefix: string;            // Docker volume prefix
  containerPrefix: string;         // Container name prefix
  host: string;                    // Browser hostname (name.localhost)
  ports: Record<string, number>;   // Allocated ports
  urls: Record<string, string>;    // Derived URLs
}

interface LockfileData {
  version: 1;
  generatedAt: string;
  instance: InstanceConfig;
}
```

## Cleanup Patterns

Surgical cleanup per instance:

```bash
# Clean only feature-x (containers + volumes + networks)
docker compose -p localnet-feature-x down -v

# Or via gen-env
gen-env --clean  # removes .localnet.env and .gen-env.lock

# List all localnet instances
docker ps -a --filter "name=localnet-" --format "table {{.Names}}\t{{.Status}}"

# Nuclear option (all instances) - DANGEROUS
docker ps -a --filter "name=localnet-" -q | xargs docker rm -f
docker volume ls --filter "name=localnet-" -q | xargs docker volume rm
```

## Common Patterns

### Pattern 1: Worktree-Based Naming

```bash
# Derive name from git worktree directory
WORKTREE_NAME=$(basename "$(git rev-parse --show-toplevel)")
gen-env --name "$WORKTREE_NAME"
```

### Pattern 2: Branch-Based Naming

```bash
# Derive name from branch
BRANCH=$(git branch --show-current | tr '/' '-')
gen-env --name "$BRANCH"
```

### Pattern 3: Explicit Na
jira-safeSkill

Implement SAFe methodology in Jira. Use when creating Epics, Features, Stories with proper hierarchy, acceptance criteria, and parent-child linking.

jira-workflowSkill

Orchestrate Jira workflows end-to-end. Use when building stories with approvals, transitioning items through lifecycle states, or syncing task completion with Jira.

chinese-learning-assistantSkill

HSK4級レベルから流暢さを目指す学習者向け。中国語表現の使用場面・自然さを分析し、作文を「ネイティブらしい流暢な表現」に改善。bilibili等のコンテンツ理解とネイティブとの会話をサポート。実際の用例をWeb検索で提示

frontend-dev-guidelinesSkill

Next.js 15 애플리케이션을 위한 프론트엔드 개발 가이드라인. React 19, TypeScript, Shadcn/ui, Tailwind CSS를 사용한 모던 패턴. Server Components, Client Components, App Router, 파일 구조, Shadcn/ui 컴포넌트, 성능 최적화, TypeScript 모범 사례 포함. 컴포넌트, 페이지, 기능 생성, 데이터 페칭, 스타일링, 라우팅, 프론트엔드 코드 작업 시 사용.

skill-developerSkill

Claude Code 스킬, 훅, 에이전트, 명령어를 생성하고 관리하기 위한 메타 스킬. 새 스킬 생성, 스킬 트리거 설정, 훅 설정, Claude Code 인프라 관리 시 사용.

sitemapkitSkill

Discover and extract sitemaps from any website using SitemapKit. Use this skill whenever the user wants to find pages on a website, get a list of URLs from a domain, audit a site's structure, crawl a sitemap, check what pages exist on a site, or do anything involving sitemaps or site URL discovery — even if they don't explicitly say "sitemap". Requires the sitemapkit MCP server configured with a valid SITEMAPKIT_API_KEY.

create-prSkill

GitHubのプルリクエスト(PR)を作成する際に使用します。変更のコミット、プッシュ、PR作成を含む完全なワークフローを日本語で実行します。「PRを作って」「プルリクエストを作成」「pull requestを作成」などのリクエストで自動的に起動します。

create-svg-from-promptSkill

Generate an SVG of a user-requested image or scene