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 | 4 GB | 6 GB | Most web applications |
| full | standard + localstack, wiremock, playwright, dozzle | 6 GB | 8+ GB | Enterprise, complex integrations |
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"
- label: "Minimal"
description: "Rails, PostgreSQL, Redis only"
- label: "Full"
description: "All services including AWS mocking, API mocking, browser automation"
- 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:
| Service | Range |
|---|---|
| rails | 3000-3099 |
| postgres | 5432-5499 |
| redis | 6379-6399 |
| mailpit_web | 8025-8049 |
| mailpit_smtp | 1025-1049 |
| playwright_cdp | 9222-9299 |
| localstack | 4566-4599 |
| wiremock | 8080-8099 |
| dozzle | 9999-9999 |
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: Display Getting Started Guide
After successful generation, show the user:
## ✅ Rails Development Environment Created
**Project:** {{ project_name }}
**Profile:** {{ profile }}
**Rails:** {{ rails_version }} | **Ruby:** {{ ruby_version }}
### Quick Start
1. **Initial Setup:**
```bash
cd {{ project_path }}
chmod +x bin/dev-*.sh
./bin/dev-setup.sh
- •
Start Services:
bash./bin/dev-start.sh
- •
Access Your App:
- •Rails: http://localhost:{{ ports.rails }} {% if has_mailpit %}
- •Mailpit: http://localhost:{{ ports.mailpit_web }} {% endif %} {% if has_dozzle %}
- •Logs: http://localhost:{{ ports.dozzle }} {% endif %}
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 |
./bin/dev-logs.sh | View logs |
./bin/dev-reset.sh | Reset environment |
./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: "LocalStack"
description: "AWS service mocking (S3, SQS, SNS)"
- label: "WireMock"
description: "API mocking"
- label: "Playwright"
description: "Browser automation for system tests"
- 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.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 | Run ./bin/dev-status.sh to check, use --force flag |
| Database connection refused | Wait for health check or run ./bin/dev-start.sh |
| Sidekiq not processing | Check Redis connection, verify queue configuration |
| Playwright tests fail | Ensure PLAYWRIGHT_BROWSER_ENDPOINT is set |
| LocalStack services unavailable | Check AWS_ENDPOINT_URL points to LocalStack |
For detailed troubleshooting, see references/troubleshooting.md.