Development

rails dev environment - Claude MCP Skill

Rails Development Environment Skill

SEO Guide: Enhance your AI agent with the rails dev environment tool. This Model Context Protocol (MCP) server allows Claude Desktop and other LLMs to rails development environment skill... Download and configure this skill to unlock new capabilities for your AI workflow.

๐ŸŒŸ1 stars โ€ข 0 forks
๐Ÿ“ฅ0 downloads

Documentation

SKILL.md
# Rails Development Environment Skill

> Generates isolated, Dockerized Rails development environments with browser automation and service mocking.

## Quick Start

```bash
# New Rails project
/rails-dev-env new myapp --profile standard

# Existing project (auto-detects Rails/Ruby versions)
/rails-dev-env setup --profile full
```

## Commands

### `new` - Create New Environment
```bash
/rails-dev-env new <project_name> [options]
```

**Options:**
- `--profile <minimal|standard|full>` - Service profile (default: standard)
- `--rails <version>` - Rails version (default: 8.1)
- `--ruby <version>` - Ruby version (default: 3.4.1)

> โš ๏ธ **CRITICAL**: Rails 8.1+ requires Ruby 3.4+ due to anonymous rest parameter syntax.
> Using Ruby 3.3.x with Rails 8.1.x will cause syntax errors.

### `setup` - Configure Existing Project
```bash
/rails-dev-env setup [options]
```

**Options:**
- `--profile <minimal|standard|full|custom>` - Service profile
- `--services <list>` - Custom services (comma-separated)
- `--force` - Overwrite existing Docker configuration

### `validate` - Validate Configuration
```bash
/rails-dev-env validate
```

### `status` - Show Environment Status
```bash
/rails-dev-env status
```

---

## Service Profiles

| Profile | Services | Min Memory | Recommended | Use Case |
|---------|----------|------------|-------------|----------|
| **minimal** | app, postgres, redis | 2 GB | 4 GB | Learning, simple apps |
| **standard** | minimal + sidekiq, mailpit, **playwright, selenium, browsers** | 6 GB | 8 GB | Most web applications, E2E testing |
| **full** | standard + localstack, wiremock, dozzle | 8 GB | 12+ GB | Enterprise, complex integrations |

> **๐Ÿงช E2E Testing Ready**: Standard profile now includes full browser automation infrastructure (Playwright, Selenium, Chrome, Firefox) making it fully equipped for end-to-end testing out of the box.

> **Note**: Memory values are Docker Desktop allocation requirements. See `references/profiles.md` for detailed per-service memory breakdown and optimization tips.

---

## Workflow: New Environment

When user requests a new Rails development environment:

### Phase 1: Gather Requirements

Ask user for project details using AskUserQuestion:

```yaml
questions:
  - question: "Which service profile do you need?"
    header: "Profile"
    options:
      - label: "Standard (Recommended)"
        description: "Rails, PostgreSQL, Redis, Sidekiq, Mailpit + Playwright/Selenium (E2E ready)"
      - label: "Minimal"
        description: "Rails, PostgreSQL, Redis only (no E2E testing)"
      - label: "Full"
        description: "Standard + AWS mocking (LocalStack), API mocking (WireMock), Dozzle"
      - label: "Custom"
        description: "Select individual services"

  - question: "Which Rails version?"
    header: "Rails"
    options:
      - label: "Rails 8.1 (Recommended)"
        description: "Latest stable (requires Ruby 3.4+)"
      - label: "Rails 8.0"
        description: "Propshaft, Import Maps, Solid Queue (Ruby 3.2+)"
      - label: "Rails 7.2"
        description: "Stable with Hotwire, good gem compatibility"
      - label: "Other"
        description: "Specify version manually"
```

### Phase 2: Analyze Existing Project (if applicable)

If setting up an existing project, run detection:

```python
from scripts.detect_project import analyze_project

analysis = analyze_project(project_path)
# Returns: ProjectAnalysis with rails_version, ruby_version,
#          database_adapter, existing_docker, detected_services
```

### Phase 3: Allocate Ports

```python
from scripts.allocate_ports import allocate_port, PORT_RANGES

ports = {}
for service, (start, end) in PORT_RANGES.items():
    ports[service] = allocate_port(
        env_name=project_name,
        service=service,
        start_port=start,
        end_port=end
    )
```

**Port Ranges** (Smart allocation prevents conflicts between concurrent environments):
| Service | Range | Notes |
|---------|-------|-------|
| rails | 3000-3099 | Primary application server |
| postgres | 5432-5499 | Database |
| redis | 6379-6399 | Cache/sessions |
| mailpit_web | 8025-8049 | Email preview UI |
| mailpit_smtp | 1025-1049 | SMTP capture |
| playwright_cdp | 9222-9299 | Chrome DevTools Protocol |
| selenium_hub | 4444-4499 | Selenium Grid hub |
| selenium_chrome | 7900-7949 | VNC for headed Chrome |
| selenium_firefox | 7950-7999 | VNC for headed Firefox |
| localstack | 4566-4599 | AWS service emulation |
| wiremock | 8080-8099 | API mocking |
| dozzle | 9999-9999 | Log viewer |

