Class: RailsAiBridge::Generators::InstallGenerator
- Inherits:
-
Rails::Generators::Base
- Object
- Rails::Generators::Base
- RailsAiBridge::Generators::InstallGenerator
- Includes:
- CommandHelp
- Defined in:
- lib/generators/rails_ai_bridge/install/install_generator.rb
Instance Method Summary collapse
-
#add_to_gitignore ⇒ void
Appends rails-ai-bridge-specific entries to .gitignore when the file exists and the entries are not already present.
-
#create_assistant_overrides_template ⇒ void
Creates the config/rails_ai_bridge/ directory with an overrides.md stub and an overrides.md.example reference file.
-
#create_initializer ⇒ void
Creates config/initializers/rails_ai_bridge.rb containing a commented configuration guide for rails-ai-bridge.
-
#create_mcp_config ⇒ void
Creates a
.mcp.jsonMCP server definition named "rails-ai-bridge". -
#generate_context_files ⇒ void
Calls RailsAiBridge.generate_context to write initial bridge files (CLAUDE.md, .cursorrules, etc.) according to the selected install profile.
-
#show_instructions ⇒ void
Prints post-install usage instructions to stdout: available rake tasks, generated file locations per AI assistant, MCP auto-discovery notes, and bridge mode options.
Methods included from CommandHelp
Instance Method Details
#add_to_gitignore ⇒ void
This method returns an undefined value.
Appends rails-ai-bridge-specific entries to .gitignore when the file exists and the entries are not already present. Does nothing if .gitignore is absent. Uses Thor's #append_to_file so the operation respects +--pretend+ (dry-run).
233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 233 def add_to_gitignore gitignore_path = '.gitignore' gitignore_full = File.join(destination_root, gitignore_path) return unless File.exist?(gitignore_full) content = File.read(gitignore_full) append = [] append << '.ai-context.json' unless content.include?('.ai-context.json') return unless append.any? append_to_file gitignore_path, "\n# rails-ai-bridge (JSON cache — markdown files should be committed)\n#{append.join("\n")}\n" say 'Updated .gitignore', :green end |
#create_assistant_overrides_template ⇒ void
This method returns an undefined value.
Creates the config/rails_ai_bridge/ directory with an overrides.md stub and an overrides.md.example reference file. Skips each file if it already exists so the method is safe to re-run (idempotent).
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 207 def create_assistant_overrides_template dir = 'config/rails_ai_bridge' empty_directory dir stub = File.join(destination_root, dir, 'overrides.md') unless File.exist?(stub) create_file "#{dir}/overrides.md", <<~MD <!-- rails-ai-bridge:omit-merge --> MD say "Created #{dir}/overrides.md (stub — remove omit-merge line when adding real rules)", :green end example = File.join(destination_root, dir, 'overrides.md.example') return if File.exist?(example) copy_file 'overrides.md.example', "#{dir}/overrides.md.example" say "Created #{dir}/overrides.md.example (reference outline, not merged)", :green end |
#create_initializer ⇒ void
This method returns an undefined value.
Creates config/initializers/rails_ai_bridge.rb containing a commented configuration guide for rails-ai-bridge. The generated initializer documents introspector presets (with interpolated counts), options for enabling/disabling introspectors, security exclusions (tables, models, paths), primary domain model hints, context/output controls, assistant override guidance, and a SECURITY CRITICAL HTTP MCP / auto_mount section with recommended authentication approaches.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 48 def create_initializer standard_count = RailsAiBridge::Configuration::PRESETS[:standard].size full_count = RailsAiBridge::Configuration::PRESETS[:full].size regulated_count = RailsAiBridge::Configuration::PRESETS[:regulated].size create_file 'config/initializers/rails_ai_bridge.rb', <<~RUBY # frozen_string_literal: true # rails-ai-bridge configuration # All settings are commented out — uncomment only what you need to change. # Defaults are production-safe: read-only introspection, no HTTP exposure. # Run `rails ai:doctor` after changes to verify your setup. RailsAiBridge.configure do |config| # --------------------------------------------------------------------------- # Introspector preset # --------------------------------------------------------------------------- # Controls how much of your app is introspected when generating context files # and answering MCP tool requests. # # :standard (default) — #{standard_count} core introspectors covering the essentials: # schema, models, routes, controllers, jobs, gems, conventions, tests, migrations # Best for most apps. Fast and focused. # # :full — all #{full_count} introspectors (everything in :standard plus): # views, Turbo/Stimulus, auth, API serializers, config, assets, DevOps # Use for full-stack Hotwire apps or when AI needs frontend/auth/API context. # # :regulated — #{regulated_count} introspectors — omits schema, models, and migrations. # Use for apps with strict data governance where schema must not be exposed. # # config.preset = :standard # already the default — uncomment only to switch # Add individual introspectors on top of the preset (does not change the preset): # Effect: each listed symbol enables one additional introspector. # config.introspectors += %i[non_ar_models views turbo auth api database_stats] # # database_stats: adds small/medium/large/hot hints to table context using # PostgreSQL table statistics. Opt-in because it queries the DB at introspection time. # Disable a whole category at runtime (overrides preset and individual additions): # :domain_metadata disables schema + models + migrations + non_ar_models # config.disabled_introspection_categories << :domain_metadata # --------------------------------------------------------------------------- # Security exclusions # --------------------------------------------------------------------------- # These settings control what gets included in generated context files and # MCP tool responses. Excluded items are silently omitted — not replaced. # Tables to hide from schema introspection and model output. # Accepts exact table names or globs ("pii_*" matches pii_users, pii_logs, etc.) # Effect: excluded tables disappear from rails_get_schema and model details. # config.excluded_tables += %w[secrets audit_logs pii_*] # ActiveRecord models to exclude from introspection. # Effect: excluded models are not listed in any generated context file or MCP response. # config.excluded_models += %w[AdminUser InternalAuditLog] # Paths excluded from rails_search_code results. # Effect: files under these paths are skipped in code search results. # config.excluded_paths += %w[vendor/bundle node_modules] # --------------------------------------------------------------------------- # Domain model hints # --------------------------------------------------------------------------- # Mark your primary business models as core_entity. This affects: # - Ordering in generated context files (core models listed first) # - Semantic tier in rails_get_model_details responses ("core_entity") # - .claude/rules/rails-models.md (tagged for Claude Code) # Effect: these models get promoted in AI context. Use your 3-7 most central models. # config.core_models += %w[User Order Project] # --------------------------------------------------------------------------- # Context output # --------------------------------------------------------------------------- # Controls how much detail goes into generated static files (CLAUDE.md, AGENTS.md, etc.) # # :compact (default) — ≤150 lines per file. Key models and routes are listed; # everything else is referenced via MCP tools. Suitable for large apps. # The AI asks MCP for details on demand — no context bloat. # # :full — dumps everything into the static files. No MCP needed for orientation, # but files can be large. Best for small apps with fewer than ~30 models. # # config.context_mode = :compact # already the default # Max lines for CLAUDE.md in compact mode (default: 150): # config.claude_max_lines = 150 # Safety cap for MCP tool responses in characters (default: 120_000): # Oversized responses are truncated with a hint to use filters or pagination. # config.max_tool_response_chars = 120_000 # Team-specific rules merged into Copilot and Codex output. # Effect: content of overrides.md is appended to .github/copilot-instructions.md # and AGENTS.md on each `rails ai:bridge` run. # IMPORTANT: Remove the first-line "<!-- rails-ai-bridge:omit-merge -->" guard # from config/rails_ai_bridge/overrides.md before this has any effect. # config.assistant_overrides_path = "config/rails_ai_bridge/overrides.md" # Model list size caps for compact output (0 = show no names, only MCP pointer): # Reduce these for apps with large model counts to keep files within size limits. # config.copilot_compact_model_list_limit = 15 # default # config.codex_compact_model_list_limit = 15 # default # ========================================================================== # HTTP MCP / auto_mount — SECURITY CRITICAL # ========================================================================== # By default, MCP runs only via stdio (`rails ai:serve`), which is local-only # and safe. The HTTP transport is an opt-in alternative for clients that cannot # spawn sub-processes (e.g. browser-based AI tools, remote agents). # # Even though tools are read-only, the HTTP endpoint exposes routes, schema, # and code structure. Treat it as an internal service — keep it on localhost # unless you add authentication AND network controls. # # To enable HTTP MCP locally (development only): # config.auto_mount = true # config.http_path = "/mcp" # endpoint path # config.http_bind = "127.0.0.1" # localhost only # Then start your Rails server and point your AI client to http://localhost:3000/mcp # # For production, you MUST also set allow_auto_mount_in_production = true AND # configure one of these auth mechanisms (highest priority first): # # 1. JWT decoder (bring your own JWT gem): # config.mcp_jwt_decoder = ->(token) { # JWT.decode(token, credentials.jwt_secret, true, algorithm: "HS256").first # rescue JWT::DecodeError, JWT::ExpiredSignature, JWT::ImmatureSignature # nil # } # # 2. Token resolver (Devise, database lookup, etc.): # config.mcp_token_resolver = ->(token) { User.find_by(mcp_api_token: token) } # # 3. Static shared secret (simplest — fine for internal tools): # config.http_mcp_token = "generate-a-long-random-secret" # # ENV["RAILS_AI_BRIDGE_MCP_TOKEN"] takes precedence when set # # Timing-safe token comparison is built in, but add rate limiting too # (e.g. Rack::Attack throttle on config.http_path) to prevent brute-force. # # config.auto_mount = false # config.allow_auto_mount_in_production = false # config.http_path = "/mcp" # config.http_port = 6029 end RUBY say 'Created config/initializers/rails_ai_bridge.rb', :green end |
#create_mcp_config ⇒ void
This method returns an undefined value.
Creates a .mcp.json MCP server definition named "rails-ai-bridge".
The created file configures an MCP server that runs bundle exec rails ai:serve and is intended
for auto-discovery by tools such as Claude Code and Cursor.
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 26 def create_mcp_config mcp_config = { mcpServers: { 'rails-ai-bridge' => { command: 'bundle', args: ['exec', 'rails', 'ai:serve'] } } } create_file '.mcp.json', "#{JSON.pretty_generate(mcp_config)}\n" say 'Created .mcp.json (auto-discovered by Claude Code, Cursor, etc.)', :green end |
#generate_context_files ⇒ void
This method returns an undefined value.
Calls RailsAiBridge.generate_context to write initial bridge files (CLAUDE.md, .cursorrules, etc.) according to the selected install profile. Skipped when +Rails.application+ is not available. Any StandardError is rescued and reported with the error class only — no raw message or sensitive path/credential details are printed or logged. +Rails.logger.debug+ receives only the exception class name and a short 12-character fingerprint derived from it, never the raw exception message.
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 257 def generate_context_files say '' say 'Generating AI bridge files...', :yellow return handle_skip_context if [:skip_context] return handle_no_rails_app unless Rails.application begin profile = resolve_profile rescue ArgumentError say ' Run `rails generate rails_ai_bridge:install --profile=minimal` (or full/custom/mcp).', :yellow return end @selected_profile = profile case profile when 'mcp' say ' Skipped (MCP-only profile). Run `rails ai:bridge` to generate context files later.', :yellow return when 'minimal', 'full' formats = ProfileResolver.formats_for(profile) split_rules = ProfileResolver.split_rules_for(profile) return generate_context_for_formats(formats, split_rules: split_rules) end return say(' Skipped. Run `rails ai:bridge` to generate context files later.', :yellow) unless yes?('Generate AI assistant context files? (y/n)') formats = collect_selected_formats return say(' No formats selected. Run `rails ai:bridge` to generate context files later.', :yellow) if formats.empty? generate_context_for_formats(formats, split_rules: true) end |
#show_instructions ⇒ void
This method returns an undefined value.
Prints post-install usage instructions to stdout: available rake tasks, generated file locations per AI assistant, MCP auto-discovery notes, and bridge mode options.
295 296 297 298 299 |
# File 'lib/generators/rails_ai_bridge/install/install_generator.rb', line 295 def show_instructions return show_skip_context_instructions if [:skip_context] show_full_instructions end |