rails-ai-context 5.32.0 → 5.32.2

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +138 -0
  3. data/CONTEXT.md +10 -8
  4. data/CONTRIBUTING.md +2 -2
  5. data/README.md +14 -11
  6. data/SECURITY.md +4 -4
  7. data/docs/ARCHITECTURE.md +11 -10
  8. data/docs/CLI.md +33 -7
  9. data/docs/COMPATIBILITY.md +69 -32
  10. data/docs/CONFIGURATION.md +10 -8
  11. data/docs/CUSTOM_TOOLS.md +8 -8
  12. data/docs/FAQ.md +6 -5
  13. data/docs/GUIDE.md +154 -80
  14. data/docs/INTROSPECTORS.md +25 -17
  15. data/docs/QUICKSTART.md +14 -3
  16. data/docs/RECIPES.md +50 -40
  17. data/docs/SECURITY.md +23 -13
  18. data/docs/SETUP.md +23 -26
  19. data/docs/STANDALONE.md +7 -3
  20. data/docs/TOOLS.md +79 -45
  21. data/docs/TROUBLESHOOTING.md +12 -11
  22. data/exe/rails-ai-context +8 -4
  23. data/lib/generators/rails_ai_context/install/install_generator.rb +1 -1
  24. data/lib/rails_ai_context/configuration.rb +2 -2
  25. data/lib/rails_ai_context/database_yml.rb +52 -2
  26. data/lib/rails_ai_context/install/ai_tool.rb +11 -2
  27. data/lib/rails_ai_context/install/cleanup.rb +69 -23
  28. data/lib/rails_ai_context/install/program.rb +4 -1
  29. data/lib/rails_ai_context/install/selection_record.rb +20 -2
  30. data/lib/rails_ai_context/introspectors/listeners/schema_dsl_listener.rb +30 -9
  31. data/lib/rails_ai_context/introspectors/model_introspector.rb +1 -1
  32. data/lib/rails_ai_context/introspectors/pg_naming.rb +133 -0
  33. data/lib/rails_ai_context/introspectors/schema_conventions.rb +0 -6
  34. data/lib/rails_ai_context/introspectors/schema_introspector.rb +188 -51
  35. data/lib/rails_ai_context/introspectors/schema_reader.rb +98 -12
  36. data/lib/rails_ai_context/introspectors/structure_sql_reader.rb +56 -33
  37. data/lib/rails_ai_context/payload.rb +25 -2
  38. data/lib/rails_ai_context/serializers/opencode_rules_serializer.rb +2 -2
  39. data/lib/rails_ai_context/server.rb +2 -2
  40. data/lib/rails_ai_context/tasks/rails_ai_context.rake +12 -4
  41. data/lib/rails_ai_context/test_helper.rb +2 -0
  42. data/lib/rails_ai_context/tools/base_tool.rb +3 -1
  43. data/lib/rails_ai_context/tools/dependency_graph.rb +2 -2
  44. data/lib/rails_ai_context/tools/get_concern.rb +1 -1
  45. data/lib/rails_ai_context/tools/get_env.rb +1 -1
  46. data/lib/rails_ai_context/tools/get_gems.rb +2 -2
  47. data/lib/rails_ai_context/tools/get_model_details.rb +2 -0
  48. data/lib/rails_ai_context/tools/get_schema.rb +17 -14
  49. data/lib/rails_ai_context/tools/query.rb +107 -39
  50. data/lib/rails_ai_context/tools/search_code.rb +20 -16
  51. data/lib/rails_ai_context/version.rb +1 -1
  52. data/server.json +1 -1
  53. metadata +2 -1
