SKILL.md
Ruby LSP Usage Guidance
This project has Ruby LSP (shopify/ruby-lsp) integration enabled. Use the LSP tool proactively for Ruby code intelligence.
CRITICAL: Check This Decision Tree FIRST
BEFORE Reading Any Ruby File, determine what information is needed:
Need file structure overview? → documentSymbol ✅ Need to know what methods exist? → documentSymbol ✅ Need method signatures? → documentSymbol + Read ✅ (NOT hover - doesn't work on definitions) Need to understand class/module structure? → documentSymbol ✅ Need to see where a method is defined? → goToDefinition ✅ (from call site) Need to see where a method is used? → findReferences ✅ (very detailed) Need quick signature from call site? → hover ✅ (works on calls, not definitions) Need implementation details? → Read ✅ Need to search across project? → Grep ✅ (workspaceSymbol doesn't work)
Key Rule: documentSymbol for structure, Read for content, LSP for navigation.
Quick Reference
| What You Need | Use This | NOT This |
|---|---|---|
| File structure overview | documentSymbol | Read entire file |
| Method signature | documentSymbol + Read | hover on definition (doesn't work) |
| Where method is defined | goToDefinition | Grep for "def method" |
| Where method is used | findReferences | Grep for method name |
| Cross-project search | Grep | workspaceSymbol (broken) |
| Quick signature from call | hover on call site | Navigate away |
| Implementation details | Read | documentSymbol (only gives structure) |
Common Workflows
Getting Method Signatures (The Right Way)
CRITICAL: Ruby LSP cannot extract signatures from method definitions.
❌ BROKEN - Hover on definitions (this will never work):
Step 1: documentSymbol → get "initialize" at line 41
Step 2: hover at line 41 → Returns "No hover information available"
Why: Hover does NOT support Prism::DefNode (method definitions)
✅ CORRECT - documentSymbol + Read:
Step 1: documentSymbol on file.rb → get method list:
- process_payment at line 145
- validate_card at line 167
- charge_card at line 189
Step 2: Read file.rb offset=144 limit=5 → see actual def:
def process_payment(amount, currency = 'USD', metadata = {})
validate_card(metadata[:card])
charge_card(amount, currency)
end
Result: Full signature without reading entire file
✅ ALTERNATIVE - Hover on call site (if you have one):
Context: You see `processor.process_payment(100, 'EUR')` at line 89
Step 1: hover at that call site (on "process_payment")
Result: Shows signature from definition: process_payment(amount, currency = 'USD', metadata = {})
Limitation: Requires finding a call site first
Why Hover Doesn't Work on Definitions
Ruby LSP's ALLOWED_TARGETS:
- ✅ Prism::CallNode (method calls)
- ✅ Prism::ConstantReadNode (constants)
- ❌ Prism::DefNode (method definitions) ← NOT SUPPORTED
This is by design. To get signatures from definitions, use documentSymbol + Read.
Understanding File Structure
❌ Wrong:
Task: Understand what's in this Ruby file
Assistant: [Reads entire file and manually parses for classes/methods]
✅ Correct:
Task: Understand what's in this Ruby file
Step 1: documentSymbol → get hierarchical structure
Result:
PaymentProcessor (Class) - Line 10
initialize (Constructor) - Line 12
process_payment (Method) - Line 145
validate_card (Method) - Line 167
Step 2: Read specific methods if needed
Finding Where Methods Are Called
❌ Wrong:
Task: Find all places where process_payment is called
Assistant: [Uses Grep to search for "process_payment" as text]
✅ Correct:
Task: Find all places where process_payment is called
Step 1: goToDefinition or documentSymbol → find method at line 145
Step 2: findReferences at line 145
Result: Found 12 references:
app/controllers/payments_controller.rb:
Line 23:15
Line 67:11
lib/billing/processor.rb:
Line 89:27
[... detailed, semantic matches]
Detailed Operation Guide
1. documentSymbol - "What's in this file?" (PRIMARY TOOL)
Use when you need:
- List of all methods in a file
- Class and module structure
- Overview before diving deeper
- Method names with line numbers
Returns:
- Hierarchical structure of all symbols
- Method names (NOT full signatures - use Read for that)
- Line numbers for each symbol
- Classes, modules, methods, instance variables
How to use:
LSP operation="documentSymbol" filePath="/absolute/path/file.rb" line=1 character=1
Note: line/character parameters are required but don't affect results - you always get all symbols.
Example:
Context: User asks "What methods are available in payment_processor.rb?"
LSP operation="documentSymbol" filePath="/app/payment_processor.rb" line=1 character=1
Returns:
PaymentProcessor (Class) - Line 10
initialize (Constructor) - Line 12
process_payment (Method) - Line 145
validate_card (Method) - Line 167
charge_card (Method) - Line 189
Follow-up: Use Read with offset/limit to see specific method signatures.
2. findReferences - "Where is this used?"
Use when you need:
- All places a method is called
- All uses of a class or constant
- Impact analysis before refactoring
Returns:
- Every location where symbol is referenced
- Very detailed output with file paths and line numbers
- Semantic matches (not string search)
How to use:
Context: Want to find all usages of log method at line 259
LSP operation="findReferences" filePath="/path/file.rb" line=259 character=7
Returns: Found 48 references across 3 files:
lib/journeys/brief_writer.rb:
Line 109:11
Line 117:7
scripts/generate_briefs.rb:
Line 143:27
Line 153:27
[... comprehensive list]
Example scenarios:
Context: About to rename or refactor process_payment method
Step 1: documentSymbol or goToDefinition → find definition location
Step 2: findReferences at definition location
Result: All call sites across project for impact analysis
3. goToDefinition - "Where is this defined?"
Use when you need:
- Jump to where method/class is defined
- Find definition of inherited method
- Navigate from usage to definition
Returns:
- Exact file path and line number of definition
- Works with inheritance and mixins
How to use:
Context: Line 143 has `log(msg)` call, need to see implementation
LSP operation="goToDefinition" filePath="/path/file.rb" line=143 character=27
Returns: Defined in scripts/generate_briefs.rb:259:7
Example scenarios:
Context: Looking at code that calls User.authenticate, need to see how it's implemented
Step 1: goToDefinition on authenticate call site
Result: Jumps to exact definition, even if in parent class or mixin
Don't use Grep to search for "def method_name" - goToDefinition understands inheritance.
4. hover - "What does this call/constant do?" (LIMITED USE)
CRITICAL: Hover is a LIMITED tool in Ruby. It works on usage sites, not definitions.
Works on:
- ✅ Method calls:
user.save→ shows signature - ✅ Constants:
PaymentProcessor→ shows class definition - ✅ Variables:
@user,@@class_var,$global→ shows where defined - ✅ Keywords:
super,yield
Does NOT work on:
- ❌ Method definitions:
def save→ no response - ❌ Local variables
- ❌ Method parameters
- ❌ Most other Ruby syntax
When to use: Reading code and encounter a method call to something defined in another file. Hover gives you quick signature without navigating away.
Example - The actual use case:
Context: You're reading payment_processor.rb and see:
validator.check_amount(amount)
You want to know check_amount's signature without navigating to validator.rb
LSP operation="hover" filePath="/app/payment_processor.rb" line=24 character=15
Returns:
check_amount(amount, options = {})
Definition: lib/validators/amount_validator.rb:45
Documentation: [if any exists]
This is useful but narrow - not a primary workflow tool.
When NOT to use:
- Getting signatures from method definitions → Use documentSymbol + Read
- Primary code exploration → Use documentSymbol
- Understanding file structure → Use documentSymbol
Why hover is secondary:
- Requires being at a specific call site
- Doesn't work on definitions (the most common need)
- documentSymbol + Read is more direct for most use cases
How to Use LSP Operations
LSP operations don't require line/character precision for most use cases:
documentSymbol:
- Call it on any Ruby file
- Returns all symbols with line numbers
- line/character parameters required but don't affect results
- Always returns complete symbol tree
goToDefinition:
- Use from a call site or reference
- Navigate to where symbol is defined
- Works semantically (understands inheritance)
findReferences:
- Use from a definition
- Get all usages across entire project
- Returns very detailed output
hover:
- Use when at a method call or constant reference
- Works on the usage site, not the definition
- Limited use cases - prefer documentSymbol + Read for getting signatures
Available LSP Operations
Ruby LSP in Claude Code has 4 useful operations:
1. documentSymbol (PRIMARY - Always Reliable)
Get all symbols in a document
- Use when: Need to understand file structure (classes, modules, methods)
- Returns: Hierarchical symbol tree with line numbers
- Why use: Always works, provides structured view instantly
- ❌ Don't use Read + manual parsing for structure
2. findReferences (Extremely Useful)
Find all references to a symbol
- Use when: Need to see where methods/classes are used across project
- Returns: All locations where symbol is referenced (very detailed)
- Why use: Understands Ruby semantics, not just text matches
- ❌ Don't use Grep to search for method name strings
3. goToDefinition (Navigation)
Find where a symbol is defined
- Use when: Need to find where classes, modules, methods are defined
- Supports: Works with inheritance and mixins
- Why use: Understands Ruby scope, provides exact locations
- ❌ Don't use Grep to search for "def method_name"
4. hover (SECONDARY - Limited Use Cases)
Get information from call sites and constants
- Use when: Looking at a method call or constant reference and need quick info
- Works on: Method CALLS (not definitions), constants, variables
- Does NOT work on: Method definitions, local variables, most syntax
- Why limited: Only works on specific node types (CallNode, ConstantReadNode)
- ❌ Don't use for method signatures from definitions (use documentSymbol + Read)
When to Use LSP (ALWAYS PREFER LSP)
Use LSP operations proactively when:
- Understanding file structure → Use
documentSymbol - Finding method/class definitions → Use
goToDefinition - Finding where a method/class is used → Use
findReferences - Getting quick info from call sites → Use
hover(limited)
When NOT to Use LSP (Use Standard Tools)
Use standard tools when:
- Reading full file contents → Use Read (LSP only returns symbol info)
- Searching across multiple files for text patterns → Use Grep (not symbol-specific)
- Editing or writing files → Use Edit or Write (LSP is read-only)
- Non-Ruby files → Use standard tools (LSP only works with .rb files)
- Finding string literals or comments → Use Grep (text search, not semantic)
- Understanding project structure (directories, file organization) → Use Glob, Bash
- Getting method signatures from definitions → Use documentSymbol + Read (hover doesn't work on defs)
Example Workflows
Task: Understand and modify a Ruby method
- ✅ documentSymbol - Get file structure with line numbers
- ✅ Read relevant lines - See method definitions and signatures
- ✅ findReferences - See where method is used (impact analysis)
- ✅ goToDefinition - Navigate to related methods if needed
- ✅ Edit - Make changes
- ✅ findReferences again - Verify all call sites are still valid
Task: Navigate unfamiliar Ruby codebase
- ✅ documentSymbol - Get structure of current file
- ✅ goToDefinition - Jump from calls to definitions
- ✅ findReferences - See how symbols are used
- ✅ Read - Examine implementation details when needed
Task: Refactor a method safely
- ✅ documentSymbol - Find method in current file
- ✅ findReferences - Find all usages before changing (detailed output)
- ✅ Read - Review implementation
- ✅ Edit - Make refactoring changes
- ✅ findReferences - Verify all call sites are updated
Task: Quick lookup while reading code
- ✅ Reading file, encounter
validator.check_amount(amount) - ✅ hover on check_amount - Get signature without navigating
- Continue reading with context
Best Practices
- Start with documentSymbol - Always get the structure first
- Use Read for signatures - Don't try to hover on definitions
- Use hover sparingly - Only when at call sites needing quick lookup
- Navigate with goToDefinition - Not Grep searches
- Verify with findReferences - Before and after refactoring (very detailed)
- Combine tools - documentSymbol + Read + findReferences is the core workflow
- Fall back gracefully - If LSP calls fail, use standard tools (Read, Grep)
Proactively use these 4 LSP operations throughout your Ruby development workflow for semantic code intelligence.