rails-ai-context 2.0.4 → 3.0.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/docs/GUIDE.md CHANGED
@@ -11,6 +11,7 @@
11
11
  - [Context Modes](#context-modes)
12
12
  - [Generated Files](#generated-files)
13
13
  - [All Commands](#all-commands)
14
+ - [CLI Tools](#cli-tools)
14
15
  - [MCP Tools — Full Reference](#mcp-tools--full-reference)
15
16
  - [MCP Resources](#mcp-resources)
16
17
  - [MCP Server Setup](#mcp-server-setup)
@@ -62,8 +63,10 @@ rails ai:doctor
62
63
 
63
64
  1. Creates `.mcp.json` in project root (MCP auto-discovery)
64
65
  2. Creates `config/initializers/rails_ai_context.rb` with commented defaults
65
- 3. Adds `.ai-context.json` to `.gitignore` (JSON cache markdown files should be committed)
66
- 4. Generates all context files
66
+ 3. Asks which AI tools you use (Claude, Cursor, Copilot, OpenCode)
67
+ 4. Asks whether to enable MCP server (`tool_mode: :mcp`) or use CLI-only mode (`tool_mode: :cli`)
68
+ 5. Adds `.ai-context.json` to `.gitignore` (JSON cache — markdown files should be committed)
69
+ 6. Generates all context files
67
70
 
68
71
  ---
69
72
 
@@ -78,7 +81,6 @@ rails ai:context
78
81
  ```
79
82
 
80
83
  - CLAUDE.md ≤150 lines
81
- - .windsurfrules ≤5,800 characters
82
84
  - copilot-instructions.md ≤500 lines
83
85
  - Files contain a project overview + MCP tool reference
84
86
  - AI uses MCP tools for detailed data on-demand
@@ -105,9 +107,6 @@ CONTEXT_MODE=full rails ai:context:claude
105
107
  # Full dump for Cursor only
106
108
  CONTEXT_MODE=full rails ai:context:cursor
107
109
 
108
- # Full dump for Windsurf only (still respects 6K char limit)
109
- CONTEXT_MODE=full rails ai:context:windsurf
110
-
111
110
  # Full dump for Copilot only
112
111
  CONTEXT_MODE=full rails ai:context:copilot
113
112
  ```
@@ -156,15 +155,6 @@ end
156
155
  | `.cursor/rules/rails-ui-patterns.mdc` | UI patterns and design tokens | `globs: app/views/**/*.erb` — loaded when editing views. |
157
156
  | `.cursor/rules/rails-mcp-tools.mdc` | MCP tool reference | `alwaysApply: true` — always available. |
158
157
 
159
- ### Windsurf (4 files)
160
-
161
- | File | Purpose | Notes |
162
- |------|---------|-------|
163
- | `.windsurfrules` | Main context file | Hard-capped at 5,800 chars (Windsurf's 6K limit). Truncated silently if exceeded. |
164
- | `.windsurf/rules/rails-context.md` | Project overview | New Windsurf rules format. |
165
- | `.windsurf/rules/rails-ui-patterns.md` | UI patterns and design tokens | Loaded when editing views. |
166
- | `.windsurf/rules/rails-mcp-tools.md` | MCP tool reference | Compact — respects 6K per-file limit. |
167
-
168
158
  ### GitHub Copilot (6 files)
169
159
 
170
160
  | File | Purpose | Notes |
@@ -199,14 +189,20 @@ Commit **all files except `.ai-context.json`** (which is gitignored). This gives
199
189
  | `rails ai:context:claude` | compact | Claude | CLAUDE.md + .claude/rules/ |
200
190
  | `rails ai:context:opencode` | compact | OpenCode | AGENTS.md + per-directory AGENTS.md |
201
191
  | `rails ai:context:cursor` | compact | Cursor | .cursor/rules/ |
202
- | `rails ai:context:windsurf` | compact | Windsurf | .windsurfrules + .windsurf/rules/ |
203
192
  | `rails ai:context:copilot` | compact | Copilot | copilot-instructions.md + .github/instructions/ |
204
193
  | `rails ai:context:json` | — | JSON | .ai-context.json |
205
194
  | `CONTEXT_MODE=full rails ai:context:claude` | full | Claude | Full dump for Claude only |
206
195
  | `CONTEXT_MODE=full rails ai:context:cursor` | full | Cursor | Full dump for Cursor only |
207
- | `CONTEXT_MODE=full rails ai:context:windsurf` | full | Windsurf | Full dump for Windsurf only |
208
196
  | `CONTEXT_MODE=full rails ai:context:copilot` | full | Copilot | Full dump for Copilot only |
209
197
 
198
+ ### CLI tools
199
+
200
+ | Command | Description |
201
+ |---------|-------------|
202
+ | `rails 'ai:tool[NAME]'` | Run any MCP tool from the CLI (e.g. `rails 'ai:tool[schema]' table=users detail=full`) |
203
+ | `rails ai:tool` | List all available tools with descriptions |
204
+ | `rails 'ai:tool[NAME]' JSON=1` | Run tool with JSON envelope output |
205
+
210
206
  ### MCP server
211
207
 
212
208
  | Command | Transport | Description |
@@ -232,6 +228,10 @@ rails-ai-context serve --transport http # Start MCP server (HTTP, port 6029)
232
228
  rails-ai-context serve --transport http --port 8080 # Custom port
233
229
  rails-ai-context context # Generate all context files
234
230
  rails-ai-context context --format claude # Generate Claude files only
231
+ rails-ai-context tool # List all available tools
232
+ rails-ai-context tool schema --table users --detail full # Run a tool
233
+ rails-ai-context tool schema --help # Per-tool help
234
+ rails-ai-context tool schema --json # JSON envelope output
235
235
  rails-ai-context doctor # Run diagnostics
236
236
  rails-ai-context watch # Watch for changes
237
237
  rails-ai-context inspect # Print introspection JSON
@@ -250,6 +250,70 @@ rails ai:context:claude # Use this instead (no quoting needed)
250
250
 
251
251
  ---
252
252
 
253
+ ## CLI Tools
254
+
255
+ All 25 MCP tools can be run directly from the terminal — no MCP server or AI client needed.
256
+
257
+ ### Rake
258
+
259
+ ```bash
260
+ # Run a tool with arguments
261
+ rails 'ai:tool[schema]' table=users detail=full
262
+
263
+ # List all available tools
264
+ rails ai:tool
265
+
266
+ # JSON envelope output
267
+ rails 'ai:tool[schema]' table=users JSON=1
268
+ ```
269
+
270
+ ### Thor CLI
271
+
272
+ ```bash
273
+ # Run a tool with arguments
274
+ rails-ai-context tool schema --table users --detail full
275
+
276
+ # List all tools
277
+ rails-ai-context tool
278
+
279
+ # Per-tool help (auto-generated from input_schema)
280
+ rails-ai-context tool schema --help
281
+
282
+ # JSON output
283
+ rails-ai-context tool schema --table users --json
284
+ ```
285
+
286
+ ### Tool name resolution
287
+
288
+ Short names are resolved automatically:
289
+
290
+ | You type | Resolves to |
291
+ |----------|-------------|
292
+ | `schema` | `rails_get_schema` |
293
+ | `get_schema` | `rails_get_schema` |
294
+ | `rails_get_schema` | `rails_get_schema` |
295
+ | `search_code` | `rails_search_code` |
296
+ | `analyze_feature` | `rails_analyze_feature` |
297
+
298
+ ### tool_mode configuration
299
+
300
+ The `tool_mode` config controls how tool references appear in generated context files:
301
+
302
+ ```ruby
303
+ RailsAiContext.configure do |config|
304
+ # :mcp (default) — MCP primary, CLI as fallback
305
+ # :cli — CLI only, no MCP server needed
306
+ config.tool_mode = :mcp
307
+ end
308
+ ```
309
+
310
+ - **`:mcp`** — context files show MCP tool syntax (e.g. `rails_get_schema(table: "users")`). CLI tools still available as fallback.
311
+ - **`:cli`** — context files show CLI syntax (e.g. `rails 'ai:tool[schema]' table=users`). No MCP server required.
312
+
313
+ The `tool_mode` is selected during `rails generate rails_ai_context:install`.
314
+
315
+ ---
316
+
253
317
  ## MCP Tools — Full Reference
254
318
 
255
319
  All 25 tools are **read-only** and **idempotent** — they never modify your application or database.
@@ -1083,6 +1147,9 @@ RailsAiContext.configure do |config|
1083
1147
 
1084
1148
  # --- MCP tools ---
1085
1149
 
1150
+ # Tool mode: :mcp (MCP primary + CLI fallback) or :cli (CLI only)
1151
+ config.tool_mode = :mcp
1152
+
1086
1153
  # Max response size for tool results (safety net)
1087
1154
  config.max_tool_response_chars = 200_000
1088
1155
 
@@ -1183,7 +1250,8 @@ end
1183
1250
  | `cache_ttl` | Integer | `60` | Cache TTL in seconds for introspection results |
1184
1251
  | `custom_tools` | Array | `[]` | Additional MCP tool classes to register alongside built-in tools |
1185
1252
  | `skip_tools` | Array | `[]` | Built-in tool names to exclude (e.g. `%w[rails_security_scan]`) |
1186
- | `ai_tools` | Array | `nil` (all) | AI tools to generate context for: `%i[claude cursor copilot windsurf opencode]`. Selected during install. |
1253
+ | `tool_mode` | Symbol | `:mcp` | `:mcp` (MCP primary + CLI fallback) or `:cli` (CLI only, no MCP server needed) |
1254
+ | `ai_tools` | Array | `nil` (all) | AI tools to generate context for: `%i[claude cursor copilot opencode]`. Selected during install. |
1187
1255
  | `excluded_models` | Array | internal Rails models | Models to skip |
1188
1256
  | `excluded_paths` | Array | `node_modules tmp log vendor .git` | Paths excluded from code search |
1189
1257
  | `sensitive_patterns` | Array | `.env`, `.key`, `.pem`, credentials | File patterns blocked from search and read tools |
@@ -1196,7 +1264,7 @@ end
1196
1264
  | `live_reload_debounce` | Float | `1.5` | Debounce interval in seconds for live reload |
1197
1265
  | `server_name` | String | `"rails-ai-context"` | MCP server name |
1198
1266
  | `server_version` | String | gem version | MCP server version |
1199
- | `generate_root_files` | Boolean | `true` | Generate root files (CLAUDE.md, .windsurfrules, etc.) — set `false` for split rules only |
1267
+ | `generate_root_files` | Boolean | `true` | Generate root files (CLAUDE.md, etc.) — set `false` for split rules only |
1200
1268
  | `max_file_size` | Integer | `5_000_000` | Per-file read limit for tools (5MB) |
1201
1269
  | `max_test_file_size` | Integer | `1_000_000` | Test file read limit (1MB) |
1202
1270
  | `max_schema_file_size` | Integer | `10_000_000` | schema.rb / structure.sql parse limit (10MB) |
@@ -1214,11 +1282,11 @@ end
1214
1282
 
1215
1283
  ### Root file generation
1216
1284
 
1217
- By default, `rails ai:context` generates root files (CLAUDE.md, AGENTS.md, .windsurfrules, etc.) alongside split rules.
1285
+ By default, `rails ai:context` generates root files (CLAUDE.md, AGENTS.md, etc.) alongside split rules.
1218
1286
 
1219
1287
  **Section markers:** Generated content is wrapped in `<!-- BEGIN rails-ai-context -->` / `<!-- END rails-ai-context -->` markers. If you add custom notes above or below the markers, they will be preserved when you re-run `rails ai:context`.
1220
1288
 
1221
- **Skip root files:** If you prefer to maintain root files yourself and only want split rules (`.claude/rules/`, `.cursor/rules/`, `.windsurf/rules/`, `.github/instructions/`):
1289
+ **Skip root files:** If you prefer to maintain root files yourself and only want split rules (`.claude/rules/`, `.cursor/rules/`, `.github/instructions/`):
1222
1290
 
1223
1291
  ```ruby
1224
1292
  RailsAiContext.configure do |config|
@@ -1345,16 +1413,6 @@ OpenCode uses **per-directory lazy-loading**: when the agent reads a file, it wa
1345
1413
 
1346
1414
  **MCP tools:** Available via `opencode.json` config above.
1347
1415
 
1348
- ### Windsurf
1349
-
1350
- **Context files loaded:**
1351
- - `.windsurfrules` — read at conversation start (≤6,000 chars, silently truncated if exceeded)
1352
- - `.windsurf/rules/*.md` — new rules format
1353
-
1354
- **Limits:**
1355
- - 6,000 characters per rule file
1356
- - 12,000 characters total (global + workspace combined)
1357
-
1358
1416
  ### GitHub Copilot
1359
1417
 
1360
1418
  **Context files loaded:**
data/exe/rails-ai-context CHANGED
@@ -5,6 +5,42 @@ require "thor"
5
5
 
6
6
  module RailsAiContext
7
7
  class CLI < Thor
8
+ # Let Thor pass unknown options through to ToolRunner for the tool command
9
+ stop_on_unknown_option! :tool
10
+
11
+ desc "tool [NAME]", "Run an MCP tool (25 available). Use --list to see all."
12
+ option :json, type: :boolean, default: false, desc: "Output as JSON envelope"
13
+ option :list, type: :boolean, default: false, desc: "List available tools"
14
+ def tool(name = nil, *args)
15
+ if options[:list] || name.nil?
16
+ boot_rails!
17
+ require "rails_ai_context"
18
+ puts RailsAiContext::CLI::ToolRunner.tool_list
19
+ return
20
+ end
21
+
22
+ boot_rails!
23
+ require "rails_ai_context"
24
+
25
+ if args.include?("--help") || args.include?("-h")
26
+ tool_class = RailsAiContext::CLI::ToolRunner.new(name, []).tool_class
27
+ puts RailsAiContext::CLI::ToolRunner.tool_help(tool_class)
28
+ return
29
+ end
30
+
31
+ runner = RailsAiContext::CLI::ToolRunner.new(name, args, json_mode: options[:json])
32
+ puts runner.run
33
+ rescue RailsAiContext::CLI::ToolRunner::ToolNotFoundError => e
34
+ $stderr.puts "Error: #{e.message}"
35
+ exit 1
36
+ rescue RailsAiContext::CLI::ToolRunner::InvalidArgumentError => e
37
+ $stderr.puts "Error: #{e.message}"
38
+ exit 3
39
+ rescue => e
40
+ $stderr.puts "Error: #{e.message}"
41
+ exit 2
42
+ end
43
+
8
44
  desc "serve", "Start MCP server (stdio transport)"
9
45
  option :transport, type: :string, default: "stdio", desc: "Transport: stdio or http"
10
46
  option :port, type: :numeric, default: 6029, desc: "HTTP port (only for http transport)"
@@ -21,7 +57,7 @@ module RailsAiContext
21
57
  end
22
58
 
23
59
  desc "context", "Generate AI context files"
24
- option :format, type: :string, default: "all", desc: "Format: claude, cursor, windsurf, copilot, json, all"
60
+ option :format, type: :string, default: "all", desc: "Format: claude, cursor, copilot, json, all"
25
61
  def context
26
62
  boot_rails!
27
63
  require "rails_ai_context"
@@ -13,8 +13,7 @@ module RailsAiContext
13
13
  "1" => { key: :claude, name: "Claude Code", files: "CLAUDE.md + .claude/rules/", format: :claude },
14
14
  "2" => { key: :cursor, name: "Cursor", files: ".cursor/rules/", format: :cursor },
15
15
  "3" => { key: :copilot, name: "GitHub Copilot", files: ".github/copilot-instructions.md + .github/instructions/", format: :copilot },
16
- "4" => { key: :windsurf, name: "Windsurf", files: ".windsurfrules + .windsurf/rules/", format: :windsurf },
17
- "5" => { key: :opencode, name: "OpenCode", files: "AGENTS.md", format: :opencode }
16
+ "4" => { key: :opencode, name: "OpenCode", files: "AGENTS.md", format: :opencode }
18
17
  }.freeze
19
18
 
20
19
  def select_ai_tools
@@ -46,7 +45,31 @@ module RailsAiContext
46
45
  say "Selected: #{selected_names.join(', ')}", :green
47
46
  end
48
47
 
48
+ def select_tool_mode
49
+ say ""
50
+ say "Do you also want MCP server support?", :yellow
51
+ say ""
52
+ say " 1. Yes — MCP primary + CLI fallback (generates .mcp.json)"
53
+ say " 2. No — CLI only (no server needed)"
54
+ say ""
55
+
56
+ input = ask("Enter number (default: 1):").strip
57
+
58
+ @tool_mode = case input
59
+ when "2" then :cli
60
+ else :mcp
61
+ end
62
+
63
+ mode_label = @tool_mode == :mcp ? "MCP + CLI fallback" : "CLI only"
64
+ say "Selected: #{mode_label}", :green
65
+ end
66
+
49
67
  def create_mcp_config
68
+ # Skip .mcp.json for CLI-only mode
69
+ if @tool_mode == :cli
70
+ say "Skipped .mcp.json (CLI-only mode)", :yellow
71
+ return
72
+ end
50
73
  mcp_path = Rails.root.join(".mcp.json")
51
74
  server_entry = {
52
75
  "command" => "bundle",
@@ -74,32 +97,107 @@ module RailsAiContext
74
97
 
75
98
  def create_initializer
76
99
  tools_line = if @selected_formats.size == AI_TOOLS.size
77
- " # config.ai_tools = %i[claude cursor copilot windsurf opencode] # default: all"
100
+ " # config.ai_tools = %i[claude cursor copilot opencode] # default: all"
78
101
  else
79
102
  " config.ai_tools = %i[#{@selected_formats.join(' ')}]"
80
103
  end
81
104
 
105
+ tool_mode_line = if @tool_mode == :cli
106
+ " config.tool_mode = :cli # CLI only (no MCP server needed)"
107
+ else
108
+ " # config.tool_mode = :mcp # MCP primary + CLI fallback (default)"
109
+ end
110
+
82
111
  create_file "config/initializers/rails_ai_context.rb", <<~RUBY
83
112
  # frozen_string_literal: true
84
113
 
85
114
  RailsAiContext.configure do |config|
86
- # AI tools to generate context files for (selected during install)
115
+ # ── AI Tools ──────────────────────────────────────────────────────
116
+ # Which AI tools to generate context files for (selected during install)
87
117
  # Run `rails generate rails_ai_context:install` to change selection
88
118
  #{tools_line}
89
119
 
120
+ # Tool invocation mode:
121
+ # :mcp — MCP primary + CLI fallback (default, requires `rails ai:serve`)
122
+ # :cli — CLI only (no MCP server needed, uses `rails 'ai:tool[NAME]'`)
123
+ #{tool_mode_line}
124
+
125
+ # ── Introspection ─────────────────────────────────────────────────
90
126
  # Introspector preset:
91
127
  # :full — all 28 introspectors (default)
92
- # :standard — 13 core introspectors
128
+ # :standard — 13 core introspectors (schema, models, routes, jobs, gems,
129
+ # conventions, controllers, tests, migrations, stimulus,
130
+ # view_templates, design_tokens, config)
93
131
  # config.preset = :full
94
132
 
133
+ # Context mode: :compact (default, ≤150 lines) or :full (dumps everything)
134
+ # config.context_mode = :compact
135
+
136
+ # Max lines for CLAUDE.md in compact mode
137
+ # config.claude_max_lines = 150
138
+
139
+ # Whether to generate root files (CLAUDE.md, AGENTS.md, etc.)
140
+ # Set false to only generate split rules (.claude/rules/, .cursor/rules/, etc.)
141
+ # config.generate_root_files = true
142
+
143
+ # ── Models & Filtering ────────────────────────────────────────────
95
144
  # Models to exclude from introspection
96
145
  # config.excluded_models += %w[AdminUser InternalThing]
97
146
 
98
- # Context mode: :compact (default, ≤150 lines) or :full (dumps everything)
99
- # config.context_mode = :compact
147
+ # Controllers to exclude from listings
148
+ # config.excluded_controllers += %w[Admin::BaseController]
149
+
150
+ # Route prefixes to hide with app_only filter
151
+ # config.excluded_route_prefixes += %w[sidekiq/]
152
+
153
+ # ── MCP Server ────────────────────────────────────────────────────
154
+ # Cache TTL in seconds for introspection data
155
+ # config.cache_ttl = 60
156
+
157
+ # Max characters for any single tool response (safety net)
158
+ # config.max_tool_response_chars = 200_000
100
159
 
101
160
  # Live reload: auto-invalidate MCP tool caches on file changes
161
+ # :auto — enable if `listen` gem is available (default)
162
+ # true — enable, raise if `listen` gem is missing
163
+ # false — disable entirely
102
164
  # config.live_reload = :auto
165
+
166
+ # Auto-mount HTTP MCP endpoint (for HTTP transport)
167
+ # config.auto_mount = false
168
+ # config.http_path = "/mcp"
169
+ # config.http_port = 6029
170
+
171
+ # ── File Size Limits ──────────────────────────────────────────────
172
+ # Increase for larger projects
173
+ # config.max_file_size = 5_000_000 # Per-file read (5MB)
174
+ # config.max_test_file_size = 1_000_000 # Test file read (1MB)
175
+ # config.max_schema_file_size = 10_000_000 # schema.rb parse (10MB)
176
+ # config.max_view_total_size = 10_000_000 # Aggregated view content (10MB)
177
+ # config.max_view_file_size = 1_000_000 # Per-view file (1MB)
178
+ # config.max_search_results = 200 # Max search results per call
179
+ # config.max_validate_files = 50 # Max files per validate call
180
+
181
+ # ── Extensibility ─────────────────────────────────────────────────
182
+ # Register additional MCP tool classes alongside the 25 built-in tools
183
+ # config.custom_tools = [MyApp::CustomTool]
184
+
185
+ # Exclude specific built-in tools by name
186
+ # config.skip_tools = %w[rails_security_scan]
187
+
188
+ # ── Security ──────────────────────────────────────────────────────
189
+ # Paths excluded from code search
190
+ # config.excluded_paths += %w[vendor/cache]
191
+
192
+ # File patterns blocked from search and read tools
193
+ # config.sensitive_patterns += %w[config/secrets.yml]
194
+
195
+ # ── Search ────────────────────────────────────────────────────────
196
+ # File extensions for fallback search (when ripgrep unavailable)
197
+ # config.search_extensions = %w[rb js erb yml yaml json ts tsx vue svelte haml slim]
198
+
199
+ # Where to look for concern source files
200
+ # config.concern_paths = %w[app/models/concerns app/controllers/concerns]
103
201
  end
104
202
  RUBY
105
203
 
@@ -160,13 +258,22 @@ module RailsAiContext
160
258
  say ""
161
259
  say "Commands:", :yellow
162
260
  say " rails ai:context # Regenerate context files"
163
- say " rails ai:serve # Start MCP server (25 live tools)"
261
+ say " rails 'ai:tool[schema]' # Run any of the 25 tools from CLI"
262
+ if @tool_mode == :mcp
263
+ say " rails ai:serve # Start MCP server (25 live tools)"
264
+ end
164
265
  say " rails ai:doctor # Check AI readiness"
165
266
  say " rails ai:inspect # Print introspection summary"
166
267
  say ""
167
- say "MCP auto-discovery:", :yellow
168
- say " .mcp.json is auto-detected by Claude Code and Cursor."
169
- say " No manual config needed just open your project."
268
+ if @tool_mode == :mcp
269
+ say "MCP auto-discovery:", :yellow
270
+ say " .mcp.json is auto-detected by Claude Code and Cursor."
271
+ say " No manual config needed — just open your project."
272
+ else
273
+ say "CLI tools:", :yellow
274
+ say " AI agents can run `rails 'ai:tool[schema]' table=users` directly."
275
+ say " No MCP server needed — tools work from the terminal."
276
+ end
170
277
  say ""
171
278
  say "To add more AI tools later:", :yellow
172
279
  say " rails ai:context:cursor # Generate for Cursor"