> **๐Ÿ”Œ Multi-Environment Support**: The port allocation system automatically assigns unique ports to each development environment, allowing you to run multiple projects simultaneously without conflicts.

### Phase 4: Generate Configuration Files

```python
from scripts.generate_templates import EnvironmentConfig, generate_all
import secrets

config = EnvironmentConfig(
    project_name=project_name,
    project_path=project_path,
    rails_version=(8, 1, 2),
    ruby_version="3.4.1",  # CRITICAL: Rails 8.1+ requires Ruby 3.4+
    node_version="20",
    bundler_version="2.5.0",
    profile="standard",
    services=["postgres", "redis", "sidekiq", "mailpit"],
    ports=ports,
    features={"action_cable": True, "active_storage": True},
    secret_key_base=secrets.token_hex(32),
    generated_at=datetime.now().isoformat(),
    skill_version="1.0.0"
)

result = generate_all(config, project_path)
```

**Generated Files:**
```
project/
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ Dockerfile.playwright
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ .env
โ”œโ”€โ”€ .env.template
โ”œโ”€โ”€ bin/
โ”‚   โ”œโ”€โ”€ dev-setup.sh
โ”‚   โ”œโ”€โ”€ dev-start.sh
โ”‚   โ”œโ”€โ”€ dev-stop.sh
โ”‚   โ”œโ”€โ”€ dev-status.sh
โ”‚   โ”œโ”€โ”€ dev-logs.sh
โ”‚   โ”œโ”€โ”€ dev-reset.sh
โ”‚   โ””โ”€โ”€ dev-rollback.sh
โ””โ”€โ”€ .devcontainer/
    โ””โ”€โ”€ devcontainer.json
```

### Phase 5: Validate Configuration

```python
from scripts.validate_environment import run_all_validations

report = run_all_validations(project_path)
if not report.all_passed:
    # Report issues and fix recommendations
    for result in report.results:
        if not result.passed:
            print(f"Issue: {result.message}")
            for fix in result.suggestions:
                print(f"  Fix: {fix}")
```

### Phase 6: Initialize Database with Seeds

**CRITICAL**: After building the environment, automatically initialize the database using `db/seeds.rb`. The seeds file should contain BOTH production-critical data AND test/demo data.

```bash
# Run database setup and seeding
./bin/dev-setup.sh  # Creates and migrates database
docker compose exec app rails db:seed
```

**Seeds.rb Best Practice**: Structure your seeds.rb to include:

```ruby
# db/seeds.rb

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# PRODUCTION-CRITICAL DATA (Required for application to function)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

puts "๐Ÿ”ง Loading production-critical data..."

# System roles that the application requires
Role.find_or_create_by!(name: 'admin') { |r| r.permissions = ['all'] }
Role.find_or_create_by!(name: 'user') { |r| r.permissions = ['read', 'write'] }

# Required configuration records
Setting.find_or_create_by!(key: 'app_name') { |s| s.value = 'MyApp' }

# Default categories, statuses, etc.
Status.find_or_create_by!(name: 'active')
Status.find_or_create_by!(name: 'inactive')

puts "โœ… Production-critical data loaded"

# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# TEST/DEMO DATA (Development and testing convenience)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

if Rails.env.development? || Rails.env.test?
  puts "๐Ÿงช Loading test/demo data..."

  # Demo admin user
  admin = User.find_or_create_by!(email: 'admin@example.com') do |u|
    u.password = 'password123'
    u.role = Role.find_by(name: 'admin')
  end

  # Sample data for testing
  5.times do |i|
    User.find_or_create_by!(email: "user#{i}@example.com") do |u|
      u.password = 'password123'
      u.role = Role.find_by(name: 'user')
    end
  end

  # Add realistic demo data using Faker if available
  if defined?(Faker)
    10.times do
      Project.create!(
        name: Faker::App.name,
        description: Faker::Lorem.paragraph,
        user: User.all.sample
      )
    end
  end

  puts "โœ… Test/demo data loaded"
end
```

**Automatic Seeding Behavior**:
- `./bin/dev-setup.sh` now runs `db:seed` automatically after `db:migrate`
- Seeds are idempotent (safe to run multiple times via `find_or_create_by!`)
- Environment-aware: Test/demo data only loads in development/test

### Phase 7: Start Development Server

**โšก AUTOMATIC SERVER STARTUP**: After completing the build, the skill automatically starts the development server.

