Agent skill
rails-dev-environment
Install this agent skill to your Project
npx add-skill https://github.com/arlenagreer/claude_configuration_docs/tree/main/skills/rails-dev-environment
SKILL.md
Rails Development Environment Skill
Generates isolated, Dockerized Rails development environments with browser automation and service mocking.
Quick Start
# 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
/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
/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
/rails-dev-env validate
status - Show Environment Status
/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.mdfor 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:
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:
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
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
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
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.
# 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:
# 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.shnow runsdb:seedautomatically afterdb: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.
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):
- Unique Port Assignment: Each environment gets its own port range allocation
- Conflict Detection: Checks for running servers before starting
- Automatic Re-allocation: Finds next available port if conflict detected
- Port Registry: Maintains registry at
~/.rails-dev-env/port_allocations.json - Multi-Environment Support: Run multiple projects simultaneously without conflicts
# 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:
## โ
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:
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
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:
- Create backup:
docker-compose.yml.backup.{timestamp} - Warn user about overwrite
- 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
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
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
generate_all(config: EnvironmentConfig, output_path) -> GenerationResult
create_context(config) -> Dict[str, Any]
render_template(template_name, context) -> str
scripts/validate_environment.py
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.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
Send and draft professional emails with seasonal HTML formatting, authentic writing style, contact lookup via Google Contacts, security-first approach, and Google Gmail API via Ruby CLI. This skill should be used for ALL email operations (mandatory per RULES.md).
commit
Create detailed Git commits and push to GitHub. Use when the user wants to commit changes, save work to Git, or push updates to the repository. Trigger words include "commit", "save changes", "push to git", "update repository". (project, gitignored)
worklog
Track billable hours for clients. This skill should be used when the user requests to log work hours, record time spent on client projects, view worklog entries, calculate total billable hours, or summarize recent work. Automatically prompts for missing information (client, hours, description) and validates client names against the invoice skill's client database.
calendar
Manage Google Calendar with full event operations including viewing schedule, creating/editing/deleting events, finding free time, managing attendees via Google Contacts, adding Google Meet links, and timezone handling. This skill should be used for ALL calendar-related requests.
google-sheets
Manage Google Sheets with comprehensive spreadsheet operations including reading/writing cell values, formulas, formatting, sheet management, and batch operations. Use for spreadsheet data operations, cell ranges, formulas, formatting, batch updates, and data analysis workflows. Shares OAuth token with email, calendar, contacts, drive, and docs skills.
google-drive
Manage Google Drive files and folders with full CRUD operations via Ruby scripts. Use for file storage operations, folder organization, sharing permissions, searching across Drive, and uploading/downloading files of any type. Works seamlessly with google-sheets and google-docs skills for complete Google Workspace integration.
Didn't find tool you were looking for?