Write standalone .rbs signature files to describe Ruby code. Use when creating type definitions for gems, libraries, or existing codebases without modifying Ruby source.
Write standalone `.rbs` type signature files in a `sig/` directory to describe Ruby code without modifying source files. Claude will use this when creating type definitions for gems, libraries, or existing codebases that need static type checking with tools like Steep.
/plugin marketplace add stevegeek/claude-ruby-plugins/plugin install ruby-rbs@stevegeek-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Write type signatures in separate .rbs files in a sig/ directory. Ruby source files remain unchanged.
# sig/person.rbs
class Person
attr_reader name: String
attr_reader age: Integer?
def initialize: (String name, ?Integer? age) -> void
def greet: () -> String
end
project/
├── lib/
│ └── person.rb # Ruby implementation
├── sig/
│ ├── person.rbs # Type signatures
│ ├── _private/ # Hidden from library users
│ │ └── internal.rbs
│ └── manifest.yaml # Stdlib dependencies
└── Steepfile
# Basic class
class User
end
# With superclass
class Admin < User
end
# With type parameters
class Container[T]
end
# Module
module Logging
end
# Module with self-type constraint
module Enumerable[Elem] : _Each[Elem]
end
class Calculator
# Instance method
def add: (Integer, Integer) -> Integer
# Singleton (class) method
def self.create: () -> Calculator
# Module function (both singleton and private instance)
def self?.sqrt: (Numeric) -> Float
# Visibility
private def internal: () -> void
end
# Required positional
def foo: (String, Integer) -> void
# Optional positional (? prefix)
def foo: (String, ?Integer) -> void
# Rest positional
def foo: (*String) -> void
# Required keyword
def foo: (name: String) -> void
# Optional keyword
def foo: (?name: String) -> void
# Keyword rest
def foo: (**String) -> void
# Block (required)
def foo: () { (String) -> Integer } -> void
# Block (optional, ? before brace)
def foo: () ?{ (String) -> Integer } -> void
# Complex signature
def foo: (
String, # Required positional
?Integer, # Optional positional
*Symbol, # Rest positional
name: String, # Required keyword
?age: Integer, # Optional keyword
**untyped # Keyword rest
) { (String) -> void } -> Array[String]
class Array[Elem]
# Multiple signatures with |
def *: (String) -> String
| (Integer) -> Array[Elem]
# Extending existing method with ...
def fetch: (Integer) -> Elem
| ...
end
class User
# Reader (generates getter + @name ivar)
attr_reader name: String
# Writer (generates setter + @email ivar)
attr_writer email: String
# Accessor (generates both)
attr_accessor age: Integer
# Custom ivar name
attr_reader display_name (@raw_name): String
# No ivar (computed property)
attr_reader full_name (): String
# Singleton attribute
attr_reader self.instance: User
end
class Counter
@count: Integer # Instance variable
self.@instances: Array[Counter] # Class instance variable
@@total: Integer # Class variable
end
class Config
VERSION: String
MAX_SIZE: Integer
VALID_STATES: Array[Symbol]
end
# Global variable
$LOAD_PATH: Array[String]
Define duck types that classes can implement:
interface _Readable
def read: (?Integer) -> String?
def eof?: () -> bool
end
interface _Writable
def write: (String) -> Integer
end
class MyIO
include _Readable
include _Writable
end
# Simple alias
type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
# Generic alias
type result[T] = [true, T] | [false, String]
# Scoped to class
class MyApp
type callback = ^(String) -> void
end
# Basic generic class
class Box[T]
def initialize: (T) -> void
def get: () -> T
end
# Variance annotations
class ReadOnly[out T] # Covariant
def get: () -> T
end
class WriteOnly[in T] # Contravariant
def set: (T) -> void
end
# Unchecked variance (for mutable collections)
class Array[unchecked out T]
end
# Upper bound
class Sorter[T < Comparable]
def sort: (Array[T]) -> Array[T]
end
# Default type
class Cache[T = String]
end
# Method-level generics
class Util
def self.identity: [T] (T) -> T
def self.map: [T, U] (Array[T]) { (T) -> U } -> Array[U]
end
class User
include Comparable
include Enumerable[String]
extend ClassMethods
prepend Instrumentation
end
Import types to avoid fully-qualified names:
use RBS::TypeName
use RBS::AST::*
class MyParser
def parse: (TypeName) -> untyped
end
Declare stdlib dependencies for gems:
# sig/manifest.yaml
dependencies:
- name: json
- name: pathname
- name: set
# Check RBS syntax and consistency
bundle exec rbs validate
# Test signatures against runtime
RBS_TEST_TARGET='MyApp::*' bundle exec ruby -r rbs/test/setup test/my_test.rb