```python
from scripts.allocate_ports import allocate_port, is_port_available, PORT_RANGES

# Smart port allocation to avoid conflicts with other running dev servers
rails_port = ports.get('rails', 3000)

# Check if allocated port is still available (another server may have started)
if not is_port_available(rails_port):
    # Find next available port in range
    rails_port = allocate_port(
        env_name=project_name,
        service='rails',
        start_port=PORT_RANGES['rails'][0],
        end_port=PORT_RANGES['rails'][1]
    )
    print(f"โš ๏ธ  Port conflict detected. Allocated new port: {rails_port}")

# Start the development server
subprocess.run(['./bin/dev-start.sh'], check=True)
```

**๐Ÿ”Œ PORT ALLOCATION SMART FEATURES** (Critical for avoiding conflicts):

1. **Unique Port Assignment**: Each environment gets its own port range allocation
2. **Conflict Detection**: Checks for running servers before starting
3. **Automatic Re-allocation**: Finds next available port if conflict detected
4. **Port Registry**: Maintains registry at `~/.rails-dev-env/port_allocations.json`
5. **Multi-Environment Support**: Run multiple projects simultaneously without conflicts

```bash
# Example: Running multiple projects
# Project A: Rails on 3000, PostgreSQL on 5432
# Project B: Rails on 3001, PostgreSQL on 5433
# Project C: Rails on 3002, PostgreSQL on 5434
```

**Server Startup Output**:
```
๐Ÿš€ Starting development server...
๐Ÿ“ Port allocation: Rails=3001, PostgreSQL=5433, Redis=6380
โšก Server ready at http://localhost:3001
```

### Phase 8: Display Getting Started Guide

After successful generation, show the user:

```markdown
## โœ… Rails Development Environment Created & Running

**Project:** {{ project_name }}
**Profile:** {{ profile }}
**Rails:** {{ rails_version }} | **Ruby:** {{ ruby_version }}

### ๐Ÿš€ Your Server is Already Running!

The development server started automatically after build completion.

**๐Ÿ”Œ Allocated Ports** (smart allocation avoids conflicts with other running servers):
- Rails: http://localhost:{{ ports.rails }}
{% if has_mailpit %}
- Mailpit: http://localhost:{{ ports.mailpit_web }}
{% endif %}
{% if has_playwright %}
- Playwright CDP: ws://localhost:{{ ports.playwright_cdp }}
{% endif %}
{% if has_selenium %}
- Selenium Hub: http://localhost:{{ ports.selenium }}
{% endif %}
{% if has_dozzle %}
- Logs: http://localhost:{{ ports.dozzle }}
{% endif %}

### ๐Ÿงช Database Pre-Populated

Your database has been initialized with:
- โœ… Production-critical data (roles, settings, configurations)
- โœ… Test/demo data (sample users, demo records)

Demo credentials: `admin@example.com` / `password123`

### ๐Ÿงช E2E Testing Ready (Standard+ Profile)

Browser automation is fully configured:
```bash
# Run system tests with Playwright
rails test:system

# Run with headed browser (visible)
HEADED=true rails test:system

# Run with Selenium
SELENIUM=true rails test:system
```

### Available Commands

| Command | Description |
|---------|-------------|
| `./bin/dev-start.sh` | Start all services |
| `./bin/dev-stop.sh` | Stop all services |
| `./bin/dev-status.sh` | Show service status & allocated ports |
| `./bin/dev-logs.sh` | View logs |
| `./bin/dev-reset.sh` | Reset environment (re-seeds database) |
| `./bin/dev-test.sh` | Run test suite including E2E tests |
| `./bin/dev-rollback.sh` | Backup/restore configuration |
```

---

## Workflow: Setup Existing Project

### Phase 1: Detect Project Configuration

```python
analysis = analyze_project(project_path)

if analysis.rails_version:
    info(f"Detected Rails {'.'.join(map(str, analysis.rails_version))}")
if analysis.ruby_version:
    info(f"Detected Ruby {analysis.ruby_version}")
if analysis.existing_docker:
    warn("Existing Docker configuration found")
    # Ask user about overwrite
```

### Phase 2: Confirm or Customize

If detection succeeds, confirm with user:
- Detected versions
- Recommended profile based on detected services
- Any existing Docker files to backup

### Phase 3-6: Same as New Environment

Follow steps from "New Environment" workflow.

---

## Custom Service Selection

For `--profile custom`, present service picker:

