rails_skills 0.1.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +99 -0
- data/Rakefile +5 -0
- data/lib/generators/rails_skills/commands_library/quality.md +16 -0
- data/lib/generators/rails_skills/install/install_generator.rb +211 -0
- data/lib/generators/rails_skills/install/templates/agents/api-dev.md.tt +28 -0
- data/lib/generators/rails_skills/install/templates/agents/fullstack-dev.md.tt +28 -0
- data/lib/generators/rails_skills/install/templates/agents/rails-developer.md.tt +22 -0
- data/lib/generators/rails_skills/install/templates/settings.local.json.tt +11 -0
- data/lib/generators/rails_skills/rules_library/code-style.md +28 -0
- data/lib/generators/rails_skills/rules_library/security.md +33 -0
- data/lib/generators/rails_skills/rules_library/testing.md +27 -0
- data/lib/generators/rails_skills/skill/skill_generator.rb +46 -0
- data/lib/generators/rails_skills/skill/templates/SKILL.md.tt +29 -0
- data/lib/generators/rails_skills/skills_library/rails-api-controllers/SKILL.md +106 -0
- data/lib/generators/rails_skills/skills_library/rails-controllers/SKILL.md +125 -0
- data/lib/generators/rails_skills/skills_library/rails-hotwire/SKILL.md +89 -0
- data/lib/generators/rails_skills/skills_library/rails-jobs/SKILL.md +39 -0
- data/lib/generators/rails_skills/skills_library/rails-models/SKILL.md +105 -0
- data/lib/generators/rails_skills/skills_library/rails-views/SKILL.md +109 -0
- data/lib/generators/rails_skills/skills_library/rspec-testing/SKILL.md +105 -0
- data/lib/rails_skills/railtie.rb +10 -0
- data/lib/rails_skills/version.rb +5 -0
- data/lib/rails_skills.rb +12 -0
- metadata +86 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 178573c6ee15fecc50390d962b0497fe63f76caa23a763105bb02cf2bd035742
|
|
4
|
+
data.tar.gz: 38fe007e723b016ea6ba499681baa7e76b2cdadbe59d8221697e60cd3719c31b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 58f7d7ea5fd40d5467f11182985ccecd43395f0a2e31aad41894d9a955088ef8c577e93568be38667a2a08e7f66f59bfea57995ad7fcb6a6993f90d7e3e46ad6
|
|
7
|
+
data.tar.gz: 1303af0ddab82bb8c0eae537997ca52b5ecf945bc1df025f23da37bf027d774826591249a0c7164bd61cdbe3ba088d23a454c17e7ce9036f430bd84ce1d9a97a
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sergii Mostovyi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# RailsSkills
|
|
2
|
+
|
|
3
|
+
A Ruby gem that organizes AI skills for Rails projects, shared between **Claude** and **Codex**.
|
|
4
|
+
|
|
5
|
+
RailsSkills creates a `skills/` directory in your Rails root as the canonical location for AI skill definitions, then symlinks it into `.claude/skills` and `.codex/skills` so both AI assistants share the same knowledge base.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add to your Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "rails_skills"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bundle install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Install with default (basic) preset
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
rails generate rails_skills:install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Install with a preset
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
rails generate rails_skills:install --preset=basic
|
|
33
|
+
rails generate rails_skills:install --preset=fullstack
|
|
34
|
+
rails generate rails_skills:install --preset=api
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### What it creates
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
your_rails_app/
|
|
41
|
+
├── skills/ # Shared AI skill files (canonical location)
|
|
42
|
+
│ ├── rails-models/
|
|
43
|
+
│ │ └── SKILL.md
|
|
44
|
+
│ ├── rails-controllers/
|
|
45
|
+
│ │ └── SKILL.md
|
|
46
|
+
│ └── rails-views/
|
|
47
|
+
│ └── SKILL.md
|
|
48
|
+
├── .claude/
|
|
49
|
+
│ ├── skills -> ../skills # Symlink to shared skills
|
|
50
|
+
│ ├── agents/
|
|
51
|
+
│ ├── commands/
|
|
52
|
+
│ ├── rules/
|
|
53
|
+
│ └── settings.local.json
|
|
54
|
+
└── .codex/
|
|
55
|
+
└── skills -> ../skills # Symlink to shared skills
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Both Claude and Codex read from the same `skills/` directory via symlinks.
|
|
59
|
+
|
|
60
|
+
### Presets
|
|
61
|
+
|
|
62
|
+
| Preset | Skills included |
|
|
63
|
+
|--------|----------------|
|
|
64
|
+
| **basic** | rails-models, rails-controllers, rails-views |
|
|
65
|
+
| **fullstack** | basic + rails-hotwire, rspec-testing |
|
|
66
|
+
| **api** | rails-models, rails-api-controllers, rspec-testing |
|
|
67
|
+
|
|
68
|
+
### Create a custom skill
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
rails generate rails_skills:skill my_custom_skill
|
|
72
|
+
rails generate rails_skills:skill my_custom_skill --description="My skill description"
|
|
73
|
+
rails generate rails_skills:skill my_custom_skill --with-references
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Skills are created in `skills/` and automatically available to both Claude and Codex.
|
|
77
|
+
|
|
78
|
+
## Skill Library
|
|
79
|
+
|
|
80
|
+
The gem ships with these pre-built skills:
|
|
81
|
+
|
|
82
|
+
- **rails-models** - ActiveRecord patterns, migrations, validations, associations
|
|
83
|
+
- **rails-controllers** - Controller actions, routing, REST conventions, filters
|
|
84
|
+
- **rails-views** - ERB templates, layouts, partials, forms, helpers
|
|
85
|
+
- **rails-hotwire** - Turbo Drive, Turbo Frames, Turbo Streams, Stimulus
|
|
86
|
+
- **rails-api-controllers** - API-only controllers, serialization, versioning
|
|
87
|
+
- **rspec-testing** - RSpec patterns for models, requests, and system tests
|
|
88
|
+
- **rails-jobs** - Active Job patterns, background processing
|
|
89
|
+
|
|
90
|
+
## How It Works
|
|
91
|
+
|
|
92
|
+
1. `skills/` is the single source of truth for AI skill files
|
|
93
|
+
2. `.claude/skills` is a symlink pointing to `../skills`
|
|
94
|
+
3. `.codex/skills` is a symlink pointing to `../skills`
|
|
95
|
+
4. Edit skills in `skills/` and both AI tools see the changes immediately
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run code quality checks
|
|
3
|
+
allowed-tools: Bash, Read
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Quality Check
|
|
7
|
+
|
|
8
|
+
Run the following quality checks on the project and report results:
|
|
9
|
+
|
|
10
|
+
1. **Linting**: Run `bundle exec rubocop` and report any violations
|
|
11
|
+
2. **Tests**: Run `bundle exec rspec` and report failures
|
|
12
|
+
3. **Security**: Run `bundle exec brakeman --no-pager` if available
|
|
13
|
+
|
|
14
|
+
Summarize findings and suggest fixes for any issues found.
|
|
15
|
+
|
|
16
|
+
Use $ARGUMENTS to scope the check (e.g., a specific file or directory).
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RailsSkills
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
class_option :preset, type: :string, default: "basic",
|
|
11
|
+
desc: "Preset bundle (basic, fullstack, api)"
|
|
12
|
+
class_option :skip_agents, type: :boolean, default: false,
|
|
13
|
+
desc: "Don't create default agents"
|
|
14
|
+
|
|
15
|
+
def create_skills_directory
|
|
16
|
+
empty_directory "skills"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_claude_directory
|
|
20
|
+
empty_directory ".claude"
|
|
21
|
+
empty_directory ".claude/commands"
|
|
22
|
+
empty_directory ".claude/rules"
|
|
23
|
+
empty_directory ".claude/agents" unless options[:skip_agents]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_codex_directory
|
|
27
|
+
empty_directory ".codex"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create_symlinks
|
|
31
|
+
create_symlink(".claude/skills", "../skills")
|
|
32
|
+
create_symlink(".codex/skills", "../skills")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def copy_claude_settings
|
|
36
|
+
template "settings.local.json.tt", ".claude/settings.local.json"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def install_preset_skills
|
|
40
|
+
case options[:preset]
|
|
41
|
+
when "fullstack"
|
|
42
|
+
install_fullstack_preset
|
|
43
|
+
when "api"
|
|
44
|
+
install_api_preset
|
|
45
|
+
else
|
|
46
|
+
install_basic_preset
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def show_instructions
|
|
51
|
+
say ""
|
|
52
|
+
say "RailsSkills installed successfully!", :green
|
|
53
|
+
say ""
|
|
54
|
+
say "Directory structure:", :yellow
|
|
55
|
+
say " skills/ <- shared AI skill files (canonical location)"
|
|
56
|
+
say " .claude/skills -> ../skills (symlink)"
|
|
57
|
+
say " .codex/skills -> ../skills (symlink)"
|
|
58
|
+
say ""
|
|
59
|
+
say "Both Claude and Codex now share the same skills from skills/", :blue
|
|
60
|
+
say ""
|
|
61
|
+
say "Next steps:", :yellow
|
|
62
|
+
say " rails g rails_skills:skill my_skill # Create a custom skill"
|
|
63
|
+
say ""
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def create_symlink(link_path, target)
|
|
69
|
+
dest = File.join(destination_root, link_path)
|
|
70
|
+
if File.symlink?(dest) || File.exist?(dest)
|
|
71
|
+
say_status :exist, link_path, :blue
|
|
72
|
+
else
|
|
73
|
+
File.symlink(target, dest)
|
|
74
|
+
say_status :symlink, "#{link_path} -> #{target}", :green
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def install_basic_preset
|
|
79
|
+
say "Installing basic preset...", :green
|
|
80
|
+
install_skill("rails-models")
|
|
81
|
+
install_skill("rails-controllers")
|
|
82
|
+
install_skill("rails-views")
|
|
83
|
+
install_rule("code-style")
|
|
84
|
+
install_rule("testing")
|
|
85
|
+
install_command("quality")
|
|
86
|
+
create_basic_agent unless options[:skip_agents]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def install_fullstack_preset
|
|
90
|
+
say "Installing fullstack preset...", :green
|
|
91
|
+
install_skill("rails-models")
|
|
92
|
+
install_skill("rails-controllers")
|
|
93
|
+
install_skill("rails-views")
|
|
94
|
+
install_skill("rails-hotwire")
|
|
95
|
+
install_skill("rspec-testing")
|
|
96
|
+
install_rule("code-style")
|
|
97
|
+
install_rule("testing")
|
|
98
|
+
install_rule("security")
|
|
99
|
+
install_command("quality")
|
|
100
|
+
create_fullstack_agent unless options[:skip_agents]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def install_api_preset
|
|
104
|
+
say "Installing API preset...", :green
|
|
105
|
+
install_skill("rails-models")
|
|
106
|
+
install_skill("rails-api-controllers")
|
|
107
|
+
install_skill("rspec-testing")
|
|
108
|
+
install_rule("code-style")
|
|
109
|
+
install_rule("testing")
|
|
110
|
+
install_rule("security")
|
|
111
|
+
install_command("quality")
|
|
112
|
+
create_api_agent unless options[:skip_agents]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def install_skill(skill_name)
|
|
116
|
+
skill_dir = "skills/#{skill_name}"
|
|
117
|
+
empty_directory skill_dir
|
|
118
|
+
|
|
119
|
+
skill_source = File.expand_path("../skills_library/#{skill_name}", __dir__)
|
|
120
|
+
if File.directory?(skill_source)
|
|
121
|
+
directory skill_source, skill_dir
|
|
122
|
+
else
|
|
123
|
+
create_file "#{skill_dir}/SKILL.md", default_skill_content(skill_name)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def install_rule(rule_name)
|
|
128
|
+
rule_file = ".claude/rules/#{rule_name}.md"
|
|
129
|
+
rule_source = File.expand_path("../rules_library/#{rule_name}.md", __dir__)
|
|
130
|
+
|
|
131
|
+
if File.exist?(rule_source)
|
|
132
|
+
copy_file rule_source, rule_file
|
|
133
|
+
else
|
|
134
|
+
create_file rule_file, default_rule_content(rule_name)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def install_command(command_name)
|
|
139
|
+
command_file = ".claude/commands/#{command_name}.md"
|
|
140
|
+
command_source = File.expand_path("../commands_library/#{command_name}.md", __dir__)
|
|
141
|
+
|
|
142
|
+
if File.exist?(command_source)
|
|
143
|
+
copy_file command_source, command_file
|
|
144
|
+
else
|
|
145
|
+
create_file command_file, default_command_content(command_name)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def create_basic_agent
|
|
150
|
+
template "agents/rails-developer.md.tt", ".claude/agents/rails-developer.md"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def create_fullstack_agent
|
|
154
|
+
template "agents/fullstack-dev.md.tt", ".claude/agents/fullstack-dev.md"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def create_api_agent
|
|
158
|
+
template "agents/api-dev.md.tt", ".claude/agents/api-dev.md"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def default_skill_content(skill_name)
|
|
162
|
+
<<~SKILL
|
|
163
|
+
---
|
|
164
|
+
name: #{skill_name}
|
|
165
|
+
description: #{skill_name.tr('-', ' ').capitalize} skill
|
|
166
|
+
version: 1.0.0
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
# #{skill_name.tr('-', ' ').capitalize}
|
|
170
|
+
|
|
171
|
+
Add your skill content here.
|
|
172
|
+
SKILL
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def default_rule_content(rule_name)
|
|
176
|
+
<<~RULE
|
|
177
|
+
# #{rule_name.tr('-', ' ').capitalize} Rules
|
|
178
|
+
|
|
179
|
+
Add your project rules and guidelines here.
|
|
180
|
+
RULE
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def default_command_content(command_name)
|
|
184
|
+
<<~COMMAND
|
|
185
|
+
---
|
|
186
|
+
description: #{command_name.tr('-', ' ').capitalize} command
|
|
187
|
+
allowed-tools: Bash, Read, Edit, Write
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## #{command_name.tr('-', ' ').capitalize}
|
|
191
|
+
|
|
192
|
+
Add your command instructions here.
|
|
193
|
+
|
|
194
|
+
Use $ARGUMENTS to reference command arguments.
|
|
195
|
+
COMMAND
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def app_name
|
|
199
|
+
Rails.application.class.module_parent_name
|
|
200
|
+
rescue StandardError
|
|
201
|
+
"MyApp"
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def rails_version
|
|
205
|
+
Rails::VERSION::STRING
|
|
206
|
+
rescue StandardError
|
|
207
|
+
"7.0"
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# API Developer Agent
|
|
2
|
+
|
|
3
|
+
You are an API-focused Rails developer working on **<%= app_name %>** (Rails <%= rails_version %>).
|
|
4
|
+
|
|
5
|
+
## Skills
|
|
6
|
+
|
|
7
|
+
Load and follow all skills from the `skills/` directory, with emphasis on:
|
|
8
|
+
- Rails models
|
|
9
|
+
- API controllers
|
|
10
|
+
- RSpec testing
|
|
11
|
+
|
|
12
|
+
## Guidelines
|
|
13
|
+
|
|
14
|
+
- Build RESTful JSON APIs
|
|
15
|
+
- Use proper HTTP status codes
|
|
16
|
+
- Implement authentication and authorization
|
|
17
|
+
- Write comprehensive API tests
|
|
18
|
+
- Document endpoints clearly
|
|
19
|
+
- Follow JSON:API or similar conventions
|
|
20
|
+
|
|
21
|
+
## Workflow
|
|
22
|
+
|
|
23
|
+
1. Understand the API requirement
|
|
24
|
+
2. Design the endpoint (HTTP method, path, request/response format)
|
|
25
|
+
3. Start with the model and migrations
|
|
26
|
+
4. Build the API controller
|
|
27
|
+
5. Write request specs
|
|
28
|
+
6. Document the endpoint
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Fullstack Developer Agent
|
|
2
|
+
|
|
3
|
+
You are a fullstack Rails developer working on **<%= app_name %>** (Rails <%= rails_version %>).
|
|
4
|
+
|
|
5
|
+
## Skills
|
|
6
|
+
|
|
7
|
+
Load and follow all skills from the `skills/` directory, with emphasis on:
|
|
8
|
+
- Rails models, controllers, and views
|
|
9
|
+
- Hotwire (Turbo + Stimulus)
|
|
10
|
+
- RSpec testing
|
|
11
|
+
|
|
12
|
+
## Guidelines
|
|
13
|
+
|
|
14
|
+
- Follow Rails conventions and best practices
|
|
15
|
+
- Build reactive UIs with Turbo Frames and Turbo Streams
|
|
16
|
+
- Use Stimulus for JavaScript behavior
|
|
17
|
+
- Write comprehensive RSpec tests
|
|
18
|
+
- Use the project's existing patterns and style
|
|
19
|
+
|
|
20
|
+
## Workflow
|
|
21
|
+
|
|
22
|
+
1. Understand the requirement
|
|
23
|
+
2. Plan the full-stack implementation (model, controller, views)
|
|
24
|
+
3. Start with the model and migrations
|
|
25
|
+
4. Build the controller with proper actions
|
|
26
|
+
5. Create views with Hotwire integration
|
|
27
|
+
6. Write RSpec tests for all layers
|
|
28
|
+
7. Verify everything works end-to-end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Rails Developer Agent
|
|
2
|
+
|
|
3
|
+
You are a Rails developer working on **<%= app_name %>** (Rails <%= rails_version %>).
|
|
4
|
+
|
|
5
|
+
## Skills
|
|
6
|
+
|
|
7
|
+
Load and follow all skills from the `skills/` directory.
|
|
8
|
+
|
|
9
|
+
## Guidelines
|
|
10
|
+
|
|
11
|
+
- Follow Rails conventions and best practices
|
|
12
|
+
- Write clean, tested code
|
|
13
|
+
- Use the project's existing patterns and style
|
|
14
|
+
- Prefer simple solutions over clever ones
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
1. Understand the requirement
|
|
19
|
+
2. Check existing code for patterns
|
|
20
|
+
3. Implement following Rails conventions
|
|
21
|
+
4. Write tests
|
|
22
|
+
5. Verify everything works
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Code Style Rules
|
|
2
|
+
|
|
3
|
+
## Ruby Style
|
|
4
|
+
|
|
5
|
+
- Use 2 spaces for indentation (not tabs)
|
|
6
|
+
- Prefer double quotes for strings
|
|
7
|
+
- Use modern Ruby syntax (Ruby 3.0+)
|
|
8
|
+
- Prefer `&.` safe navigation over conditional checks
|
|
9
|
+
- Use trailing commas in multi-line arrays and hashes
|
|
10
|
+
|
|
11
|
+
## Rails Conventions
|
|
12
|
+
|
|
13
|
+
- Follow RESTful routing patterns
|
|
14
|
+
- Keep controllers thin, models focused
|
|
15
|
+
- Use `before_action` for shared controller setup
|
|
16
|
+
- Use strong parameters for mass assignment protection
|
|
17
|
+
- Prefer ActiveRecord query methods over raw SQL
|
|
18
|
+
|
|
19
|
+
## Naming
|
|
20
|
+
|
|
21
|
+
- snake_case for variables, methods, and file names
|
|
22
|
+
- PascalCase for classes and modules
|
|
23
|
+
- Prefix boolean methods with `?` (e.g., `published?`)
|
|
24
|
+
- Prefix destructive methods with `!` (e.g., `publish!`)
|
|
25
|
+
|
|
26
|
+
## Auto-Fixing
|
|
27
|
+
|
|
28
|
+
Run `bundle exec rubocop -a` to fix style violations before committing.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Security Rules
|
|
2
|
+
|
|
3
|
+
## Input Handling
|
|
4
|
+
|
|
5
|
+
- Always use strong parameters in controllers
|
|
6
|
+
- Never trust user input - validate and sanitize
|
|
7
|
+
- Use parameterized queries (ActiveRecord handles this by default)
|
|
8
|
+
- Never interpolate user input into SQL strings
|
|
9
|
+
|
|
10
|
+
## Authentication
|
|
11
|
+
|
|
12
|
+
- Use established libraries (Devise, etc.) for authentication
|
|
13
|
+
- Store passwords with bcrypt (`has_secure_password`)
|
|
14
|
+
- Use CSRF protection (enabled by default in Rails)
|
|
15
|
+
- Implement proper session management
|
|
16
|
+
|
|
17
|
+
## Authorization
|
|
18
|
+
|
|
19
|
+
- Check permissions in every controller action
|
|
20
|
+
- Use authorization libraries (Pundit, CanCanCan) for complex rules
|
|
21
|
+
- Never rely on hiding UI elements as a security measure
|
|
22
|
+
|
|
23
|
+
## Output
|
|
24
|
+
|
|
25
|
+
- ERB auto-escapes output by default - don't bypass with `raw` or `html_safe` unless necessary
|
|
26
|
+
- Sanitize HTML content with `sanitize` helper
|
|
27
|
+
- Set proper Content Security Policy headers
|
|
28
|
+
|
|
29
|
+
## Secrets
|
|
30
|
+
|
|
31
|
+
- Never commit secrets, API keys, or credentials to git
|
|
32
|
+
- Use Rails credentials (`rails credentials:edit`) or environment variables
|
|
33
|
+
- Add sensitive files to `.gitignore`
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Testing Rules
|
|
2
|
+
|
|
3
|
+
## General
|
|
4
|
+
|
|
5
|
+
- Every feature must have tests
|
|
6
|
+
- Test behavior, not implementation details
|
|
7
|
+
- Keep tests fast and independent
|
|
8
|
+
- Use factories (FactoryBot) over fixtures
|
|
9
|
+
|
|
10
|
+
## Test Types
|
|
11
|
+
|
|
12
|
+
- **Model specs** for validations, associations, and business logic
|
|
13
|
+
- **Request specs** for controller actions and API endpoints
|
|
14
|
+
- **System specs** for user-facing workflows (use sparingly)
|
|
15
|
+
|
|
16
|
+
## Conventions
|
|
17
|
+
|
|
18
|
+
- One assertion per test when practical
|
|
19
|
+
- Use `let` for lazy setup, `let!` when eager evaluation is needed
|
|
20
|
+
- Use `describe` for the subject, `context` for conditions, `it` for behavior
|
|
21
|
+
- Name tests clearly: `it "returns published posts for active users"`
|
|
22
|
+
|
|
23
|
+
## Running Tests
|
|
24
|
+
|
|
25
|
+
- `bundle exec rspec` to run all tests
|
|
26
|
+
- `bundle exec rspec spec/models/` to run model specs
|
|
27
|
+
- `bundle exec rspec spec/file.rb:42` to run a specific test
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module RailsSkills
|
|
6
|
+
module Generators
|
|
7
|
+
class SkillGenerator < Rails::Generators::NamedBase
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
class_option :description, type: :string, default: nil,
|
|
11
|
+
desc: "Skill description"
|
|
12
|
+
class_option :with_references, type: :boolean, default: false,
|
|
13
|
+
desc: "Create references directory"
|
|
14
|
+
|
|
15
|
+
def create_skill_directory
|
|
16
|
+
empty_directory skill_path
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_skill_file
|
|
20
|
+
template "SKILL.md.tt", "#{skill_path}/SKILL.md"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create_references_directory
|
|
24
|
+
return unless options[:with_references]
|
|
25
|
+
|
|
26
|
+
empty_directory "#{skill_path}/references"
|
|
27
|
+
create_file "#{skill_path}/references/.keep", ""
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def show_instructions
|
|
31
|
+
say "\nSkill '#{file_name}' created in #{skill_path}/", :green
|
|
32
|
+
say "This skill is available to both Claude and Codex via symlinks.", :blue
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def skill_path
|
|
38
|
+
"skills/#{file_name}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def skill_description
|
|
42
|
+
options[:description] || "Custom skill for #{file_name.tr('-', ' ')}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: <%= file_name %>
|
|
3
|
+
description: <%= skill_description %>
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# <%= file_name.tr('-', ' ').split.map(&:capitalize).join(' ') %>
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
| Command | Purpose |
|
|
12
|
+
|---------|---------|
|
|
13
|
+
| TODO | Add commands here |
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
<%= skill_description %>
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Add usage examples and patterns here.
|
|
22
|
+
|
|
23
|
+
## Common Patterns
|
|
24
|
+
|
|
25
|
+
Add frequently used code patterns here.
|
|
26
|
+
|
|
27
|
+
## Best Practices
|
|
28
|
+
|
|
29
|
+
Add best practices and conventions here.
|