ruby_llm-skills 0.1.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +77 -316
- data/lib/generators/skill/USAGE +29 -0
- data/lib/generators/skill/skill_generator.rb +14 -5
- data/lib/generators/skill/templates/SKILL.md.tt +43 -7
- data/lib/ruby_llm/skills/agent_extensions.rb +148 -0
- data/lib/ruby_llm/skills/chat_extensions.rb +85 -32
- data/lib/ruby_llm/skills/composite_loader.rb +1 -1
- data/lib/ruby_llm/skills/database_loader.rb +20 -91
- data/lib/ruby_llm/skills/error.rb +1 -1
- data/lib/ruby_llm/skills/filesystem_loader.rb +43 -10
- data/lib/ruby_llm/skills/loader.rb +1 -1
- data/lib/ruby_llm/skills/parser.rb +1 -1
- data/lib/ruby_llm/skills/railtie.rb +14 -5
- data/lib/ruby_llm/skills/skill.rb +21 -6
- data/lib/ruby_llm/skills/skill_tool.rb +82 -40
- data/lib/ruby_llm/skills/validator.rb +1 -1
- data/lib/ruby_llm/skills/version.rb +2 -2
- data/lib/ruby_llm/skills.rb +60 -24
- metadata +20 -5
- data/lib/ruby_llm/skills/zip_loader.rb +0 -129
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '048ac6f6a76a7fd48994d208799b967754b25ecc3959acd56d44f5ab707f9f8d'
|
|
4
|
+
data.tar.gz: 268827da6d73359d9451b159b1abe68dea7881419df6b473cceeb2d8c74bc073
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: febe501ab666f7e1cdf06e043ab44305ea065ffe561508b6fdcb9a959a90eabad8d2cb9fcc90384536eaf0871f73f2e52c3c9e93b8d883fbe8823274f547f0f3
|
|
7
|
+
data.tar.gz: 73226c3f1eb42ba6073dbfdcccb9f334896e078ca04ab1814260feb4218d432a83cf92817a32bb6c1abe847cf7fcd0098259aa2bab5886ce933d2c258d4ae8f1
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-02-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `RubyLLM::Agent` integration via `RubyLLM::Skills::AgentExtensions`
|
|
13
|
+
- Class-level `skills` DSL on agent subclasses with source, `only:`, and proc support
|
|
14
|
+
- Instance-level `with_skills` for runtime agent skill configuration
|
|
15
|
+
- Agent-specific unit and integration test coverage
|
|
16
|
+
- Compatibility tests for delegate fallback behavior
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Tightened `ruby_llm` dependency from open lower bound to `~> 1.12`
|
|
21
|
+
- Added explicit runtime compatibility checks for required `RubyLLM::Agent` hooks
|
|
22
|
+
- Documented `agent.with_skills(...)` replacement semantics in README
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Dynamic skill blocks resolving to `nil` or `[]` no longer silently load default skills
|
|
27
|
+
- Skill source normalization and validation now prevent nested/invalid source runtime crashes
|
|
28
|
+
- Delegate fallback now supports common delegation options (`prefix`, `allow_nil`, `private`)
|
|
29
|
+
|
|
8
30
|
## [0.1.0] - 2025-01-15
|
|
9
31
|
|
|
10
32
|
### Added
|
data/README.md
CHANGED
|
@@ -2,15 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Agent Skills for [RubyLLM](https://github.com/crmne/ruby_llm). Teach your AI how to do things your way.
|
|
4
4
|
|
|
5
|
-
Skills are folders of instructions, scripts, and resources that extend LLM capabilities for specialized tasks. This gem implements the [Agent Skills specification](https://agentskills.io/specification) for RubyLLM.
|
|
6
|
-
|
|
7
5
|
[](https://badge.fury.io/rb/ruby_llm-skills)
|
|
8
6
|
[](https://github.com/kieranklaassen/ruby_llm-skills/actions)
|
|
7
|
+
[](https://github.com/EveryInc/compound-engineering-plugin)
|
|
9
8
|
|
|
10
9
|
## Installation
|
|
11
10
|
|
|
12
|
-
Add this line to your application's Gemfile:
|
|
13
|
-
|
|
14
11
|
```ruby
|
|
15
12
|
gem "ruby_llm-skills"
|
|
16
13
|
```
|
|
@@ -19,378 +16,142 @@ gem "ruby_llm-skills"
|
|
|
19
16
|
|
|
20
17
|
```ruby
|
|
21
18
|
chat = RubyLLM.chat
|
|
22
|
-
chat.with_skills # Load skills from app/skills
|
|
23
|
-
chat.ask "Create a PDF report from this data"
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
That's it. Skills are discovered automatically and injected into the system prompt.
|
|
27
|
-
|
|
28
|
-
## How It Works
|
|
29
|
-
|
|
30
|
-
Skills follow a three-level progressive disclosure pattern:
|
|
31
|
-
|
|
32
|
-
1. **Metadata** - Name and description loaded at startup (~100 tokens per skill)
|
|
33
|
-
2. **Instructions** - Full SKILL.md loaded when skill triggers
|
|
34
|
-
3. **Resources** - Scripts and references loaded on demand
|
|
35
|
-
|
|
36
|
-
This keeps context lean while making capabilities available.
|
|
37
|
-
|
|
38
|
-
## Configuration
|
|
39
|
-
|
|
40
|
-
```ruby
|
|
41
|
-
RubyLLM::Skills.default_path = "lib/skills" # Default: app/skills
|
|
42
|
-
RubyLLM::Skills.logger = Rails.logger # Default: nil
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Loading Skills
|
|
46
|
-
|
|
47
|
-
### From Filesystem (Default)
|
|
48
|
-
|
|
49
|
-
```ruby
|
|
50
|
-
# Load from default path (app/skills)
|
|
51
19
|
chat.with_skills
|
|
52
|
-
|
|
53
|
-
# Load from specific directory
|
|
54
|
-
chat.with_skills(from: "lib/skills")
|
|
55
|
-
|
|
56
|
-
# Load specific skills only
|
|
57
|
-
chat.with_skills(only: [:pdf_report, :data_analysis])
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### From Multiple Sources
|
|
61
|
-
|
|
62
|
-
Pass an array to load from multiple locations:
|
|
63
|
-
|
|
64
|
-
```ruby
|
|
65
|
-
chat.with_skills(from: [
|
|
66
|
-
"app/skills", # Directory
|
|
67
|
-
"extras/skills.zip", # Zip file
|
|
68
|
-
current_user.skills # ActiveRecord relation
|
|
69
|
-
])
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Sources are loaded in order. Later skills with the same name override earlier ones.
|
|
73
|
-
|
|
74
|
-
### From Database
|
|
75
|
-
|
|
76
|
-
Store complete skills in your database for per-user customization. Two storage formats are supported:
|
|
77
|
-
|
|
78
|
-
**Option A: Store as text (SKILL.md content)**
|
|
79
|
-
|
|
80
|
-
```ruby
|
|
81
|
-
# Migration
|
|
82
|
-
create_table :skills do |t|
|
|
83
|
-
t.string :name, null: false
|
|
84
|
-
t.text :description, null: false
|
|
85
|
-
t.text :content, null: false # Full SKILL.md content
|
|
86
|
-
t.references :user
|
|
87
|
-
t.timestamps
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Model
|
|
91
|
-
class Skill < ApplicationRecord
|
|
92
|
-
belongs_to :user, optional: true
|
|
93
|
-
|
|
94
|
-
validates :name, format: { with: /\A[a-z0-9-]+\z/ }
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Create a skill
|
|
98
|
-
current_user.skills.create!(
|
|
99
|
-
name: "my-workflow",
|
|
100
|
-
description: "Custom workflow for data processing",
|
|
101
|
-
content: <<~SKILL
|
|
102
|
-
# My Workflow
|
|
103
|
-
|
|
104
|
-
## Steps
|
|
105
|
-
1. Load the data
|
|
106
|
-
2. Process with custom rules
|
|
107
|
-
3. Export results
|
|
108
|
-
SKILL
|
|
109
|
-
)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**Option B: Store as binary (zip file)**
|
|
113
|
-
|
|
114
|
-
For skills with scripts, references, or assets:
|
|
115
|
-
|
|
116
|
-
```ruby
|
|
117
|
-
# Migration
|
|
118
|
-
create_table :skills do |t|
|
|
119
|
-
t.string :name, null: false
|
|
120
|
-
t.text :description, null: false
|
|
121
|
-
t.binary :data, null: false # Zip file blob
|
|
122
|
-
t.references :user
|
|
123
|
-
t.timestamps
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Model
|
|
127
|
-
class Skill < ApplicationRecord
|
|
128
|
-
belongs_to :user, optional: true
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Upload a skill zip
|
|
132
|
-
skill_zip = File.read("my-skill.zip")
|
|
133
|
-
current_user.skills.create!(
|
|
134
|
-
name: "pdf-report",
|
|
135
|
-
description: "Generate PDF reports with charts",
|
|
136
|
-
data: skill_zip
|
|
137
|
-
)
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
**Loading database skills**
|
|
141
|
-
|
|
142
|
-
```ruby
|
|
143
|
-
# Combine app skills with user's custom skills
|
|
144
|
-
chat.with_skills(from: [
|
|
145
|
-
"app/skills", # Base skills from filesystem
|
|
146
|
-
current_user.skills # User's skills from database
|
|
147
|
-
])
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
The gem detects the storage format automatically:
|
|
151
|
-
- Records with `content` field → parsed as SKILL.md text
|
|
152
|
-
- Records with `data` field → extracted as zip
|
|
153
|
-
|
|
154
|
-
### From Zip Files
|
|
155
|
-
|
|
156
|
-
```ruby
|
|
157
|
-
chat.with_skills(from: "skills.zip")
|
|
158
|
-
chat.with_skills(from: ["core.zip", "custom.zip"])
|
|
20
|
+
chat.ask "Create a PDF report from this data"
|
|
159
21
|
```
|
|
160
22
|
|
|
161
|
-
|
|
23
|
+
The LLM discovers skills, calls the skill tool, and gets instructions.
|
|
162
24
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
| Input | Type |
|
|
166
|
-
|-------|------|
|
|
167
|
-
| String ending in `/` or directory path | Filesystem |
|
|
168
|
-
| String ending in `.zip` | Zip file |
|
|
169
|
-
| ActiveRecord relation or array of objects | Database |
|
|
170
|
-
|
|
171
|
-
## Rails Integration
|
|
172
|
-
|
|
173
|
-
Skills load automatically via Railtie. No configuration needed.
|
|
25
|
+
## Usage
|
|
174
26
|
|
|
175
27
|
```ruby
|
|
176
|
-
# app/skills
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
def create
|
|
181
|
-
chat = RubyLLM.chat
|
|
182
|
-
chat.with_skills # Already has app/skills loaded
|
|
183
|
-
chat.ask "Generate quarterly report from #{@data}"
|
|
184
|
-
end
|
|
185
|
-
end
|
|
28
|
+
chat.with_skills # app/skills (default)
|
|
29
|
+
chat.with_skills("lib/skills") # custom path
|
|
30
|
+
chat.with_skills("app/skills", "app/commands") # multiple paths
|
|
31
|
+
chat.with_skills("app/skills", user.skills) # with database records
|
|
186
32
|
```
|
|
187
33
|
|
|
188
|
-
###
|
|
34
|
+
### With RubyLLM::Agent (v1.12+)
|
|
189
35
|
|
|
190
36
|
```ruby
|
|
191
|
-
class
|
|
192
|
-
|
|
37
|
+
class SupportAgent < RubyLLM::Agent
|
|
38
|
+
model "gpt-5-nano"
|
|
39
|
+
instructions "You are a support assistant."
|
|
40
|
+
skills "app/skills", only: [:faq, :troubleshooting]
|
|
193
41
|
end
|
|
194
42
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
validates :name, presence: true,
|
|
199
|
-
format: { with: /\A[a-z0-9-]+\z/ },
|
|
200
|
-
length: { maximum: 64 }
|
|
201
|
-
validates :description, presence: true,
|
|
202
|
-
length: { maximum: 1024 }
|
|
203
|
-
validates :content, presence: true
|
|
204
|
-
end
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Skill Discovery
|
|
208
|
-
|
|
209
|
-
Skills are injected into the system prompt as available tools:
|
|
43
|
+
chat = SupportAgent.chat
|
|
44
|
+
chat.ask("How do I reset my password?")
|
|
210
45
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
<name>pdf-report</name>
|
|
215
|
-
<description>Generate PDF reports with charts...</description>
|
|
216
|
-
<location>app/skills/pdf-report</location>
|
|
217
|
-
</skill>
|
|
218
|
-
</available_skills>
|
|
46
|
+
agent = SupportAgent.new
|
|
47
|
+
agent.with_skills("extra/skills")
|
|
48
|
+
agent.ask("What can you help with?")
|
|
219
49
|
```
|
|
220
50
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
## API Reference
|
|
224
|
-
|
|
225
|
-
### RubyLLM::Skills
|
|
226
|
-
|
|
227
|
-
```ruby
|
|
228
|
-
RubyLLM::Skills.default_path # Get/set default skills directory
|
|
229
|
-
RubyLLM::Skills.logger # Get/set logger
|
|
230
|
-
RubyLLM::Skills.load(from:) # Load skills from path/database/zip
|
|
231
|
-
RubyLLM::Skills.validate(skill) # Validate skill structure
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### RubyLLM::Skills::Skill
|
|
235
|
-
|
|
236
|
-
```ruby
|
|
237
|
-
skill = RubyLLM::Skills.find("pdf-report")
|
|
238
|
-
|
|
239
|
-
skill.name # "pdf-report"
|
|
240
|
-
skill.description # "Generate PDF reports..."
|
|
241
|
-
skill.content # Full SKILL.md content
|
|
242
|
-
skill.path # Filesystem path
|
|
243
|
-
skill.metadata # Parsed frontmatter hash
|
|
244
|
-
skill.references # Array of reference files
|
|
245
|
-
skill.scripts # Array of script files
|
|
246
|
-
skill.assets # Array of asset files
|
|
247
|
-
skill.valid? # Validates structure
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Chat Integration
|
|
251
|
-
|
|
252
|
-
```ruby
|
|
253
|
-
chat = RubyLLM.chat
|
|
254
|
-
|
|
255
|
-
chat.with_skills # Load default skills
|
|
256
|
-
chat.with_skills(only: [:name]) # Load specific skills
|
|
257
|
-
chat.with_skills(except: [:name]) # Exclude skills
|
|
258
|
-
chat.with_skills(from: records) # Load from database
|
|
259
|
-
chat.skills # List loaded skills
|
|
260
|
-
chat.skill_metadata # Get metadata for prompt
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
## Validation
|
|
264
|
-
|
|
265
|
-
Validate skills match the specification:
|
|
266
|
-
|
|
267
|
-
```ruby
|
|
268
|
-
skill = RubyLLM::Skills.find("my-skill")
|
|
269
|
-
skill.valid? # => true/false
|
|
270
|
-
skill.errors # => ["name contains uppercase"]
|
|
271
|
-
|
|
272
|
-
# Validate all skills
|
|
273
|
-
RubyLLM::Skills.validate_all
|
|
274
|
-
# => { valid: [...], invalid: [...] }
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## Provider Support
|
|
278
|
-
|
|
279
|
-
Skills work with any RubyLLM provider. The skill metadata is injected into the system prompt, so any model that supports system prompts can use skills.
|
|
280
|
-
|
|
281
|
-
Tested with: OpenAI, Anthropic, Google Gemini, AWS Bedrock, Ollama.
|
|
282
|
-
|
|
283
|
-
## Comparison with MCP
|
|
284
|
-
|
|
285
|
-
| Feature | Skills | MCP |
|
|
286
|
-
|---------|--------|-----|
|
|
287
|
-
| Execution | Prompt-based | Tool-based |
|
|
288
|
-
| Setup | Drop in folder | Server config |
|
|
289
|
-
| Context | Progressive disclosure | Always available |
|
|
290
|
-
| Best for | Domain knowledge | External integrations |
|
|
291
|
-
|
|
292
|
-
Use skills for specialized instructions. Use [ruby_llm-mcp](https://github.com/patvice/ruby_llm-mcp) for external tool integrations. They compose well together.
|
|
51
|
+
`agent.with_skills(...)` replaces the current skill tool configuration.
|
|
52
|
+
To combine sources, pass all sources in a single `skills`/`with_skills` call.
|
|
293
53
|
|
|
294
54
|
## Creating Skills
|
|
295
55
|
|
|
296
|
-
Create a folder with a `SKILL.md` file:
|
|
297
|
-
|
|
298
56
|
```
|
|
299
57
|
app/skills/
|
|
300
58
|
└── pdf-report/
|
|
301
59
|
├── SKILL.md
|
|
302
60
|
├── scripts/
|
|
303
|
-
│ └── generate.rb
|
|
304
61
|
└── references/
|
|
305
|
-
└── templates.md
|
|
306
62
|
```
|
|
307
63
|
|
|
308
|
-
|
|
64
|
+
SKILL.md requires frontmatter:
|
|
309
65
|
|
|
310
|
-
```
|
|
66
|
+
```markdown
|
|
311
67
|
---
|
|
312
68
|
name: pdf-report
|
|
313
|
-
description: Generate PDF reports
|
|
69
|
+
description: Generate PDF reports. Use when asked to create reports or export to PDF.
|
|
314
70
|
---
|
|
315
71
|
|
|
316
72
|
# PDF Report Generator
|
|
317
73
|
|
|
318
|
-
|
|
74
|
+
Instructions here...
|
|
75
|
+
```
|
|
319
76
|
|
|
320
|
-
|
|
77
|
+
## Slash Commands
|
|
321
78
|
|
|
322
|
-
|
|
323
|
-
ruby scripts/generate.rb --input data.json --output report.pdf
|
|
324
|
-
```
|
|
79
|
+
Single-file skills work as commands:
|
|
325
80
|
|
|
326
|
-
|
|
81
|
+
```
|
|
82
|
+
app/commands/
|
|
83
|
+
├── write-poem.md
|
|
84
|
+
└── review-code.md
|
|
85
|
+
```
|
|
327
86
|
|
|
328
|
-
|
|
329
|
-
|
|
87
|
+
```ruby
|
|
88
|
+
chat.with_skills("app/skills", "app/commands")
|
|
89
|
+
chat.ask "/write-poem about robots"
|
|
330
90
|
```
|
|
331
91
|
|
|
332
|
-
|
|
92
|
+
## Database Skills
|
|
333
93
|
|
|
334
|
-
|
|
335
|
-
|-------|----------|-------------|
|
|
336
|
-
| `name` | Yes | Lowercase, hyphens only. Max 64 chars. |
|
|
337
|
-
| `description` | Yes | What it does AND when to use it. Max 1024 chars. |
|
|
338
|
-
| `license` | No | License identifier |
|
|
339
|
-
| `compatibility` | No | Environment requirements |
|
|
340
|
-
| `metadata` | No | Custom key-value pairs |
|
|
94
|
+
Store skills or commands in your database:
|
|
341
95
|
|
|
342
|
-
|
|
96
|
+
```ruby
|
|
97
|
+
create_table :skills do |t|
|
|
98
|
+
t.string :name, null: false
|
|
99
|
+
t.text :description, null: false
|
|
100
|
+
t.text :content, null: false # SKILL.md body
|
|
101
|
+
t.references :user
|
|
102
|
+
t.timestamps
|
|
103
|
+
end
|
|
343
104
|
|
|
105
|
+
chat.with_skills(user.skills)
|
|
106
|
+
chat.ask "/my-command args" # works as command too
|
|
344
107
|
```
|
|
345
|
-
skill-name/
|
|
346
|
-
├── SKILL.md # Required - instructions
|
|
347
|
-
├── scripts/ # Optional - executable code
|
|
348
|
-
├── references/ # Optional - additional docs
|
|
349
|
-
└── assets/ # Optional - templates, images
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Best Practices
|
|
353
108
|
|
|
354
|
-
|
|
109
|
+
Records must respond to `#name`, `#description`, and `#content`. For skills with scripts/references, use filesystem skills.
|
|
355
110
|
|
|
356
|
-
|
|
111
|
+
## Rails
|
|
357
112
|
|
|
358
|
-
|
|
359
|
-
# Good
|
|
360
|
-
description: Extract text and tables from PDF files. Use when working with PDFs, forms, or document extraction.
|
|
113
|
+
Default path auto-configured to `Rails.root/app/skills`.
|
|
361
114
|
|
|
362
|
-
|
|
363
|
-
description
|
|
115
|
+
```bash
|
|
116
|
+
rails generate skill pdf-report --description "Generate PDF reports"
|
|
364
117
|
```
|
|
365
118
|
|
|
366
|
-
|
|
119
|
+
## Development
|
|
367
120
|
|
|
368
|
-
|
|
121
|
+
### Setup
|
|
369
122
|
|
|
370
|
-
|
|
123
|
+
```bash
|
|
124
|
+
bin/setup
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Running Tests
|
|
371
128
|
|
|
372
129
|
```bash
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
bundle
|
|
376
|
-
bundle exec rake
|
|
130
|
+
bundle exec rake test # Unit tests (151 tests)
|
|
131
|
+
bundle exec rake test_rails # Rails integration tests (25+ tests)
|
|
132
|
+
bundle exec rake test_all # Both
|
|
133
|
+
bundle exec rake # Tests + linting
|
|
377
134
|
```
|
|
378
135
|
|
|
379
|
-
|
|
136
|
+
### Dummy Rails App
|
|
380
137
|
|
|
381
|
-
|
|
382
|
-
2. Create your feature branch (`git checkout -b my-feature`)
|
|
383
|
-
3. Commit your changes (`git commit -am 'Add feature'`)
|
|
384
|
-
4. Push to the branch (`git push origin my-feature`)
|
|
385
|
-
5. Create a Pull Request
|
|
138
|
+
A minimal Rails 8 app at `test/dummy/` tests Rails integration:
|
|
386
139
|
|
|
387
|
-
|
|
140
|
+
- **Filesystem skills**: `app/skills/greeting/` tests directory-based loading
|
|
141
|
+
- **Database skills**: `Skill` model tests ActiveRecord-based loading
|
|
142
|
+
- **Generator tests**: Tests for `rails generate skill`
|
|
143
|
+
- **Composite loading**: Tests combining filesystem + database sources
|
|
388
144
|
|
|
389
|
-
|
|
145
|
+
```bash
|
|
146
|
+
cd test/dummy
|
|
147
|
+
bundle exec rails test # Run Rails tests directly
|
|
148
|
+
```
|
|
390
149
|
|
|
391
150
|
## Resources
|
|
392
151
|
|
|
393
152
|
- [Agent Skills Specification](https://agentskills.io/specification)
|
|
394
|
-
- [Anthropic Skills Repository](https://github.com/anthropics/skills)
|
|
395
153
|
- [RubyLLM](https://github.com/crmne/ruby_llm)
|
|
396
|
-
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Creates a new Agent Skill following the agentskills.io specification.
|
|
3
|
+
Skills are stored in app/skills/ and contain a SKILL.md file with
|
|
4
|
+
YAML frontmatter (name, description) and markdown instructions.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
rails generate skill pdf-report --description "Generate PDF reports"
|
|
8
|
+
|
|
9
|
+
This creates:
|
|
10
|
+
app/skills/pdf-report/
|
|
11
|
+
app/skills/pdf-report/SKILL.md
|
|
12
|
+
|
|
13
|
+
With optional directories:
|
|
14
|
+
--scripts Creates scripts/ directory for executable code
|
|
15
|
+
--references Creates references/ directory for documentation
|
|
16
|
+
--assets Creates assets/ directory for templates/images
|
|
17
|
+
|
|
18
|
+
Full Example:
|
|
19
|
+
rails generate skill data-export -d "Export data to CSV/JSON. Use when asked to export or download data." --scripts --assets
|
|
20
|
+
|
|
21
|
+
This creates:
|
|
22
|
+
app/skills/data-export/
|
|
23
|
+
app/skills/data-export/SKILL.md
|
|
24
|
+
app/skills/data-export/scripts/.keep
|
|
25
|
+
app/skills/data-export/assets/.keep
|
|
26
|
+
|
|
27
|
+
Note:
|
|
28
|
+
The description should include both what the skill does AND when to use it.
|
|
29
|
+
Example: "Generate PDF reports from data. Use when asked to create reports or export to PDF."
|
|
@@ -5,11 +5,16 @@ require "rails/generators"
|
|
|
5
5
|
class SkillGenerator < Rails::Generators::NamedBase
|
|
6
6
|
source_root File.expand_path("templates", __dir__)
|
|
7
7
|
|
|
8
|
-
class_option :description, type: :string, default: "Description of what this skill does"
|
|
9
|
-
|
|
10
|
-
class_option :
|
|
11
|
-
|
|
12
|
-
class_option :
|
|
8
|
+
class_option :description, type: :string, default: "Description of what this skill does. Use when...",
|
|
9
|
+
aliases: "-d", desc: "Short description of the skill (max 1024 chars)"
|
|
10
|
+
class_option :license, type: :string, default: nil,
|
|
11
|
+
aliases: "-l", desc: "License identifier (e.g., MIT, Apache-2.0)"
|
|
12
|
+
class_option :scripts, type: :boolean, default: false,
|
|
13
|
+
desc: "Create scripts/ directory for executable code"
|
|
14
|
+
class_option :references, type: :boolean, default: false,
|
|
15
|
+
desc: "Create references/ directory for documentation"
|
|
16
|
+
class_option :assets, type: :boolean, default: false,
|
|
17
|
+
desc: "Create assets/ directory for templates/images"
|
|
13
18
|
|
|
14
19
|
def create_skill_directory
|
|
15
20
|
empty_directory skill_path
|
|
@@ -57,4 +62,8 @@ class SkillGenerator < Rails::Generators::NamedBase
|
|
|
57
62
|
def skill_license
|
|
58
63
|
options[:license]
|
|
59
64
|
end
|
|
65
|
+
|
|
66
|
+
def skill_title
|
|
67
|
+
skill_name.split("-").map(&:capitalize).join(" ")
|
|
68
|
+
end
|
|
60
69
|
end
|
|
@@ -6,16 +6,52 @@ license: <%= skill_license %>
|
|
|
6
6
|
<% end -%>
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
# <%=
|
|
9
|
+
# <%= skill_title %>
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<%= skill_description %>
|
|
12
12
|
|
|
13
13
|
## When to Use
|
|
14
14
|
|
|
15
|
-
Use this skill when
|
|
15
|
+
Use this skill when:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
- [Trigger condition 1 - be specific about keywords/phrases]
|
|
18
|
+
- [Trigger condition 2]
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
## Instructions
|
|
21
|
+
|
|
22
|
+
### Step 1: [Action]
|
|
23
|
+
|
|
24
|
+
[Clear instruction with expected outcome]
|
|
25
|
+
|
|
26
|
+
### Step 2: [Action]
|
|
27
|
+
|
|
28
|
+
[Clear instruction with expected outcome]
|
|
29
|
+
|
|
30
|
+
### Step 3: [Action]
|
|
31
|
+
|
|
32
|
+
[Clear instruction with expected outcome]
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Example 1: [Scenario]
|
|
37
|
+
|
|
38
|
+
**Input:**
|
|
39
|
+
```
|
|
40
|
+
[Example input or command]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Output:**
|
|
44
|
+
```
|
|
45
|
+
[Expected result]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Edge Cases
|
|
49
|
+
|
|
50
|
+
- **[Scenario]**: [How to handle it]
|
|
51
|
+
- **[Error condition]**: [Recovery steps]
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
|
|
55
|
+
- Keep this file under 500 lines for optimal token usage
|
|
56
|
+
- Move detailed documentation to `references/` directory
|
|
57
|
+
- Move executable code to `scripts/` directory
|