```yaml
questions:
  - question: "Which services do you need?"
    header: "Services"
    multiSelect: true
    options:
      - label: "PostgreSQL"
        description: "Primary database"
      - label: "Redis"
        description: "Caching, sessions, Action Cable"
      - label: "Sidekiq"
        description: "Background job processing"
      - label: "Mailpit"
        description: "Email testing"
      - label: "Browser Automation (Playwright + Selenium)"
        description: "Full E2E testing: Chromium, Firefox, WebKit, headed/headless modes"
      - label: "LocalStack"
        description: "AWS service mocking (S3, SQS, SNS)"
      - label: "WireMock"
        description: "API mocking"
      - label: "Dozzle"
        description: "Real-time log viewer"
```

---

## Error Handling

### Port Conflicts
```python
if not is_port_available(port):
    # Find next available port in range
    port = allocate_port(env_name, service, start, end)
```

### Existing Configuration
If `docker-compose.yml` exists:
1. Create backup: `docker-compose.yml.backup.{timestamp}`
2. Warn user about overwrite
3. Offer to merge or replace

### Version Mismatch
If detected version differs from requested:
```
โš ๏ธ Project uses Ruby 3.2.2 but 3.4.1 requested.
   Using detected version for compatibility.
```

### Rails 8.1 Ruby Requirement
```
โŒ ERROR: Rails 8.1.x requires Ruby 3.4+

   Rails 8.1 uses anonymous rest parameter syntax (`**`) which is only
   available in Ruby 3.4.0 and later. Ruby 3.3.x will fail with:

   syntax error, unexpected tPOW, expecting ')'
       def foo(**)
              ^~

   FIX: Update Ruby version to 3.4.1 or use Rails 8.0.x
```

---

## Reference Files

The skill uses these reference documents for decision making:

| File | Purpose |
|------|---------|
| `references/rails-ruby-matrix.md` | Version compatibility lookup |
| `references/service-catalog.md` | Service configuration details |
| `references/docker-templates.md` | Dockerfile patterns by Rails version |
| `references/profiles.md` | Profile definitions and resource estimates |
| `references/troubleshooting.md` | Common issues and solutions |

---

## Scripts API Reference

### `scripts/allocate_ports.py`
```python
allocate_port(env_name, service, start_port, end_port) -> int
release_ports(env_name) -> None
get_allocated_ports(env_name) -> Dict[str, int]
is_port_available(port) -> bool
cleanup_stale_allocations() -> int
```

### `scripts/detect_project.py`
```python
analyze_project(project_path) -> ProjectAnalysis
detect_rails_version(project_path) -> Optional[Tuple[int, int, int]]
detect_ruby_version(project_path) -> Optional[str]
detect_database_config(project_path) -> Dict
detect_services(project_path) -> List[str]
```

### `scripts/generate_templates.py`
```python
generate_all(config: EnvironmentConfig, output_path) -> GenerationResult
create_context(config) -> Dict[str, Any]
render_template(template_name, context) -> str
```

### `scripts/validate_environment.py`
```python
run_all_validations(project_path) -> ValidationReport
validate_compose_syntax(compose_path) -> ValidationResult
validate_ports(ports) -> ValidationResult
test_service_connectivity(service, host, port) -> bool
```

---

## Version History

| Version | Date | Changes |
|---------|------|---------|
| 1.1.0 | 2026-02-06 | **Major update**: Browser automation (Playwright + Selenium) now in Standard profile; automatic db:seed after build; automatic server startup with smart port allocation |
| 1.0.1 | 2026-02-04 | Updated defaults: Ruby 3.4.1, Rails 8.1; added /tmp/pids directory |
| 1.0.0 | 2026-02-03 | Initial release with full profile support |

---

## Troubleshooting Quick Reference

| Issue | Solution |
|-------|----------|
| Port already in use | Smart allocation auto-assigns next available port; check `./bin/dev-status.sh` |
| Database connection refused | Wait for health check or run `./bin/dev-start.sh` |
| Database missing seed data | Run `docker compose exec app rails db:seed` |
| Sidekiq not processing | Check Redis connection, verify queue configuration |
| Playwright tests fail | Ensure `PLAYWRIGHT_BROWSER_ENDPOINT` is set; check `./bin/dev-status.sh` |
| Selenium tests fail | Check `SELENIUM_HUB_URL`; ensure browsers are running |
| E2E tests timing out | Increase timeout or check browser container health |
| Headed browser not visible | Ensure VNC ports (7900-7999) are accessible |
| LocalStack services unavailable | Check `AWS_ENDPOINT_URL` points to LocalStack |
| Server didn't auto-start | Check for port conflicts; run `./bin/dev-start.sh` manually |

For detailed troubleshooting, see `references/troubleshooting.md`.

Signals

Avg ratingโญ 0.0
Reviews0
Favorites0

Information

Repository
arlenagreer/claude_configuration_docs
Author
arlenagreer
Last Sync
3/12/2026
Repo Updated
3/11/2026
Created
2/6/2026

Reviews (0)

No reviews yet. Be the first to review this skill!