Symbol-based refactoring via MCP for TypeScript/JavaScript. Use for finding references, renaming symbols, safe refactoring, and type updates. Trigger with "find usages", "rename across codebase", "update type definition", "what calls this", "refactor safely". PROACTIVELY use before any symbol manipulation.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/find-implementations.tsexamples/rename-function.tsreferences/background.mdreferences/complete-tool-inventory.mdreferences/optimal-refactoring-workflow.mdreferences/tool-reference.mdToken-efficient symbol refactoring via the serena MCP server.
From Serena's official docs:
"I WILL BE SERIOUSLY UPSET IF YOU READ ENTIRE FILES WITHOUT NEED!" "THE PURPOSE OF THE SYMBOLIC TOOLS IS TO HAVE TO READ LESS CODE, NOT READ THE SAME CONTENT MULTIPLE TIMES!"
The Golden Rule: Never read entire files. Use progressive disclosure:
serena.get_symbols_overview → see file structure (no bodies)serena.find_symbol(include_body=false) → see symbol structureserena.find_symbol(include_body=true) → only when you need the actual codeserena.search_for_pattern → for non-code files or unknown symbol pathsAnti-Pattern: Reading a file with the Read tool, then using Serena to analyze the same content = wasted tokens.
| Need | Use | Why |
|---|---|---|
| Find function/class definition | serena.find_symbol | Precise, returns metadata |
| Find all usages of a symbol | serena.find_referencing_symbols | Complete reference list with context |
| Rename across codebase | serena.rename_symbol | Safe, handles all references |
Find field access patterns (.name) | serena.search_for_pattern | Symbolic tools miss these |
| Unsure of symbol location | ChunkHound.search_semantic first | Find candidates, then use Serena |
| Simple string search | Grep | Faster for exact matches |
CRITICAL: Get initial instructions BEFORE using any Serena tools:
// Call once per session
await serena.initial_instructions({})
This provides project context, available memories, and configuration.
// Get a high-level overview of symbols in a file
await serena.get_symbols_overview({
relative_path: "path/to/file.ts"
})
// Find a specific symbol by name pattern
await serena.find_symbol({
name_path_pattern: "MyClass/myMethod",
relative_path: "src/",
depth: 1, // Include children (methods of a class)
include_body: true // Include the source code
})
// Find all references to a symbol
await serena.find_referencing_symbols({
name_path: "functionName",
relative_path: "path/to/file.ts"
})
// Rename a symbol across the entire codebase
await serena.rename_symbol({
name_path: "oldName",
relative_path: "path/to/file.ts",
new_name: "newName"
})
// Replace the body of a function or method
await serena.replace_symbol_body({
name_path: "MyClass/myMethod",
relative_path: "path/to/file.ts",
body: "new implementation code"
})
// Use regex to search for patterns with context
await serena.search_for_pattern({
substring_pattern: "useQuery",
relative_path: "apps/web/src",
context_lines_before: 2,
context_lines_after: 2
})
// List available memories
await serena.list_memories({})
// Read a specific memory
await serena.read_memory({
memory_file_name: "project_overview"
})
// Write a custom memory
await serena.write_memory({
memory_file_name: "my_notes",
content: "markdown content"
})
// 1. Find all references to understand usage
const refs = await serena.find_referencing_symbols({
name_path: "handlePayment",
relative_path: "src/lib/payments.ts"
})
// 2. If the symbol is found, review usage patterns
if (refs.references && refs.references.length > 0) {
// 3. Rename the symbol safely
await serena.rename_symbol({
name_path: "handlePayment",
relative_path: "src/lib/payments.ts",
new_name: "processPayment"
})
// 4. Update the implementation
await serena.replace_symbol_body({
name_path: "processPayment",
relative_path: "src/lib/payments.ts",
body: "function processPayment(data: PaymentData) { /* new implementation */ }"
})
} else {
// Fallback: use grep for a broader, text-based search if the symbol isn't found
await grep({ pattern: "handlePayment", type: "ts" })
}
// 1. Find all references first to gauge the scope of the change
const refs = await serena.find_referencing_symbols({
name_path: "oldFunctionName",
relative_path: "src/utils/helpers.ts"
})
console.log(`Found ${refs.references?.length || 0} references to rename.`)
// 2. Perform the rename across the entire codebase
await serena.rename_symbol({
name_path: "oldFunctionName",
relative_path: "src/utils/helpers.ts",
new_name: "newFunctionName"
})
// 3. Verify that no instances of the old name remain
const oldRefs = await serena.search_for_pattern({
substring_pattern: "oldFunctionName",
relative_path: "src/"
})
console.log("Occurrences of old name:", oldRefs)
search_for_pattern DetailsUse this tool to find field access, string literals, or any code pattern that isn't a formal symbol.
| Parameter | Type | Description |
|---|---|---|
substring_pattern | string | Required. Regex pattern. |
paths_include_glob | string | Glob for files to include (e.g., "src/**/*.ts"). |
relative_path | string | Restrict search to a specific file or directory. |
Example: Find all .paymentMethod field access:
await serena.search_for_pattern({
substring_pattern: "\\.paymentMethod",
paths_include_glob: "src/**/*.{ts,tsx}"
})