claude-on-rails 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/SETUP.md ADDED
@@ -0,0 +1,132 @@
1
+ # ClaudeOnRails Setup Guide
2
+
3
+ This guide covers the complete setup process for ClaudeOnRails, including the optional Rails MCP Server integration.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Add to your Gemfile
9
+ gem 'claude-on-rails', group: :development
10
+
11
+ # Install the gem
12
+ bundle install
13
+
14
+ # Generate swarm configuration (includes optional MCP setup)
15
+ rails generate claude_on_rails:swarm
16
+ # Press Y when prompted to set up Rails MCP Server!
17
+
18
+ # Start your AI development team
19
+ claude-swarm
20
+ ```
21
+
22
+ ## Enhanced Setup with Rails MCP Server
23
+
24
+ Rails MCP Server provides your AI agents with real-time access to Rails documentation. While optional, it significantly improves the quality and accuracy of generated code.
25
+
26
+ ### Automated Setup
27
+
28
+ The easiest way is during initial generation - just press Y when prompted!
29
+
30
+ If you skipped it or want to set it up later:
31
+
32
+ ```bash
33
+ bundle exec rake claude_on_rails:setup_mcp
34
+ ```
35
+
36
+ This interactive command will:
37
+ - Install the Rails MCP Server gem globally
38
+ - Configure your environment for enhanced documentation access
39
+
40
+ ### Manual Setup
41
+
42
+ If you prefer manual installation:
43
+
44
+ 1. **Install Rails MCP Server**
45
+ ```bash
46
+ gem install rails-mcp-server
47
+ ```
48
+
49
+ 2. **Regenerate Swarm Configuration**
50
+ ```bash
51
+ rails generate claude_on_rails:swarm
52
+ ```
53
+
54
+ ### Checking MCP Status
55
+
56
+ To verify your Rails MCP Server setup:
57
+
58
+ ```bash
59
+ bundle exec rake claude_on_rails:mcp_status
60
+ ```
61
+
62
+ This shows:
63
+ - Installation status
64
+ - Downloaded resources
65
+ - Missing resources
66
+
67
+ ## Configuration Options
68
+
69
+ ### Generator Options
70
+
71
+ ```bash
72
+ # Skip MCP Server integration
73
+ rails generate claude_on_rails:swarm --no-mcp-server
74
+
75
+ # API-only application
76
+ rails generate claude_on_rails:swarm --api-only
77
+
78
+ # Skip test agent
79
+ rails generate claude_on_rails:swarm --skip-tests
80
+
81
+ # Include GraphQL support
82
+ rails generate claude_on_rails:swarm --graphql
83
+ ```
84
+
85
+ ## Troubleshooting
86
+
87
+ ### Rails MCP Server Not Found
88
+
89
+ If the generator doesn't detect Rails MCP Server:
90
+
91
+ 1. Verify installation: `gem list rails-mcp-server`
92
+ 2. Check PATH: `which rails-mcp-server`
93
+ 3. Reinstall: `gem install rails-mcp-server`
94
+
95
+ ### Documentation Access
96
+
97
+ The Rails MCP Server gem includes built-in documentation for:
98
+ - Rails framework and guides
99
+ - Turbo and Stimulus frameworks
100
+ - Kamal deployment tool
101
+
102
+ No separate download steps are required!
103
+
104
+ ### Multiple Rails Projects
105
+
106
+ MCP Server resources are shared globally, benefiting all your Rails projects:
107
+
108
+ ```bash
109
+ # Install once
110
+ bundle exec rake claude_on_rails:setup_mcp
111
+
112
+ # Use in any Rails project
113
+ cd my-rails-app
114
+ rails generate claude_on_rails:swarm
115
+ ```
116
+
117
+ ## Getting Help
118
+
119
+ - Check status: `bundle exec rake claude_on_rails:mcp_status`
120
+ - View logs: `claude-swarm.log`
121
+ - Report issues: [GitHub Issues](https://github.com/obie/claude-on-rails/issues)
122
+ - Documentation: [README.md](./README.md)
123
+
124
+ ## Next Steps
125
+
126
+ After setup:
127
+
128
+ 1. Review generated `claude-swarm.yml`
129
+ 2. Customize agent prompts in `.claude-on-rails/prompts/`
130
+ 3. Start building with `claude-swarm`
131
+ 4. Describe features in natural language
132
+ 5. Let your AI team implement them!
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file exists to match the gem name for Rails autoloading
4
+ require 'claude_on_rails'
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ClaudeOnRails
2
4
  class Configuration
3
5
  attr_accessor :default_model, :vibe_mode, :session_directory, :log_directory
4
-
6
+
5
7
  def initialize
6
- @default_model = "opus"
8
+ @default_model = 'opus'
7
9
  @vibe_mode = true
8
- @session_directory = ".claude-on-rails/sessions"
9
- @log_directory = ".claude-on-rails/logs"
10
+ @session_directory = '.claude-on-rails/sessions'
11
+ @log_directory = '.claude-on-rails/logs'
10
12
  end
11
-
13
+
12
14
  def to_h
13
15
  {
14
16
  default_model: default_model,
@@ -18,4 +20,4 @@ module ClaudeOnRails
18
20
  }
19
21
  end
20
22
  end
21
- end
23
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClaudeOnRails
4
+ # Interactive installer for Rails MCP Server
5
+ class MCPInstaller
6
+ def run
7
+ puts "\e[32m🚀 ClaudeOnRails MCP Server Setup\e[0m"
8
+ puts "\e[32m#{'=' * 50}\e[0m"
9
+
10
+ if MCPSupport.available?
11
+ puts "\e[32m✓ Rails MCP Server is already installed\e[0m"
12
+ else
13
+ handle_installation
14
+ end
15
+
16
+ puts "\n\e[32m✅ Setup complete!\e[0m"
17
+ show_next_steps
18
+ end
19
+
20
+ private
21
+
22
+ def handle_installation
23
+ puts "\n\e[33mRails MCP Server provides your AI agents with:\e[0m"
24
+ puts "\e[36m • Real-time Rails documentation access\e[0m"
25
+ puts "\e[36m • Version-specific API references\e[0m"
26
+ puts "\e[36m • Framework guides (Turbo, Stimulus, Kamal)\e[0m"
27
+ puts "\e[36m • Best practices and examples\e[0m"
28
+
29
+ if prompt_yes_no?("\nWould you like to install Rails MCP Server? (Y/n)")
30
+ install_mcp_server
31
+ else
32
+ puts "\n\e[33mSkipping Rails MCP Server installation.\e[0m"
33
+ puts "\e[36mYou can run 'bundle exec rake claude_on_rails:setup_mcp' later to set it up.\e[0m"
34
+ end
35
+ end
36
+
37
+ def install_mcp_server
38
+ puts "\n\e[32mInstalling Rails MCP Server globally...\e[0m"
39
+
40
+ # Install without documentation to avoid RDoc conflicts
41
+ if system('gem install rails-mcp-server --no-document')
42
+ puts "\e[32m✓ Rails MCP Server installed successfully!\e[0m"
43
+ else
44
+ puts "\n\e[31m❌ Failed to install Rails MCP Server\e[0m"
45
+ puts "\e[33mPlease try running manually:\e[0m"
46
+ puts "\e[36m gem install rails-mcp-server --no-document\e[0m"
47
+ exit 1
48
+ end
49
+ end
50
+
51
+ def show_next_steps
52
+ puts "\n\e[33mNext steps:\e[0m"
53
+
54
+ if MCPSupport.available?
55
+ puts "\e[36m1. Run the swarm generator to update your configuration:\e[0m"
56
+ puts "\e[36m rails generate claude_on_rails:swarm\e[0m"
57
+ puts "\n\e[36m2. Start your enhanced Rails development swarm:\e[0m"
58
+ puts "\e[36m claude-swarm\e[0m"
59
+ puts "\n\e[32mYour AI agents now have access to Rails documentation! 🎉\e[0m"
60
+ else
61
+ puts "\e[36m1. Complete the MCP Server setup when ready:\e[0m"
62
+ puts "\e[36m bundle exec rake claude_on_rails:setup_mcp\e[0m"
63
+ puts "\n\e[36m2. Then run the swarm generator:\e[0m"
64
+ puts "\e[36m rails generate claude_on_rails:swarm\e[0m"
65
+ end
66
+
67
+ puts "\n\e[36mFor more information:\e[0m"
68
+ puts "\e[36m • Check status: bundle exec rake claude_on_rails:mcp_status\e[0m"
69
+ puts "\e[36m • View documentation: https://github.com/obie/claude-on-rails\e[0m"
70
+ end
71
+
72
+ def prompt_yes_no?(question)
73
+ print "\e[32m#{question} \e[0m"
74
+ response = $stdin.gets.chomp.downcase
75
+ response.empty? || response.start_with?('y')
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ClaudeOnRails
4
+ # Support module for Rails MCP Server integration
5
+ module MCPSupport
6
+ class << self
7
+ # Check if Rails MCP Server gem is available on the system
8
+ def available?
9
+ # Check if the gem is installed
10
+ system('gem list -i rails-mcp-server > /dev/null 2>&1') ||
11
+ # Also check if the executable is available
12
+ system('which rails-mcp-server > /dev/null 2>&1')
13
+ rescue StandardError
14
+ false
15
+ end
16
+
17
+ # Check if a specific resource is downloaded
18
+ def resource_available?(_resource_name)
19
+ # Rails MCP Server includes all resources in the gem
20
+ available?
21
+ end
22
+
23
+ # Get the MCP server configuration for swarm
24
+ def server_config(rails_env = 'development')
25
+ {
26
+ name: 'rails',
27
+ type: 'stdio',
28
+ command: 'rails-mcp-server',
29
+ args: [],
30
+ env: { 'RAILS_ENV' => rails_env }
31
+ }
32
+ end
33
+
34
+ # Check if we can download a resource (always true for gem-based server)
35
+ def download_resource?(_resource_name)
36
+ return false unless available?
37
+
38
+ # Rails MCP Server doesn't require separate resource downloads
39
+ # Documentation is built-in to the gem
40
+ true
41
+ end
42
+
43
+ # Get available resources that can be downloaded
44
+ def available_resources
45
+ %w[rails turbo stimulus kamal]
46
+ end
47
+
48
+ # Check which resources are currently downloaded
49
+ def downloaded_resources
50
+ # All resources are included in the gem
51
+ available? ? available_resources : []
52
+ end
53
+
54
+ # Check which resources are missing
55
+ def missing_resources
56
+ # No resources are missing if the gem is installed
57
+ available? ? [] : available_resources
58
+ end
59
+
60
+ # Check if common resources are set up
61
+ def common_resources_setup?
62
+ # No separate resource setup needed
63
+ available?
64
+ end
65
+
66
+ # Generate installation instructions
67
+ def installation_instructions
68
+ instructions = []
69
+
70
+ unless available?
71
+ instructions << "Install Rails MCP Server:"
72
+ instructions << " gem install rails-mcp-server --no-document"
73
+ instructions << ""
74
+ end
75
+
76
+ instructions
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,159 +1,147 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ClaudeOnRails
2
4
  class ProjectAnalyzer
3
5
  attr_reader :root_path
4
-
6
+
5
7
  def initialize(root_path)
6
8
  @root_path = root_path
7
9
  end
8
-
10
+
9
11
  def analyze
10
12
  {
11
13
  api_only: api_only?,
12
14
  test_framework: detect_test_framework,
13
- has_graphql: has_graphql?,
14
- has_turbo: has_turbo?,
15
- has_devise: has_devise?,
16
- has_sidekiq: has_sidekiq?,
15
+ has_graphql: graphql?,
16
+ has_turbo: turbo?,
17
+ has_devise: devise?,
18
+ has_sidekiq: sidekiq?,
17
19
  javascript_framework: detect_javascript_framework,
18
20
  database: detect_database,
19
21
  deployment: detect_deployment_method,
20
22
  custom_patterns: detect_custom_patterns
21
23
  }
22
24
  end
23
-
25
+
24
26
  private
25
-
27
+
26
28
  def api_only?
27
29
  application_rb = File.join(root_path, 'config', 'application.rb')
28
30
  return false unless File.exist?(application_rb)
29
-
31
+
30
32
  File.read(application_rb).include?('config.api_only = true')
31
33
  end
32
-
34
+
33
35
  def detect_test_framework
34
36
  if File.exist?(File.join(root_path, 'spec'))
35
37
  'RSpec'
36
38
  elsif File.exist?(File.join(root_path, 'test'))
37
39
  'Minitest'
38
- else
39
- nil
40
40
  end
41
41
  end
42
-
43
- def has_graphql?
42
+
43
+ def graphql?
44
44
  gemfile_path = File.join(root_path, 'Gemfile')
45
45
  return false unless File.exist?(gemfile_path)
46
-
46
+
47
47
  gemfile_content = File.read(gemfile_path)
48
- gemfile_content.include?('graphql') ||
48
+ gemfile_content.include?('graphql') ||
49
49
  File.exist?(File.join(root_path, 'app', 'graphql'))
50
50
  end
51
-
52
- def has_turbo?
51
+
52
+ def turbo?
53
53
  gemfile_path = File.join(root_path, 'Gemfile')
54
54
  return false unless File.exist?(gemfile_path)
55
-
55
+
56
56
  gemfile_content = File.read(gemfile_path)
57
- gemfile_content.include?('turbo-rails') ||
57
+ gemfile_content.include?('turbo-rails') ||
58
58
  gemfile_content.include?('stimulus-rails') ||
59
59
  File.exist?(File.join(root_path, 'app', 'javascript', 'controllers'))
60
60
  end
61
-
62
- def has_devise?
61
+
62
+ def devise?
63
63
  gemfile_path = File.join(root_path, 'Gemfile')
64
64
  return false unless File.exist?(gemfile_path)
65
-
65
+
66
66
  File.read(gemfile_path).include?('devise')
67
67
  end
68
-
69
- def has_sidekiq?
68
+
69
+ def sidekiq?
70
70
  gemfile_path = File.join(root_path, 'Gemfile')
71
71
  return false unless File.exist?(gemfile_path)
72
-
72
+
73
73
  File.read(gemfile_path).include?('sidekiq')
74
74
  end
75
-
75
+
76
76
  def detect_javascript_framework
77
77
  package_json = File.join(root_path, 'package.json')
78
78
  return 'importmap' unless File.exist?(package_json)
79
-
79
+
80
80
  content = File.read(package_json)
81
- case
82
- when content.include?('webpack')
81
+ if content.include?('webpack')
83
82
  'webpack'
84
- when content.include?('esbuild')
83
+ elsif content.include?('esbuild')
85
84
  'esbuild'
86
- when content.include?('vite')
85
+ elsif content.include?('vite')
87
86
  'vite'
88
87
  else
89
88
  'importmap'
90
89
  end
91
90
  end
92
-
91
+
93
92
  def detect_database
94
93
  database_yml = File.join(root_path, 'config', 'database.yml')
95
94
  return 'sqlite3' unless File.exist?(database_yml)
96
-
95
+
97
96
  content = File.read(database_yml)
98
- case
99
- when content.include?('postgresql')
97
+ if content.include?('postgresql')
100
98
  'postgresql'
101
- when content.include?('mysql2')
99
+ elsif content.include?('mysql2')
102
100
  'mysql'
103
- when content.include?('sqlite3')
101
+ elsif content.include?('sqlite3')
104
102
  'sqlite3'
105
103
  else
106
104
  'unknown'
107
105
  end
108
106
  end
109
-
107
+
110
108
  def detect_deployment_method
111
109
  # Check for various deployment configurations
112
110
  return 'kubernetes' if File.exist?(File.join(root_path, 'k8s')) ||
113
- File.exist?(File.join(root_path, 'kubernetes'))
111
+ File.exist?(File.join(root_path, 'kubernetes'))
114
112
  return 'docker' if File.exist?(File.join(root_path, 'Dockerfile'))
115
113
  return 'capistrano' if File.exist?(File.join(root_path, 'Capfile'))
116
114
  return 'heroku' if File.exist?(File.join(root_path, 'Procfile'))
117
115
  return 'kamal' if File.exist?(File.join(root_path, 'config', 'deploy.yml'))
118
-
116
+
119
117
  'unknown'
120
118
  end
121
-
119
+
122
120
  def detect_custom_patterns
123
121
  patterns = {}
124
-
122
+
125
123
  # Check for service objects
126
- if File.directory?(File.join(root_path, 'app', 'services'))
127
- patterns[:has_services] = true
128
- end
129
-
124
+ patterns[:has_services] = true if File.directory?(File.join(root_path, 'app', 'services'))
125
+
130
126
  # Check for form objects
131
- if File.directory?(File.join(root_path, 'app', 'forms'))
132
- patterns[:has_forms] = true
133
- end
134
-
127
+ patterns[:has_forms] = true if File.directory?(File.join(root_path, 'app', 'forms'))
128
+
135
129
  # Check for presenters/decorators
136
130
  if File.directory?(File.join(root_path, 'app', 'presenters')) ||
137
131
  File.directory?(File.join(root_path, 'app', 'decorators'))
138
132
  patterns[:has_presenters] = true
139
133
  end
140
-
134
+
141
135
  # Check for query objects
142
- if File.directory?(File.join(root_path, 'app', 'queries'))
143
- patterns[:has_queries] = true
144
- end
145
-
136
+ patterns[:has_queries] = true if File.directory?(File.join(root_path, 'app', 'queries'))
137
+
146
138
  # Check for policies (authorization)
147
- if File.directory?(File.join(root_path, 'app', 'policies'))
148
- patterns[:has_policies] = true
149
- end
150
-
139
+ patterns[:has_policies] = true if File.directory?(File.join(root_path, 'app', 'policies'))
140
+
151
141
  # Check for serializers
152
- if File.directory?(File.join(root_path, 'app', 'serializers'))
153
- patterns[:has_serializers] = true
154
- end
155
-
142
+ patterns[:has_serializers] = true if File.directory?(File.join(root_path, 'app', 'serializers'))
143
+
156
144
  patterns
157
145
  end
158
146
  end
159
- end
147
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+
5
+ module ClaudeOnRails
6
+ # Railtie to load rake tasks in Rails applications
7
+ class Railtie < Rails::Railtie
8
+ rake_tasks do
9
+ load File.expand_path('../tasks/claude_on_rails.rake', __dir__)
10
+ end
11
+ end
12
+ end