Class: RubyLLM::Skills::Skill

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/skills/skill.rb

Overview

Represents a single skill with its metadata and content.

Skills follow a progressive disclosure pattern:

  • Level 1: Metadata (name, description) - loaded immediately
  • Level 2: Content (SKILL.md body) - loaded lazily on demand
  • Level 3: Resources (scripts, references, assets) - loaded lazily

Examples:

skill = Skill.new(
  path: "app/skills/pdf-report",
  metadata: { "name" => "pdf-report", "description" => "Generate PDFs" }
)
skill.name        # => "pdf-report" (immediate)
skill.content     # => loads SKILL.md body (lazy)
skill.scripts     # => lists script files (lazy)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, metadata:, content: nil, virtual: false) ⇒ Skill

Initialize a skill from parsed metadata.

Parameters:

  • path (String) —

    path to skill directory, file, or virtual identifier

  • metadata (Hash) —

    parsed YAML frontmatter

  • content (String, nil) (defaults to: nil) —

    pre-loaded content (optional)

  • virtual (Boolean) (defaults to: false) —

    force virtual mode (no filesystem access)



30
31
32
33
34
35
# File 'lib/ruby_llm/skills/skill.rb', line 30

def initialize(path:, metadata:, content: nil, virtual: false)
  @path = path.to_s
   =  || {}
  @content = content
  @virtual = virtual
end

Instance Attribute Details

#metadata ⇒ Object (readonly)

Returns the value of attribute metadata.



22
23
24
# File 'lib/ruby_llm/skills/skill.rb', line 22

def 
  
end

#path ⇒ Object (readonly)

Returns the value of attribute path.



22
23
24
# File 'lib/ruby_llm/skills/skill.rb', line 22

def path
  @path
end

Instance Method Details

#allowed_tools ⇒ Array<String>

Returns list of allowed tools (experimental).

Returns:

  • (Array<String>) —

    list of allowed tools (experimental)



63
64
65
# File 'lib/ruby_llm/skills/skill.rb', line 63

def allowed_tools
  (["allowed-tools"] || "").split
end

#assets ⇒ Array<String>

List asset files in the assets/ directory. Loaded lazily on first access.

Returns:

  • (Array<String>) —

    paths to asset files



95
96
97
# File 'lib/ruby_llm/skills/skill.rb', line 95

def assets
  @assets ||= list_resources("assets")
end

#compatibility ⇒ String?

Returns compatibility info from frontmatter.

Returns:

  • (String, nil) —

    compatibility info from frontmatter



53
54
55
# File 'lib/ruby_llm/skills/skill.rb', line 53

def compatibility
  ["compatibility"]
end

#content ⇒ String

Get the full SKILL.md content (body without frontmatter). Content is loaded lazily on first access.

Returns:

  • (String) —

    skill instructions



71
72
73
# File 'lib/ruby_llm/skills/skill.rb', line 71

def content
  @content ||= load_content
end

#custom_metadata ⇒ Hash

Returns custom metadata key-value pairs.

Returns:

  • (Hash) —

    custom metadata key-value pairs



58
59
60
# File 'lib/ruby_llm/skills/skill.rb', line 58

def 
  ["metadata"] || {}
end

#description ⇒ String

Returns skill description from frontmatter.

Returns:

  • (String) —

    skill description from frontmatter



43
44
45
# File 'lib/ruby_llm/skills/skill.rb', line 43

def description
  ["description"]
end

#errors ⇒ Array<String>

Get validation errors.

Returns:

  • (Array<String>) —

    list of error messages



132
133
134
# File 'lib/ruby_llm/skills/skill.rb', line 132

def errors
  @errors ||= Validator.validate(self)
end

#filesystem? ⇒ Boolean

Check if skill path is a filesystem path (vs database virtual path).

Returns:

  • (Boolean) —

    true if path points to filesystem



102
103
104
# File 'lib/ruby_llm/skills/skill.rb', line 102

def filesystem?
  !virtual?
end

#inspect ⇒ String

Returns inspection string.

Returns:

  • (String) —

    inspection string



147
148
149
# File 'lib/ruby_llm/skills/skill.rb', line 147

def inspect
  "#<#{self.class.name} name=#{name.inspect} path=#{path.inspect}>"
end

#license ⇒ String?

Returns license from frontmatter.

Returns:

  • (String, nil) —

    license from frontmatter



48
49
50
# File 'lib/ruby_llm/skills/skill.rb', line 48

def license
  ["license"]
end

#name ⇒ String

Returns skill name from frontmatter.

Returns:

  • (String) —

    skill name from frontmatter



38
39
40
# File 'lib/ruby_llm/skills/skill.rb', line 38

def name
  ["name"]
end

#references ⇒ Array<String>

List reference files in the references/ directory. Loaded lazily on first access.

Returns:

  • (Array<String>) —

    paths to reference files



87
88
89
# File 'lib/ruby_llm/skills/skill.rb', line 87

def references
  @references ||= list_resources("references")
end

#reload! ⇒ Object

Clear cached content and resources (useful for testing).



137
138
139
140
141
142
143
144
# File 'lib/ruby_llm/skills/skill.rb', line 137

def reload!
  @content = nil
  @scripts = nil
  @references = nil
  @assets = nil
  @errors = nil
  self
end

#scripts ⇒ Array<String>

List script files in the scripts/ directory. Loaded lazily on first access.

Returns:

  • (Array<String>) —

    paths to script files



79
80
81
# File 'lib/ruby_llm/skills/skill.rb', line 79

def scripts
  @scripts ||= list_resources("scripts")
end

#skill_md_path ⇒ String?

Path to the SKILL.md file.

Returns:

  • (String, nil) —

    path to SKILL.md or nil for virtual skills



116
117
118
119
120
# File 'lib/ruby_llm/skills/skill.rb', line 116

def skill_md_path
  return nil if virtual?

  File.join(@path, "SKILL.md")
end

#valid? ⇒ Boolean

Validate the skill structure.

Returns:

  • (Boolean) —

    true if skill is valid



125
126
127
# File 'lib/ruby_llm/skills/skill.rb', line 125

def valid?
  errors.empty?
end

#virtual? ⇒ Boolean

Check if skill is a virtual/database skill (no filesystem resources).

Returns:

  • (Boolean) —

    true if skill has no filesystem resources



109
110
111
# File 'lib/ruby_llm/skills/skill.rb', line 109

def virtual?
  @virtual || @path.start_with?("database:")
end