---
name: code-search
description: Search reasoning guide — tool selection matrix (LSP → intent-based → AST → raw), monorepo navigation, common workflows.
---

# Code Search & Codebase Navigation

> **When to load this skill:** Any task requiring codebase exploration, understanding
> unfamiliar code, finding symbols, or navigating project structure.

## Tool Selection — Pick the Cheapest Tool That Answers the Question

**The golden rule: start with the most specific tool, escalate to broader search only if needed.**

### Tier 1: Compiler-Grade (Best — Use First)

These give exact, zero-false-positive results. Use when you have a specific symbol name.

| I need to…                        | Use                                  |
| --------------------------------- | ------------------------------------ |
| Jump to where symbol X is defined | `lsp_navigation` → `definition`      |
| Find all usages of symbol X       | `lsp_navigation` → `references`      |
| Get type/docs for symbol X        | `lsp_navigation` → `hover`           |
| See who calls function X          | `lsp_navigation` → `incomingCalls`   |
| See what function X calls         | `lsp_navigation` → `outgoingCalls`   |
| Rename symbol X safely            | `lsp_navigation` → `rename`          |
| Search symbols by name            | `lsp_navigation` → `workspaceSymbol` |

**Prerequisite:** You need an exact position (file + line + column) or the project
must have a running language server. If you don't have that — drop to Tier 2.

### Tier 2: Intent-Based Search (Good — Use for Exploration)

These encode common search patterns so you don't have to construct regexes.

| I need to…                              | Use                                                      |
| --------------------------------------- | -------------------------------------------------------- |
| Find where X is defined (fuzzy/partial) | `find_symbol` with mode `"definition"`                   |
| Find where module X is imported         | `find_symbol` with mode `"usage"`                        |
| Search config files for key/value       | `search_config`                                          |
| Understand a file's structure           | `inspect_code` (outline for large files, full for small) |

**When to prefer these over LSP:**

- You don't know the exact symbol name (partial match, pattern)
- You want to search across all files at once (not one file at a time)
- You're looking in non-code files (config, docs)
- LSP isn't available for the language/project

### Tier 3: Structural Pattern Matching

| I need to…                            | Use                |
| ------------------------------------- | ------------------ |
| Find a code pattern like `foo($BAR)`  | `ast_grep_search`  |
| Find all imports from a specific path | `ast_grep_search`  |
| Refactor a pattern across files       | `ast_grep_replace` |

**Best for:** Structural patterns where you care about syntax shape, not just text.
Example: `import { $NAMES } from "$PATH"` finds all imports regardless of what's imported.

### Tier 4: Raw Text Search (Fallback)

| I need to…                 | Use                                                    |
| -------------------------- | ------------------------------------------------------ |
| Search for arbitrary text  | `rg` (ripgrep)                                        |
| Find files by name pattern | `find`                                                 |
| Read a known file          | `read`                                                 |
| Understand file structure  | `inspect_code` (tree-sitter outline with line ranges)  |
| Read a specific function   | `inspect_code` with `functions` arg (hash-based dedup) |

### Tier 5: Shell Commands (Last Resort)

Only reach for `bash` with rg/find/fd when the above tools genuinely can't
express what you need. Examples:

- Complex multi-step pipelines with awk/sed
- Counting/statistics across files
- Combining search with file manipulation

---

## Search Reasoning Patterns

### Pattern 1: Scope First, Then Search

**Wrong:** Search everything, then narrow.

```
rg "handleAuth" .              → 500 results
rg "handleAuth" . | head -50   → lost 450 results
```

**Right:** Estimate scope upfront.

```
find_symbol { name: "handleAuth", mode: "definition", scope: "packages/core/src" }  → 3 results ✓
```

**Decision tree:**

1. Is the project a monorepo with `packages/`? → Scope to the relevant package.
2. Is it a single repo with `src/`? → Scope to `src/`.
3. Not sure? → Use `inspect_code { paths: ["."] }` to see the directory tree.

### Pattern 2: Match Intent to Tool

| User says…                   | Intent     | Best tool                            |
| ---------------------------- | ---------- | ------------------------------------ |
| "Find where X is defined"    | Definition | `find_symbol { mode: "definition" }` |
| "Where is X imported"        | Import     | `find_symbol { mode: "usage" }`      |
| "What config controls X"     | Config     | `search_config`                      |
| "Show me the file structure" | Outline    | `inspect_code`                       |
| "Find all calls to X"        | Usage      | `lsp_navigation` → `references`      |
| "What type is X"             | Type info  | `lsp_navigation` → `hover`           |
| "Find pattern like X($Y)"    | Structure  | `ast_grep_search`                    |
| "Search for text X"          | Raw text   | `rg` (ripgrep)                        |

### Pattern 3: Zero Results → Expand

If a scoped search returns 0 results:

1. Check spelling / case sensitivity
2. Broaden the scope (remove scope parameter → search entire project)
3. Try a less specific pattern
4. Check if the symbol might have a different name (alias, re-export)

### Pattern 4: Too Many Results → Refine

If a search returns >50 results:

1. Add a scope parameter to narrow to a directory
2. Specify a language if you know it
3. Make the pattern more specific
4. Switch to LSP if you need exact symbol resolution

---

## Monorepo Navigation

For monorepos with a `packages/` directory:

1. **Start with `inspect_code { paths: ["."] }`** to see all packages
2. **Scope searches to the relevant package** — e.g., `scope: "packages/core/src"`
3. **If searching across packages**, omit scope but expect more results
4. **For cross-package dependencies**, use `find_symbol { mode: "usage" }` with the package name

---

## Common Workflows

### "I'm new to this codebase"

1. `inspect_code { paths: ["."] }` — understand directory structure
2. `inspect_code { paths: ["src/"] }` — get outlines of key files
3. `find_symbol { name: "...", mode: "definition" }` — find important symbols

### "I need to change function X"

1. `lsp_navigation` → `definition` — find the function
2. `lsp_navigation` → `incomingCalls` — understand who depends on it
3. `inspect_code { paths: ["file.ts"], functions: ["X"] }` — read the implementation
4. Make the change
5. `lsp_navigation` → `references` — verify nothing broke

### "I need to find where config Y is set"

1. `search_config` with the config key
2. If not found in config files: `rg` with broader scope

### "I need to understand how module Z is used"

1. `find_symbol { name: "Z", mode: "usage" }` to see all consumers
2. `lsp_navigation` → `references` on exported symbols for detailed usage