data/docs/GUIDE.md CHANGED
@@ -40,11 +40,11 @@
40
40
  - [Generated Files](#generated-files)
41
41
  - [All Commands](#all-commands)
42
42
  - [CLI Tools](#cli-tools)
43
- - [MCP Tools - Common Reference](#mcp-tools--common-reference)
43
+ - [MCP Tools - Common Reference](#mcp-tools---common-reference)
44
44
  - [MCP Resources](#mcp-resources)
45
45
  - [MCP Server Setup](#mcp-server-setup)
46
- - [Configuration - All Options](#configuration--all-options)
47
- - [Introspectors - Full List](#introspectors--full-list)
46
+ - [Configuration - All Options](#configuration---all-options)
47
+ - [Introspectors - Full List](#introspectors---full-list)
48
48
  - [AI Assistant Setup](#ai-assistant-setup)
49
49
  - [Stack Compatibility](#stack-compatibility)
50
50
  - [Diagnostics](#diagnostics)
@@ -89,12 +89,49 @@ No Gemfile entry, no initializer, no files in your project besides config and co
89
89
 
90
90
  ### What the install generator does
91
91
 
92
- 1. Creates per-tool MCP config files (`.mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `opencode.json`, `.codex/config.toml`)
93
- 2. Creates `config/initializers/rails_ai_context.rb` with commented defaults
94
- 3. Asks which AI tools you use (Claude, Cursor, Copilot, OpenCode, Codex)
95
- 4. Asks whether to enable MCP server (`tool_mode: :mcp`) or use CLI-only mode (`tool_mode: :cli`)
96
- 5. Adds `.ai-context.json` to `.gitignore` (JSON cache - markdown files should be committed)
97
- 6. Generates all context files
92
+ `rails generate rails_ai_context:install` runs these steps in this order. Steps 1, 2, 3, 8 and 9 can ask a question.
93
+
94
+ 1. **Asks which AI tools you use.** It prints this menu, then `Enter numbers separated by commas (e.g. 1,2) or 'a' for all:`
95
+
96
+ ```
97
+ 1. Claude Code -> CLAUDE.md + .claude/rules/
98
+ 2. Cursor -> .cursor/rules/ + .cursorrules (legacy fallback)
99
+ 3. GitHub Copilot -> .github/copilot-instructions.md + .github/instructions/
100
+ 4. OpenCode -> AGENTS.md
101
+ 5. Codex CLI -> AGENTS.md + .codex/config.toml
102
+ a. All of the above
103
+ ```
104
+
105
+ There is no "none" choice. An empty answer, or one with no valid number in it, prints `No tools selected - defaulting to all.` and selects all five.
106
+ 2. **Offers to clean up tools you dropped.** Only on a re-run, and only when the last recorded selection (the `config.ai_tools` line in the initializer, else `.rails-ai-context.yml`) has a tool you did not pick this time. It lists them and asks `Remove their generated files?` with `y` (all), `n` (keep, the default) or numbers like `1,2`. A yes removes only what the gem generated: the rule files it names inside the tool's rules directory (the directory goes too when nothing else is left in it), and the block between the `rails-ai-context` markers in a root file such as `CLAUDE.md`. A rule file you wrote by hand, your own lines around the markers, a root file with no markers and a symlink are left alone. It also keeps any file a remaining tool shares (`AGENTS.md`), and takes only the `rails-ai-context` entry out of the tool's MCP config.
107
+ 3. **Asks what to write**, then `Enter number (default: 1):`
108
+
109
+ ```
110
+ 1. MCP config + context files (default)
111
+ 2. Context files only (CLI mode, no MCP server)
112
+ 3. MCP config only (leaves CLAUDE.md, AGENTS.md and rules untouched)
113
+ ```
114
+
115
+ Choices 1 and 3 set `tool_mode` to `:mcp`, choice 2 sets it to `:cli`. Choice 3 also sets `context_files` to `false`. Any other answer counts as 1.
116
+ 4. **Writes the MCP config for each selected tool** (`.mcp.json`, `.cursor/mcp.json`, `.vscode/mcp.json`, `opencode.json`, `.codex/config.toml`). Skipped for choice 2. An existing file is merged: only the `rails-ai-context` entry is added or replaced.
117
+ 5. **Creates or updates `config/initializers/rails_ai_context.rb`.** A new file gets your three answers as live lines (`config.ai_tools`, `config.tool_mode`, `config.context_files`) and every other option commented out at its default, wrapped in `if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)`. In an existing file it rewrites those three lines, appends any config section the file lacks, adds the guard if it is missing, and leaves the rest alone.
118
+ 6. **Writes `.rails-ai-context.yml`** with `ai_tools`, `tool_mode` and `context_files`. Other keys already in the file are kept.
119
+ 7. **Adds lines to `.gitignore`**, if the file exists: `.ai-context.json` (not for choice 3) and `.codex/config.toml` (always, because it holds this machine's Ruby paths). A line that is already there is not added again.
120
+ 8. **Asks about a pre-commit hook:** `Install a pre-commit hook that validates Rails references? (y/N)`. Only `y` installs it. The hook runs `rails 'ai:tool[validate]'` on the staged `.rb` and `.erb` files. No question is asked when the app has no `.git` directory or when the hook is already installed. When another `.git/hooks/pre-commit` exists it prints `Skipped pre-commit hook (existing hook found - add manually)` and moves on.
121
+ 9. **Generates the context files** for the selected tools. Skipped for choice 3. If files that v5.0.0 stopped generating are still there (`.claude/rules/rails-ui-patterns.md`, `.claude/rules/rails-accessibility.md`, `.cursor/rules/rails-ui-patterns.mdc`, `.github/instructions/rails-ui-patterns.instructions.md`), it lists them first and asks `Delete them? [y/N]:`. Without a terminal, or under `--defaults`, it prints the `rm` command and does not ask.
122
+ 10. **Prints a summary:** the files each selected tool got and the commands to run next.
123
+
124
+ Two flags change the prompts:
125
+
126
+ - `--defaults` answers every prompt with its default: all five tools, keep dropped tools' files, choice 1, no hook, keep legacy files. Piping an empty stdin does the same.
127
+ - `--mcp-only` skips the step 3 question and acts as choice 3. Steps 1, 2 and 8 still ask.
128
+
129
+ A team that wants no AI tool files in the repo can skip the generator. The gem needs none of its output: `rails 'ai:tool[NAME]'`, `rails ai:serve`, `rails ai:doctor` and the `rails-ai-context` binary all work on the defaults with no initializer, no `.rails-ai-context.yml` and no MCP config. `rails ai:context` is the one to leave alone in that setup, since it writes context files. To make that safe too, set `config.ai_tools = []` in an initializer: an empty list means no tool, so nothing is written and nothing is asked.
130
+
131
+ Two other entry points ask the same step 1 and step 3 questions:
132
+
133
+ - `rails-ai-context init` (standalone) asks both, then offers the step 2 and step 9 cleanups, writes `.rails-ai-context.yml`, the MCP configs and the `.gitignore` lines, and generates the context files. On an MCP-only run it skips the step 9 question, as the generator does. It never creates the initializer (in one that exists it updates `config.ai_tools`, `config.tool_mode` and `config.context_files`), never offers the pre-commit hook, and has `--mcp-only` but no `--defaults`.
134
+ - `rails ai:context` asks step 1 only when no tool selection is recorded, and step 3 only when no `tool_mode` is recorded. It then writes `.rails-ai-context.yml`, the MCP configs and the `.gitignore` lines before generating. It does not create the initializer or offer the hook.
98
135
 
99
136
  ---
100
137
 
@@ -123,7 +160,7 @@ rails ai:context:full
123
160
  CONTEXT_MODE=full rails ai:context
124
161
  ```
125
162
 
126
- - Dumps everything into context files (schema, all models, all routes, etc.)
163
+ - Dumps everything into the root files CLAUDE.md, AGENTS.md and copilot-instructions.md (schema, all models, all routes, etc.). The split rule files and Cursor's files are the same in both modes
127
164
  - Can produce thousands of lines for large apps
128
165
  - **Best for:** small apps (<30 models) where the full dump fits in context
129
166
 
@@ -133,9 +170,6 @@ CONTEXT_MODE=full rails ai:context
133
170
  # Full dump for Claude only, compact for everything else
134
171
  CONTEXT_MODE=full rails ai:context:claude
135
172
 
136
- # Full dump for Cursor only
137
- CONTEXT_MODE=full rails ai:context:cursor
138
-
139
173
  # Full dump for Copilot only
140
174
  CONTEXT_MODE=full rails ai:context:copilot
141
175
  ```
@@ -144,7 +178,7 @@ CONTEXT_MODE=full rails ai:context:copilot
144
178
 
145
179
  ```ruby
146
180
  # config/initializers/rails_ai_context.rb
147
- if defined?(RailsAiContext)
181
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
148
182
  RailsAiContext.configure do |config|
149
183
  config.context_mode = :full # or :compact (default)
150
184
  end
@@ -229,7 +263,7 @@ unmarked file was generated with the app running.
229
263
  | `rails ai:context:full` | full | all | Generate all files in full mode |
230
264
  | `rails ai:context:claude` | compact | Claude | CLAUDE.md + .claude/rules/ |
231
265
  | `rails ai:context:opencode` | compact | OpenCode | AGENTS.md + per-directory AGENTS.md |
232
- | `rails ai:context:codex` | compact | Codex | AGENTS.md + .codex/config.toml |
266
+ | `rails ai:context:codex` | compact | Codex | AGENTS.md + per-directory AGENTS.md (same files as OpenCode; `.codex/config.toml` comes from the installer or `rails ai:context`) |
233
267
  | `rails ai:context:cursor` | compact | Cursor | .cursor/rules/ |
234
268
  | `rails ai:context:copilot` | compact | Copilot | copilot-instructions.md + .github/instructions/ |
235
269
  | `rails ai:context:json` | - | JSON | .ai-context.json |
@@ -249,16 +283,18 @@ unmarked file was generated with the app running.
249
283
 
250
284
  | Command | Transport | Description |
251
285
  |---------|-----------|-------------|
252
- | `rails ai:serve` | stdio | Start MCP server. Auto-discovered by each AI tool via its own config file. |
286
+ | `rails ai:serve` | stdio | Start MCP server. The generated MCP config files start the same server with `bundle exec rails-ai-context serve`. |
253
287
  | `rails ai:serve_http` | HTTP | Start MCP server at `http://127.0.0.1:6029/mcp`. For remote clients. |
254
288
 
255
289
  ### Utilities
256
290
 
257
291
  | Command | Description |
258
292
  |---------|-------------|
259
- | `rails ai:doctor` | Run 13 diagnostic checks. Reports pass/warn/fail with fix suggestions. AI readiness score (0-100). |
293
+ | `rails ai:doctor` | Run up to 25 diagnostic checks. Reports pass/warn/fail with fix suggestions. AI readiness score (0-100). `STRICT=1` exits 1 when a check fails. |
260
294
  | `rails ai:watch` | Watch for file changes and auto-regenerate context files. Requires `listen` gem. |
261
295
  | `rails ai:inspect` | Print introspection summary to stdout. Useful for debugging. |
296
+ | `rails ai:facts` | Print a short schema facts summary (tables, columns, indexes, associations, dependencies). |
297
+ | `rails 'ai:preset[NAME]'` | Run a multi-tool preset: `architecture`, `debugging` or `migration`. |
262
298
 
263
299
  ### Standalone CLI
264
300
 
@@ -275,14 +311,16 @@ rails-ai-context tool # List all available tools
275
311
  rails-ai-context tool schema --table users --detail full # Run a tool
276
312
  rails-ai-context tool schema --help # Per-tool help
277
313
  rails-ai-context tool schema --json # JSON envelope output
278
- rails-ai-context doctor # Run diagnostics
314
+ rails-ai-context doctor # Run diagnostics (--strict exits 1 on a failed check)
279
315
  rails-ai-context watch # Watch for changes
280
316
  rails-ai-context inspect # Print introspection JSON
317
+ rails-ai-context facts # Print schema facts summary
318
+ rails-ai-context preset architecture # Run a multi-tool preset
281
319
  rails-ai-context version # Print version
282
320
  rails-ai-context help # Show all commands
283
321
  ```
284
322
 
285
- Must be run from your Rails app root directory (requires `config/environment.rb`).
323
+ Run it from your Rails app root, or pass `--app-path PATH`. Booting needs `config/environment.rb`. When the app cannot boot, or with `--no-boot`, every command except `doctor` reads the source files instead.
286
324
 
287
325
  **Config:** Standalone mode reads from `.rails-ai-context.yml` (created by `init`), and that is its only config source - the gem is not loaded while `config/initializers` runs. If no config file exists, defaults are used. With the gem in the Gemfile the two merge key by key ([Precedence](CONFIGURATION.md#precedence)).
288
326
 
@@ -345,7 +383,7 @@ Short names are resolved automatically:
345
383
  The `tool_mode` config controls how tool references appear in generated context files:
346
384
 
347
385
  ```ruby
348
- if defined?(RailsAiContext)
386
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
349
387
  RailsAiContext.configure do |config|
350
388
  # :mcp (default) - MCP primary, CLI as fallback
351
389
  # :cli - CLI only, no MCP server needed
@@ -377,7 +415,7 @@ Returns database schema: tables, columns, indexes, foreign keys.
377
415
  |-------|------|-------------|
378
416
  | `table` | string | Specific table name for full detail. Omit for listing. |
379
417
  | `detail` | string | `summary` / `standard` (default) / `full` |
380
- | `limit` | integer | Max tables to return. Default: 50 (summary), 15 (standard), 5 (full). |
418
+ | `limit` | integer | Max tables to return. Default: 50 (summary), 25 (standard), 10 (full). |
381
419
  | `offset` | integer | Skip tables for pagination. Default: 0. |
382
420
  | `format` | string | `markdown` (default) / `json`. JSON returns the same page of tables keyed by table name, or the single table's own data when `table` is given. |
383
421
 
@@ -385,7 +423,7 @@ Returns database schema: tables, columns, indexes, foreign keys.
385
423
 
386
424
  ```
387
425
  rails_get_schema()
388
- → Standard detail, first 15 tables with column names and types
426
+ → Standard detail, first 25 tables with column names and types
389
427
 
390
428
  rails_get_schema(detail: "summary")
391
429
  → All tables with column and index counts (up to 50)
@@ -402,7 +440,7 @@ rails_get_schema(detail: "full", format: "json")
402
440
 
403
441
  ### rails_get_model_details
404
442
 
405
- Returns model details: associations, validations, scopes, enums, callbacks, concerns. Source parsing uses Prism AST - every result carries a `[VERIFIED]` (static literal arguments) or `[INFERRED]` (dynamic expressions) confidence tag.
443
+ Returns model details: associations, validations, scopes, enums, callbacks, concerns. Source parsing uses Prism AST. The model heading and each scope carry a confidence tag: `[VERIFIED]` (confirmed by the booted app, or static literal arguments), `[INFERRED]` (dynamic expressions) or `[STATIC]` (read from source without a boot).
406
444
 
407
445
  **Parameters:**
408
446
 
@@ -442,7 +480,7 @@ Returns all routes: HTTP verbs, paths, controller actions, route names.
442
480
  |-------|------|-------------|
443
481
  | `controller` | string | Filter by controller name (e.g. `users`, `api/v1/posts`). Case-insensitive. |
444
482
  | `detail` | string | `summary` / `standard` (default) / `full` |
445
- | `limit` | integer | Max routes to return. Default: 100 (standard), 200 (full). |
483
+ | `limit` | integer | Max routes to return. Default: 150 (standard), 200 (full). |
446
484
  | `offset` | integer | Skip routes for pagination. Default: 0. |
447
485
  | `app_only` | boolean | Filter out internal Rails routes (Active Storage, Action Mailbox, Conductor, etc.). Default: true. |
448
486
 
@@ -458,8 +496,8 @@ rails_get_routes(detail: "summary")
458
496
  rails_get_routes(controller: "users")
459
497
  → All routes for UsersController
460
498
 
461
- rails_get_routes(controller: "api")
462
- → All routes matching "api" (partial match, case-insensitive)
499
+ rails_get_routes(controller: "posts")
500
+ → Also reaches a namespaced `api/v1/posts`: an exact name first, then the trailing path segments, never a substring
463
501
 
464
502
  rails_get_routes(detail: "full", limit: 50)
465
503
  → Full table with route names, first 50 routes
@@ -537,13 +575,15 @@ Returns notable gems categorized by function.
537
575
 
538
576
  | Param | Type | Description |
539
577
  |-------|------|-------------|
540
- | `category` | string | Filter by category: `auth`, `jobs`, `frontend`, `api`, `database`, `files`, `testing`, `deploy`, `all` (default). |
578
+ | `category` | string | Filter by category: `auth`, `jobs`, `frontend`, `api`, `database`, `files`, `testing`, `deploy`, `monitoring`, `admin`, `pagination`, `search`, `forms`, `server`, `notifications`, `validation`, `utilities`, `services`, `payments`, `all` (default). |
579
+ | `limit` | integer | Max gems to return. Default: 50. |
580
+ | `offset` | integer | Skip this many gems for pagination. Default: 0. |
541
581
 
542
582
  **Returns:** Notable gems grouped by category with descriptions.
543
583
 
544
584
  ```
545
585
  rails_get_gems()
546
- → auth: devise (4.9.3), background_jobs: sidekiq (7.2.1), ...
586
+ → Auth: devise `4.9.3`, Jobs: sidekiq `7.2.1`, ...
547
587
  ```
548
588
 
549
589
  ### rails_get_conventions
@@ -716,7 +756,7 @@ rails_search_code(pattern: "User", match_type: "class")
716
756
  → Only `class User` / `module User` definitions
717
757
  ```
718
758
 
719
- **Security:** Uses `Open3.capture2` with array arguments (no shell injection). Validates file_type. Blocks path traversal. Respects `excluded_paths` and `sensitive_patterns` config on both backends, and the Ruby fallback reads the ignore files ripgrep reads and ranks them the way ripgrep does: `.rgignore` over `.ignore` over `.gitignore` (each scoped to its own directory) over `.git/info/exclude` over the global excludes file, the file type deciding before depth, which breaks ties only within one type; `.ignore` and `.rgignore` apply outside a git repository too, and a directory the rules ignore is never entered. As ripgrep does, the fallback also reads the ignore files of every directory above the app, the git ones only as far up as the nearest `.git` (a file for a worktree or submodule), so an app nested in a larger repository gets that repository's rules and a repository nested in the app stops the app's `.gitignore`. Patterns match case-sensitively, symlinks are not followed, and a file with a NUL byte in its first 64 KiB is skipped unread, all as in ripgrep, so the two return the same set.
759
+ **Security:** Uses `Open3.capture3` with array arguments (no shell injection). Validates file_type. Blocks path traversal. Respects `excluded_paths` and `sensitive_patterns` config on both backends, and the Ruby fallback reads the ignore files ripgrep reads and ranks them the way ripgrep does: `.rgignore` over `.ignore` over `.gitignore` (each scoped to its own directory) over `.git/info/exclude` over the global excludes file, the file type deciding before depth, which breaks ties only within one type; `.ignore` and `.rgignore` apply outside a git repository too, and a directory the rules ignore is never entered. As ripgrep does, the fallback also reads the ignore files of every directory above the app, the git ones only as far up as the nearest `.git` (a file for a worktree or submodule), so an app nested in a larger repository gets that repository's rules and a repository nested in the app stops the app's `.gitignore`. Patterns match case-sensitively, symlinks are not followed, and a file with a NUL byte in its first 64 KiB is skipped unread, all as in ripgrep, so the two return the same set.
720
760
 
721
761
  ### rails_analyze_feature
722
762
 
@@ -750,7 +790,7 @@ rails_analyze_feature(feature: "orders")
750
790
 
751
791
  ### rails_security_scan
752
792
 
753
- Runs Brakeman static security analysis on the Rails app. Detects SQL injection, XSS, mass assignment, command injection, and other vulnerabilities. Requires the `brakeman` gem - returns installation instructions if not present.
793
+ Runs Brakeman static security analysis on the Rails app. Detects SQL injection, XSS, mass assignment, command injection, and other vulnerabilities. Uses the app's `brakeman` gem, or a `brakeman` gem installed for the same Ruby when the bundle has none. Returns installation instructions when neither is there.
754
794
 
755
795
  **Parameters:**
756
796
 
@@ -785,7 +825,8 @@ Get ActiveSupport::Concern details: public methods, included modules, and which
785
825
  | Param | Type | Description |
786
826
  |-------|------|-------------|
787
827
  | `name` | string | Concern module name (e.g. `Searchable`, `Authenticatable`). Omit to list all concerns. |
788
- | `type` | string | Filter by concern type: `model`, `controller`, `all` (default). |
828
+ | `type` | string | Filter by concern type, the name the listing's section headings print: `model`, `controller`, `mailer`, the root a concern outside every concerns directory lives in (`service`, `lib`), `other`, or `all` (default). |
829
+ | `detail` | string | `summary` / `standard` (default) / `full`. Only read when `name` is given: `full` adds each method's source code, `summary` and `standard` both return method signatures. The listing is the same at every level. |
789
830
 
790
831
  **Examples:**
791
832
 
@@ -844,6 +885,8 @@ Get Rails helper modules: method signatures, framework helpers in use, and which
844
885
  |-------|------|-------------|
845
886
  | `helper` | string | Helper module name (e.g. `ApplicationHelper`, `UsersHelper`). Omit to list all helpers. |
846
887
  | `detail` | string | `summary` / `standard` (default) / `full`. summary: names + method counts. standard: names + method signatures. full: method signatures + view cross-references + framework helpers. |
888
+ | `limit` | integer | Max helpers to return. Default: 50. |
889
+ | `offset` | integer | Skip this many helpers for pagination. Default: 0. |
847
890
 
848
891
  **Examples:**
849
892
 
@@ -862,7 +905,7 @@ rails_get_helper_methods(detail: "full")
862
905
 
863
906
  ### rails_get_service_pattern
864
907
 
865
- Analyze service objects in app/services/: patterns, interfaces, dependencies, and side effects. Specify a service for full detail, or omit to detect the common pattern and list all services.
908
+ Analyze service objects in app/services/, app/interactions/ and app/interactors/: patterns, interfaces, dependencies, and side effects. Specify a service for full detail, or omit to detect the common pattern and list all services.
866
909
 
867
910
  **Parameters:**
868
911
 
@@ -914,7 +957,7 @@ rails_get_job_pattern(detail: "full")
914
957
 
915
958
  ### rails_get_env
916
959
 
917
- Discover environment variables, external service dependencies, and credentials keys used by the app. Scans Ruby files for ENV[], .env.example, Dockerfile, the env Kamal's config/deploy.yml sets (secret names; clear values, except one holding a URL or a key-like token, or under a secret-named variable, which shows as hidden, and one an ERB tag sets, which says so), config gem setting keys, Anyway::Config attributes with their env names, external HTTP calls, and credentials keys (never values).
960
+ Discover environment variables, external service dependencies, and credentials keys used by the app. Scans .rb, .rake, ERB views and config YAML for ENV[], .env.example, Dockerfile, the env Kamal's config/deploy.yml sets (secret names; clear values, except one holding a URL or a key-like token, or under a secret-named variable, which shows as hidden, and one an ERB tag sets, which says so), config gem setting keys, Anyway::Config attributes with their env names, external HTTP calls, and credentials keys (never values).
918
961
 
919
962
  **Parameters:**
920
963
 
@@ -1002,6 +1045,7 @@ Get cross-layer context in a single call - combines schema, model, controller, r
1002
1045
  | `action` | string | Specific action name (e.g. `create`). Requires controller. Returns full action context. |
1003
1046
  | `model` | string | Model name (e.g. `Post`). Returns schema, associations, validations, scopes, callbacks, tests. |
1004
1047
  | `feature` | string | Feature keyword (e.g. `post`). Like analyze_feature but includes schema columns and scope bodies. |
1048
+ | `include` | array | Extra context to append in any mode: `stimulus`, `turbo`, `services`, `jobs`, `conventions`, `helpers`, `env`, `callbacks`. |
1005
1049
 
1006
1050
  **Examples:**
1007
1051
 
@@ -1010,13 +1054,13 @@ rails_get_context(controller: "PostsController", action: "create")
1010
1054
  → Controller action source + model details + routes + views - everything for that action
1011
1055
 
1012
1056
  rails_get_context(model: "User")
1013
- → Model details + schema columns + test file content
1057
+ → Model details + schema columns + the names of its tests
1014
1058
 
1015
1059
  rails_get_context(feature: "orders")
1016
1060
  → Full-stack feature analysis including schema columns and scope bodies
1017
1061
  ```
1018
1062
 
1019
- **Returns:** Combined context from multiple tools in a single response. For controller+action: controller source with filters, inferred model details, matching routes, and view templates. For model: model details with associations/validations/scopes, schema columns with types, and test file content. For feature: delegates to full-stack feature analysis.
1063
+ **Returns:** Combined context from multiple tools in a single response. For controller+action: controller source with filters, inferred model details, matching routes, and view templates. For model: model details with associations/validations/scopes, schema columns with types, and the names of the tests in its test file. For feature: delegates to full-stack feature analysis.
1020
1064
 
1021
1065
  ### Detail Level Summary
1022
1066
 
@@ -1025,10 +1069,10 @@ All tools that support `detail` use these three levels. Default limits vary by t
1025
1069
  | Level | What it returns | Schema default limit | Best for |
1026
1070
  |-------|----------------|---------------------|----------|
1027
1071
  | `summary` | Names + counts | 50 | Getting the landscape, understanding what exists |
1028
- | `standard` | Names + key details | 29 | Working context, column types, action names |
1072
+ | `standard` | Names + key details | 25 | Working context, column types, action names |
1029
1073
  | `full` | Everything | 10 | Deep inspection, indexes, FKs, constraints |
1030
1074
 
1031
- Other tools default to higher limits (e.g. models/controllers/stimulus: 50 for all levels, routes: 100/200).
1075
+ Other tools default to higher limits (e.g. models/controllers/stimulus: 50 for all levels, routes: 150/200).
1032
1076
 
1033
1077
  ### Recommended Workflow
1034
1078
 
@@ -1067,7 +1111,7 @@ Live resources introspected fresh on every request - zero stale data:
1067
1111
  | `rails-ai-context://controllers/{name}` | Controller details with actions, filters, strong params |
1068
1112
  | `rails-ai-context://controllers/{name}/{action}` | Specific action source code and applicable filters |
1069
1113
  | `rails-ai-context://views/{path}` | View template content (path traversal protected) |
1070
- | `rails-ai-context://routes` | Live route map (optionally filter by controller) |
1114
+ | `rails-ai-context://routes/{controller}` | Live route map, filtered by controller |
1071
1115
 
1072
1116
  ---
1073
1117
 
@@ -1094,7 +1138,7 @@ The install generator (or `rails-ai-context init`) creates per-tool MCP config f
1094
1138
  | OpenCode | `opencode.json` | `mcp` | JSON |
1095
1139
  | Codex CLI | `.codex/config.toml` | `[mcp_servers]` | TOML |
1096
1140
 
1097
- Each file is merge-safe - only the `rails-ai-context` entry is managed, other servers are preserved.
1141
+ Each file is merge-safe - only the `rails-ai-context` entry is managed, other servers are preserved. When the gem is not in the app's `Gemfile.lock` (standalone install) the entry runs `rails-ai-context serve` with no `bundle exec`.
1098
1142
 
1099
1143
  **Example: `.mcp.json` (Claude Code)**
1100
1144
  ```json
@@ -1102,7 +1146,7 @@ Each file is merge-safe - only the `rails-ai-context` entry is managed, other se
1102
1146
  "mcpServers": {
1103
1147
  "rails-ai-context": {
1104
1148
  "command": "bundle",
1105
- "args": ["exec", "rails", "ai:serve"]
1149
+ "args": ["exec", "rails-ai-context", "serve"]
1106
1150
  }
1107
1151
  }
1108
1152
  }
@@ -1112,7 +1156,7 @@ Each file is merge-safe - only the `rails-ai-context` entry is managed, other se
1112
1156
  ```toml
1113
1157
  [mcp_servers.rails-ai-context]
1114
1158
  command = "bundle"
1115
- args = ["exec", "rails", "ai:serve"]
1159
+ args = ["exec", "rails-ai-context", "serve"]
1116
1160
 
1117
1161
  [mcp_servers.rails-ai-context.env]
1118
1162
  PATH = "/home/user/.rbenv/shims:/usr/local/bin:/usr/bin"
@@ -1144,14 +1188,14 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
1144
1188
  "mcpServers": {
1145
1189
  "rails-ai-context": {
1146
1190
  "command": "bundle",
1147
- "args": ["exec", "rails", "ai:serve"],
1191
+ "args": ["exec", "rails-ai-context", "serve"],
1148
1192
  "cwd": "/path/to/your/rails/app"
1149
1193
  }
1150
1194
  }
1151
1195
  }
1152
1196
  ```
1153
1197
 
1154
- Or for standalone: replace `"command": "bundle"` / `"args": ["exec", "rails", "ai:serve"]` with `"command": "rails-ai-context"` / `"args": ["serve"]`.
1198
+ Or for standalone: replace `"command": "bundle"` / `"args": ["exec", "rails-ai-context", "serve"]` with `"command": "rails-ai-context"` / `"args": ["serve"]`.
1155
1199
 
1156
1200
  ### Cursor
1157
1201
 
@@ -1162,7 +1206,7 @@ Auto-discovered via `.cursor/mcp.json`. Or add manually in **Cursor Settings > M
1162
1206
  "mcpServers": {
1163
1207
  "rails-ai-context": {
1164
1208
  "command": "bundle",
1165
- "args": ["exec", "rails", "ai:serve"],
1209
+ "args": ["exec", "rails-ai-context", "serve"],
1166
1210
  "cwd": "/path/to/your/rails/app"
1167
1211
  }
1168
1212
  }
@@ -1184,7 +1228,7 @@ rails ai:serve_http
1184
1228
  Or auto-mount inside your Rails app (no separate process):
1185
1229
 
1186
1230
  ```ruby
1187
- if defined?(RailsAiContext)
1231
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
1188
1232
  RailsAiContext.configure do |config|
1189
1233
  config.auto_mount = true
1190
1234
  config.http_path = "/mcp" # default
@@ -1213,7 +1257,7 @@ This provides a native Rails controller (`RailsAiContext::McpController`) that d
1213
1257
 
1214
1258
  ```ruby
1215
1259
  # config/initializers/rails_ai_context.rb
1216
- if defined?(RailsAiContext)
1260
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
1217
1261
  RailsAiContext.configure do |config|
1218
1262
  # --- Introspectors ---
1219
1263
 
@@ -1348,7 +1392,7 @@ end
1348
1392
  | `tool_mode` | Symbol | `:mcp` | `:mcp` (MCP primary + CLI fallback) or `:cli` (CLI only, no MCP server needed) |
1349
1393
  | `ai_tools` | Array | `nil` (all) | AI tools to generate context for: `%i[claude cursor copilot opencode codex]`. Selected during install. |
1350
1394
  | `excluded_models` | Array | internal Rails models | Models to skip |
1351
- | `excluded_paths` | Array | `node_modules tmp log vendor .git` | Paths excluded from code search |
1395
+ | `excluded_paths` | Array | `node_modules tmp log vendor .git doc docs` | Paths excluded from code search |
1352
1396
  | `sensitive_patterns` | Array | `.env`, `.key`, `.pem`, credentials | File patterns blocked from search and read tools |
1353
1397
  | `output_dir` | String | `nil` (Rails.root) | Where to write context files |
1354
1398
  | `auto_mount` | Boolean | `false` | Auto-mount HTTP MCP endpoint |
@@ -1358,7 +1402,7 @@ end
1358
1402
  | `live_reload` | Symbol/Boolean | `:auto` | `:auto`, `true`, or `false` - enable MCP live reload |
1359
1403
  | `live_reload_debounce` | Float | `1.5` | Debounce interval in seconds for live reload |
1360
1404
  | `server_name` | String | `"rails-ai-context"` | MCP server name |
1361
- | `server_version` | String | gem version | MCP server version |
1405
+ | `server_version` | String | gem version | MCP server version. Read-only, there is no setter |
1362
1406
  | `generate_root_files` | Boolean | `true` | Set `false` to generate split rules only: no CLAUDE.md, AGENTS.md, .cursorrules or copilot-instructions.md (`.ai-context.json` is still written) |
1363
1407
  | `anti_hallucination_rules` | Boolean | `true` | Embed 6-rule Anti-Hallucination Protocol in generated context files - set `false` to skip |
1364
1408
  | `hydration_enabled` | Boolean | `true` | Inject schema hints into controller/view tool responses |
@@ -1378,6 +1422,16 @@ end
1378
1422
  | `excluded_middleware` | Array | standard Rails middleware | Default middleware hidden from config output |
1379
1423
  | `search_extensions` | Array | `nil` | Narrows the Ruby fallback to these extensions. Unset, it searches every non-hidden, non-binary file, as ripgrep does |
1380
1424
  | `concern_paths` | Array | `nil` (discovers `app/concerns` and `app/*/concerns`) | Where to look for concern source files. Setting it replaces discovery |
1425
+ | `context_files` | Boolean | `true` | Set `false` for an MCP-only install: no CLAUDE.md, AGENTS.md, rules files or `.ai-context.json` are written |
1426
+ | `frontend_paths` | Array | `nil` (auto-detected) | Frontend directories, e.g. `["app/frontend", "../web-client"]`. One outside the app root is read for manifests only |
1427
+ | `extra_app_paths` | Array | `[]` | More app-root-relative directories that hold Rails app code. Each one's `app/models`, `app/controllers` and `app/views` are scanned |
1428
+ | `query_timeout` | Integer | `5` | `rails_query` statement timeout in seconds |
1429
+ | `query_row_limit` | Integer | `100` | Max rows `rails_query` returns (1 to 1000) |
1430
+ | `query_redacted_columns` | Array | `password_digest`, `encrypted_password`, tokens, etc. | Column names whose values `rails_query` redacts |
1431
+ | `query_allowed_columns` | Array | `[]` | Column names to exempt from the built-in sensitive list |
1432
+ | `allow_query_in_production` | Boolean | `false` | Allow `rails_query` in production |
1433
+ | `log_lines` | Integer | `50` | Default number of lines `rails_read_logs` tails |
1434
+ | `instrumentation_include_arguments` | Boolean | `false` | Forward raw tool arguments in `ActiveSupport::Notifications` events |
1381
1435
 
1382
1436
  ### Root file generation
1383
1437
 
@@ -1388,14 +1442,14 @@ By default, `rails ai:context` generates root files (CLAUDE.md, AGENTS.md, etc.)
1388
1442
  **Skip root files:** If you prefer to maintain root files yourself and only want split rules (`.claude/rules/`, `.cursor/rules/`, `.github/instructions/`):
1389
1443
 
1390
1444
  ```ruby
1391
- if defined?(RailsAiContext)
1445
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
1392
1446
  RailsAiContext.configure do |config|
1393
1447
  config.generate_root_files = false
1394
1448
  end
1395
1449
  end
1396
1450
  ```
1397
1451
 
1398
- All split rules include an app overview file, so no context is lost when root files are disabled.
1452
+ The Claude Code, Cursor and Copilot rule sets each keep an app overview file (`rails-context.md`, `rails-project.mdc`, `rails-context.instructions.md`). The Claude Code one leaves out gems, architecture, services and jobs, which it expects in CLAUDE.md. OpenCode and Codex have no overview outside AGENTS.md: their split files hold only the model and controller listings.
1399
1453
 
1400
1454
  ---
1401
1455
 
@@ -1411,7 +1465,7 @@ Core Rails structure only. Use `config.preset = :standard` for a lighter footpri
1411
1465
  | `models` | Associations, validations, scopes, enums, callbacks, concerns, instance methods, class methods. Source-level macros via Prism AST (single-pass, 8 listeners): `has_secure_password`, `encrypts`, `normalizes`, `delegate`, `serialize`, `store`, `generates_token_for`, `has_one_attached`, `has_many_attached`, `has_rich_text`, `broadcasts_to`. Every result tagged `[VERIFIED]` or `[INFERRED]`. |
1412
1466
  | `routes` | All routes with HTTP verbs, paths, controller actions, route names, API namespaces, mounted engines. |
1413
1467
  | `jobs` | ActiveJob classes with queue names. Mailers with action methods. Action Cable channels. |
1414
- | `gems` | 70+ notable gems categorized: auth, background_jobs, admin, monitoring, search, pagination, forms, file_upload, testing, linting, security, api, frontend, utilities. |
1468
+ | `gems` | 127 notable gems categorized: auth, jobs, frontend, api, database, files, testing, deploy, monitoring, admin, pagination, search, forms, server, notifications, validation, utilities, services, payments. |
1415
1469
  | `conventions` | Architecture patterns (MVC, service objects, STI, polymorphism, etc.), directory structure with file counts, config files, detected patterns. |
1416
1470
  | `controllers` | Actions, filters (before/after/around with only/except), strong params methods, parent class, API controller detection, concerns. |
1417
1471
  | `tests` | Test framework (rspec/minitest), factories/fixtures with locations and counts, system tests, CI config files, coverage tool, test helpers, VCR cassettes. |
@@ -1441,11 +1495,19 @@ Includes all standard introspectors plus:
1441
1495
  | `action_mailbox` | Action Mailbox mailboxes with routing patterns. |
1442
1496
  | `seeds` | db/seeds.rb analysis (Faker usage, environment conditionals), seed files in db/seeds/, models seeded. |
1443
1497
  | `middleware` | Custom Rack middleware in app/middleware/ and lib/middleware/ with detected patterns (auth, rate limiting, tenant isolation, logging), what the app's config inserts, moves or removes, and the full middleware stack. |
1444
- | `engines` | Mounted Rails engines from routes.rb with paths and descriptions for 23+ known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.). |
1498
+ | `engines` | Mounted Rails engines from routes.rb with paths and descriptions for 23 known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.). |
1445
1499
  | `env_config` | Per-environment config files (`config/environments/*.rb`): notable toggles (`force_ssl`, `eager_load`, caching, log level, queue adapter, mailer delivery) with URI credentials redacted, assigned config keys, plus the keys `config/application.rb` sets for every environment and the keys each `config_for` YAML file gives. |
1446
1500
  | `multi_database` | Multiple databases, replicas, sharding config, model-specific `connects_to` declarations. database.yml parsing fallback. |
1447
1501
  | `frontend_frameworks` | Frontend JS framework detection (React/Vue/Svelte/Angular), mounting strategy (Inertia/react-rails), TypeScript config, state management, package manager. |
1448
1502
  | `database_stats` | PostgreSQL approximate row counts via `pg_stat_user_tables`. Gracefully skips on non-PostgreSQL adapters. |
1503
+ | `initializers` | The `Rails.application.initializers` graph (name, owner, `before:`/`after:` edges) and a per-file summary of `config/initializers/*.rb`. |
1504
+ | `autoload` | Zeitwerk autoloaders with collapsed and ignored dirs, `autoload_paths`, `eager_load_paths`, custom inflections. |
1505
+ | `connection_pool` | Per-database adapter config: pool size, `checkout_timeout`, `reaping_frequency`, `prepared_statements`, replica flag, connection-handler roles. |
1506
+ | `active_support` | Concerns in `app/**/concerns/`, deprecators, MessageEncryptor/Verifier usage, notification subscriptions, on-load hooks, cache store options. |
1507
+ | `credentials` | Encrypted credentials files (default and per-environment), where the master key comes from, top-level key names only (never values). |
1508
+ | `security` | `force_ssl` and SSL options, host authorization, Content Security Policy and Permissions Policy directives, CSRF config, cookie session options. |
1509
+ | `observability` | Log subscribers, `ActiveSupport::Notifications` subscribers, `ServerTiming` middleware, log level and tags. |
1510
+ | `env` | Rails-related ENV vars split into set and unset (sensitive ones are redacted), plus the app's own `ENV["X"]` references. |
1449
1511
 
1450
1512
  ### Using the standard preset
1451
1513
 
@@ -1501,7 +1563,7 @@ config.introspectors = %i[schema models routes gems auth api]
1501
1563
  "mcp": {
1502
1564
  "rails-ai-context": {
1503
1565
  "type": "local",
1504
- "command": ["bundle", "exec", "rails", "ai:serve"]
1566
+ "command": ["bundle", "exec", "rails-ai-context", "serve"]
1505
1567
  }
1506
1568
  }
1507
1569
  }
@@ -1563,21 +1625,21 @@ OpenCode uses **per-directory lazy-loading**: when the agent reads a file, it wa
1563
1625
  | Setup | Coverage | Notes |
1564
1626
  |-------|----------|-------|
1565
1627
  | Rails full-stack (ERB + Hotwire) | 40/40 | All introspectors relevant |
1566
- | Rails + Inertia.js (React/Vue) | ~34/40 | Views/Turbo partially useful, backend fully covered |
1567
- | Rails API + React/Next.js SPA | ~32/40 | Schema, models, routes, API, auth, jobs - all covered |
1568
- | Rails API + mobile app | ~32/40 | Same as SPA - backend introspection is identical |
1569
- | Rails engine (mountable gem) | ~27/40 | Core introspectors (schema, models, routes, gems) work |
1628
+ | Rails + Inertia.js (React/Vue) | Backend ones | Views/Turbo partially useful, backend fully covered |
1629
+ | Rails API + React/Next.js SPA | Backend ones | Schema, models, routes, API, auth, jobs - all covered |
1630
+ | Rails API + mobile app | Backend ones | Same as SPA - backend introspection is identical |
1631
+ | Rails engine (mountable gem) | Core ones | Core introspectors (schema, models, routes, gems) work |
1570
1632
 
1571
- Frontend introspectors (views, Turbo, Stimulus, assets) degrade gracefully - they report nothing when those features aren't present.
1633
+ All 40 introspectors run on every setup with the default `:full` preset. The gem keeps no per-setup count: frontend introspectors (views, Turbo, Stimulus, assets) degrade gracefully - they report nothing when those features aren't present.
1572
1634
 
1573
1635
  **Tip for API-only apps:**
1574
1636
 
1575
1637
  ```ruby
1576
- # Use standard preset (already perfect for API apps)
1638
+ # Use standard preset (it already has auth)
1577
1639
  config.preset = :standard
1578
1640
 
1579
- # Or add API-specific introspectors
1580
- config.introspectors += %i[auth api]
1641
+ # And add the API introspector, which standard leaves out
1642
+ config.introspectors += %i[api]
1581
1643
  ```
1582
1644
 
1583
1645
  ---
@@ -1588,23 +1650,35 @@ config.introspectors += %i[auth api]
1588
1650
  rails ai:doctor
1589
1651
  ```
1590
1652
 
1591
- Runs 13 checks and reports an AI readiness score (0-100):
1653
+ Runs up to 25 checks and reports an AI readiness score (0-100). A check that does not apply to the app prints no row:
1592
1654
 
1593
1655
  | Check | What it verifies |
1594
1656
  |-------|------------------|
1595
- | Schema | db/schema.rb exists and is parseable |
1596
- | Models | Model files detected in app/models/ |
1597
- | Routes | Routes are mapped |
1598
- | Gems | Gemfile.lock exists and is parseable |
1657
+ | Schema | A schema dump file exists |
1658
+ | Pending migrations | No migration is pending (fails when one is) |
1659
+ | Models | Model files detected |
1660
+ | Routes | `config/routes.rb` exists |
1661
+ | Gems | The lockfile exists |
1599
1662
  | Controllers | Controller files detected |
1600
- | Views | View templates detected |
1601
- | I18n | Locale files exist |
1602
- | Tests | Test framework detected |
1663
+ | Views | Files exist under `app/views` |
1664
+ | Tests | A test suite is found |
1603
1665
  | Migrations | Migration files exist |
1604
- | Context files | Generated context files exist |
1605
- | MCP Server | MCP server can be built |
1606
- | Ripgrep | `rg` binary installed (optional, falls back to Ruby) |
1666
+ | Context files | Generated context files exist and are newer than the code they describe. No row on an MCP-only install |
1667
+ | Initializer guard | Shown only when `config/initializers/rails_ai_context.rb` has no guard, or guards on `defined?(RailsAiContext)` alone |
1668
+ | MCP configs | Each selected tool's MCP config file exists and parses. Skipped in CLI-only mode |
1669
+ | Codex env snapshot | The `GEM_HOME` saved in `.codex/config.toml` still exists. Only when Codex is selected |
1670
+ | MCP server | MCP server can be built |
1671
+ | Introspector health | Every configured introspector returns data |
1672
+ | Preset coverage | The preset covers the features the app has |
1673
+ | ripgrep | `rg` binary installed (optional, falls back to Ruby) |
1674
+ | Prism parser | Prism is available for AST-based validation |
1675
+ | Brakeman | Brakeman is available for `rails_security_scan` (optional) |
1607
1676
  | Live reload | `listen` gem installed (optional, enables MCP live reload) |
1677
+ | MCP stdio hygiene | On a standalone install, gem activation prints nothing on stdout |
1678
+ | Secrets in .gitignore | Sensitive files that exist are gitignored |
1679
+ | MCP auto_mount | `auto_mount` is not on in production |
1680
+ | Schema file size | The schema file is under 80% of `max_schema_file_size` |
1681
+ | View aggregation size | `app/views` templates total under 80% of `max_view_total_size` |
1608
1682
 
1609
1683
  Each check reports **pass**, **warn**, or **fail** with fix suggestions.
1610
1684
 
@@ -1625,7 +1699,7 @@ Requires the `listen` gem:
1625
1699
  gem "listen", group: :development
1626
1700
  ```
1627
1701
 
1628
- Watches for changes in: `app/`, `config/`, `db/`, `lib/`, `rakelib/`, `test/`, `spec/`, and regenerates only the files that changed (diff-aware, skips unchanged files).
1702
+ Watches for changes in: `app/`, `config/`, `db/`, `lib/`, `rakelib/`, `test/`, `spec/`, plus the app directories of packs, in-repo engines and `extra_app_paths`, and regenerates only the files that changed (diff-aware, skips unchanged files).
1629
1703
 
1630
1704
  ---
1631
1705
 
@@ -1635,12 +1709,12 @@ When running the MCP server via `rails ai:serve`, **live reload** automatically
1635
1709
 
1636
1710
  ### How it works
1637
1711
 
1638
- 1. A background thread watches `app/`, `config/`, `db/`, `lib/`, `rakelib/`, `test/` and `spec/` for changes
1712
+ 1. A background thread watches `app/`, `config/`, `db/`, `lib/`, `rakelib/`, `test/` and `spec/` (plus the app directories of packs, in-repo engines and `extra_app_paths`) for changes
1639
1713
  2. On change (debounced 1.5s), it checks the file fingerprint to avoid false positives
1640
1714
  3. If files truly changed, it:
1641
1715
  - Clears all MCP tool caches
1642
1716
  - Sends `notifications/resources/list_changed` to the AI client
1643
- - Logs a summary of what changed (e.g., "Files changed: 2 model(s), 1 controller(s)")
1717
+ - Logs a summary of what changed (e.g., "Files changed: 2 models, 1 controller.")
1644
1718
 
1645
1719
  ### Setup
1646
1720
 
@@ -1656,9 +1730,9 @@ Live reload is **enabled by default** when the `listen` gem is available. No con
1656
1730
  ### Configuration
1657
1731
 
1658
1732
  ```ruby
1659
- if defined?(RailsAiContext)
1733
+ if defined?(RailsAiContext) && RailsAiContext.respond_to?(:configure)
1660
1734
  RailsAiContext.configure do |config|
1661
- # :auto (default) - enable if `listen` gem is available, skip silently otherwise
1735
+ # :auto (default) - enable if `listen` gem is available, otherwise skip with one line on stderr
1662
1736
  # true - enable, raise if `listen` gem is missing
1663
1737
  # false - disable entirely
1664
1738
  config.live_reload = :auto
@@ -1696,12 +1770,12 @@ Works in:
1696
1770
  ## Security
1697
1771
 
1698
1772
  - All MCP tools are **read-only** - they never modify your application or database
1699
- - Code search uses `Open3.capture2` with array arguments - **no shell injection**
1773
+ - Code search uses `Open3.capture3` with array arguments - **no shell injection**
1700
1774
  - File paths are validated against **path traversal** attacks
1701
1775
  - Credentials and secret values are **never exposed** - only key names are introspected
1702
1776
  - The gem makes **no outbound network requests**
1703
1777
  - File type validation prevents arbitrary file access in code search
1704
- - `max_results` is capped at 100 to prevent resource exhaustion
1778
+ - Search output is capped at `max_search_results` lines (default 200) to prevent resource exhaustion
1705
1779
 
1706
1780
  ---
1707
1781
 
@@ -1735,7 +1809,7 @@ config.max_tool_response_chars = 60_000
1735
1809
 
1736
1810
  ### Models not detected
1737
1811
 
1738
- - Models must be in `app/models/` and inherit from `ApplicationRecord`
1812
+ - Models must descend from `ActiveRecord::Base`, through `ApplicationRecord` or any other base class. Without a boot they must also sit in a model directory (`app/models/`, or a pack's or engine's)
1739
1813
  - Excluded models: `ApplicationRecord`, `ActiveStorage::*`, `ActionText::*`, `ActionMailbox::*`
1740
1814
  - Add custom exclusions: `config.excluded_models += %w[InternalModel]`
1741
1815