This skill should be used when the user asks about "metaprogramming", "DSL", "domain-specific language", "method_missing", "define_method", "class_eval", "instance_eval", "module_eval", "hooks", "included", "extended", "inherited", "singleton class", "eigenclass", "dynamic methods", "eval", or needs guidance on Ruby metaprogramming techniques.
/plugin marketplace add bastos/ruby-plugin-marketplace/plugin install ruby@ruby-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/metaprogramming-patterns.mdGuide to Ruby metaprogramming techniques, DSL creation, and dynamic code generation.
Use metaprogramming when:
Avoid when:
class Calculator
OPERATIONS = { add: :+, subtract: :-, multiply: :*, divide: :/ }.freeze
OPERATIONS.each do |operation, operator|
define_method(operation) do |a, b|
a.send(operator, b)
end
end
end
calc = Calculator.new
calc.add(2, 3) # => 5
calc.multiply(4, 5) # => 20
class FlexibleStruct
def initialize(attributes = {})
@attributes = attributes
end
def method_missing(name, *args)
attribute = name.to_s.chomp("=").to_sym
if name.to_s.end_with?("=")
@attributes[attribute] = args.first
elsif @attributes.key?(attribute)
@attributes[attribute]
else
super
end
end
def respond_to_missing?(name, include_private = false)
attribute = name.to_s.chomp("=").to_sym
@attributes.key?(attribute) || super
end
end
person = FlexibleStruct.new(name: "Alice")
person.name # => "Alice"
person.age = 30
person.age # => 30
person.respond_to?(:name) # => true
# Add methods to a class dynamically
String.class_eval do
def shout
upcase + "!"
end
end
"hello".shout # => "HELLO!"
# With string evaluation (use sparingly)
klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method_name}
@#{attribute}
end
RUBY
# Evaluate in context of an object
class Config
attr_accessor :host, :port
def configure(&block)
instance_eval(&block)
end
end
config = Config.new
config.configure do
self.host = "localhost"
self.port = 3000
end
module Trackable
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
# Add instance-level behavior
attr_accessor :tracked_at
end
end
def self.extended(base)
# Called when module is extended
end
module ClassMethods
def track_creation
define_method(:initialize) do |*args|
super(*args)
@tracked_at = Time.now
end
end
end
end
class User
include Trackable
track_creation
end
class BaseModel
def self.inherited(subclass)
subclass.instance_variable_set(:@fields, [])
subclass.extend(ClassMethods)
end
module ClassMethods
def field(name)
@fields << name
attr_accessor name
end
def fields
@fields
end
end
end
class User < BaseModel
field :name
field :email
end
User.fields # => [:name, :email]
module MethodLogger
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def method_added(name)
return if @_adding_method
return if name == :initialize
@_adding_method = true
original = instance_method(name)
define_method(name) do |*args, &block|
puts "Calling #{name} with #{args}"
original.bind(self).call(*args, &block)
end
@_adding_method = false
end
end
end
class ServerConfig
attr_reader :settings
def initialize
@settings = {}
end
def self.configure(&block)
config = new
config.instance_eval(&block)
config
end
def host(value)
@settings[:host] = value
end
def port(value)
@settings[:port] = value
end
def ssl(enabled: true, &block)
@settings[:ssl] = { enabled: enabled }
SSLConfig.new(@settings[:ssl]).instance_eval(&block) if block
end
class SSLConfig
def initialize(settings)
@settings = settings
end
def certificate(path)
@settings[:certificate] = path
end
def key(path)
@settings[:key] = path
end
end
end
config = ServerConfig.configure do
host "localhost"
port 3000
ssl enabled: true do
certificate "/path/to/cert.pem"
key "/path/to/key.pem"
end
end
class HTMLBuilder
def initialize
@html = []
end
def method_missing(tag, content = nil, **attrs, &block)
attr_str = attrs.map { |k, v| %( #{k}="#{v}") }.join
@html << "<#{tag}#{attr_str}>"
if block
nested = HTMLBuilder.new
nested.instance_eval(&block)
@html << nested.to_s
elsif content
@html << content
end
@html << "</#{tag}>"
self
end
def respond_to_missing?(*)
true
end
def to_s
@html.join
end
end
html = HTMLBuilder.new
html.div(class: "container") do
h1 "Welcome"
p "Hello, World!"
ul do
li "Item 1"
li "Item 2"
end
end
puts html.to_s
# <div class="container"><h1>Welcome</h1><p>Hello, World!</p>...
obj = Object.new
# Access singleton class
obj.singleton_class
# Define singleton methods
def obj.greet
"Hello!"
end
# Or using singleton_class
obj.singleton_class.define_method(:farewell) { "Goodbye!" }
# Class methods are singleton methods on Class objects
class User
def self.count # Defined on User's singleton class
@count ||= 0
end
end
module A; end
module B; end
module C; end
class Parent
include A
end
class Child < Parent
include B
prepend C # Prepend inserts before the class
end
Child.ancestors
# => [C, Child, B, Parent, A, Object, Kernel, BasicObject]
# Method lookup follows ancestors chain
module Logging
def save
puts "Before save"
super
puts "After save"
end
end
class Record
prepend Logging # Logging#save called before Record#save
def save
puts "Saving..."
end
end
Record.new.save
# Before save
# Saving...
# After save
references/metaprogramming-patterns.md - Common metaprogramming patterns and anti-patternsThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.