ruby-rbs
Comprehensive skill for Ruby RBS type signatures. Use for writing inline type annotations in Ruby files, creating standalone .rbs signature files, scaffolding types, or setting up Steep type checking. Covers both inline syntax (rbs-inline) and standalone RBS file format.
What this skill does
# Ruby RBS Type Signatures
RBS is Ruby's official type signature language for describing the structure of Ruby programs - classes, modules, methods, and types. This skill covers both approaches to adding types:
1. **Inline RBS** (`# rbs_inline: enabled`) - Type annotations embedded in Ruby source files as comments
2. **Standalone RBS files** (`.rbs`) - Separate signature files that describe Ruby code
## Choosing an Approach
| Aspect | Inline RBS | Standalone .rbs Files |
|--------|-----------|----------------------|
| Co-location | Types live with code | Types in separate sig/ directory |
| Ruby files | Modified with comments | Unchanged |
| Tooling | Requires rbs-inline gem | Native RBS support |
| Use case | New code, gradual adoption | Libraries, gems, existing codebases |
**Use inline RBS when:** Starting fresh, want types near code, prefer gradual typing
**Use standalone .rbs when:** Publishing gems, typing third-party code, complete API documentation
## Subskills
For detailed guidance on each approach:
- **`subskills/inline/SKILL.md`** - Writing inline RBS annotations in Ruby files
- **`subskills/rbs-files/SKILL.md`** - Writing standalone .rbs signature files
## Core Type Syntax (Both Approaches)
### Basic Types
```
String # String instance
Integer # Integer instance
Float # Float instance
bool # true | false
boolish # Any truthy/falsy value (for predicates)
nil # nil value
void # Return value not used
untyped # Skip type checking (gradual typing)
top # Supertype of all types
bot # Subtype of all types (never returns)
self # Type of receiver
instance # Instance of the class
class # Singleton class
```
### Compound Types
```
String? # Optional: String | nil
String | Integer # Union type
_Reader & _Writer # Intersection type
Array[String] # Generic class
Hash[Symbol, Integer] # Hash with typed keys/values
[String, Integer] # Tuple (fixed-size array)
{ name: String, age: Integer } # Record (typed hash)
{ name: String, age?: Integer } # Record with optional key
^(Integer) -> String # Proc/lambda type
```
### Literal Types
```
:ready # Symbol literal
"https" # String literal
123 # Integer literal
true # Boolean literal
```
## Steep Integration
Steep is the primary type checker for RBS.
### Setup
```bash
# Add dependencies
bundle add rbs-inline --require=false # Only for inline RBS
bundle add steep --group=development
# Initialize
bundle exec steep init
bundle exec rbs collection init
bundle exec rbs collection install
```
### Basic Steepfile
```ruby
D = Steep::Diagnostic
target :app do
check "lib"
check "app"
signature "sig" # Standalone RBS files
signature "sig/generated" # Generated from inline RBS
library "pathname", "json" # Standard libraries
collection_config "rbs_collection.yaml"
configure_code_diagnostics(D::Ruby.strict)
end
```
### Workflow Commands
```bash
# Generate RBS from inline annotations
bundle exec rbs-inline --output lib
# Type check
bundle exec steep check
# Watch mode
bundle exec steep watch
# Language server for editor integration
bundle exec steep langserver
```
## Critical Pattern: Nil Narrowing
Steep's flow analysis doesn't narrow instance variable types after nil checks. Even when you've checked `if @user`, Steep still considers `@user` potentially nil inside the block. Assign to a local variable to narrow the type:
```ruby
# WRONG - @user stays User? in the if body
if @user
@user.name # ERROR: @user is still User?
end
# RIGHT - Assignment narrows the type
if user = @user
user.name # OK: user is User
end
```
## Gradual Typing Strategy
1. **Start with public APIs** - Type method signatures users call
2. **Avoid `untyped` where possible** - Prefer concrete types, unions, interfaces, or generics. Reserve `untyped` only for truly dynamic code (metaprogramming, `eval`, external data with unknown shape). When you must use `untyped`, treat it as technical debt to revisit.
3. **Progress inward** - Add types to private methods over time
4. **Add to CI early** - Catch regressions immediately
## Testing Signatures
Verify RBS signatures are correct by writing Ruby test files that exercise the typed APIs:
```
my_gem/
├── sig/
│ └── my_gem.rbs # Your RBS signatures
└── test/
└── rbs/ # Type checking test directory
├── Steepfile # Points to ../../sig
└── lib/
└── usage.rb # Ruby code exercising the API
```
Write test files that use your gem's public API:
```ruby
# test/rbs/lib/usage.rb
require "my_gem"
# Test instantiation and methods
user = MyGem::User.new("Alice", "[email protected]")
name = user.name # Verifies return type
user.update(name: "Bob") # Verifies argument types
# Test from documentation examples
client = MyGem::Client.new(api_key: "xxx")
response = client.get("/users")
```
Run `bundle exec steep check` in the test directory. Errors reveal signature problems:
- Wrong argument types
- Missing optional parameters
- Incorrect return types
- Generic type mismatches
See `references/validating-signatures.md` for full setup and patterns.
## References
- `references/type-syntax.md` - Complete type syntax reference
- `references/steep-integration.md` - Steep setup, configuration, and commands
- `references/validating-signatures.md` - Write test code to validate signatures with Steep
- `references/comparing-signatures.md` - Compare standalone and generated RBS files
- `references/rbs-test-instrumentation.md` - Runtime type checking with `rbs/test`
- `references/type-tracer.md` - Discover types from runtime execution
- `references/scaffolding.md` - Generate initial RBS from existing code
- `references/patterns.md` - Common patterns and best practices
- `references/troubleshooting.md` - Gotchas and troubleshooting guide
## External Resources
- [RBS Syntax Documentation](https://github.com/ruby/rbs/blob/master/docs/syntax.md)
- [RBS Inline Wiki](https://github.com/soutaro/rbs-inline/wiki/Syntax-guide)
- [Steep Type Checker](https://github.com/soutaro/steep)
- [gem_rbs_collection](https://github.com/ruby/gem_rbs_collection) - Community RBS for gems
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.