> ## Documentation Index
> Fetch the complete documentation index at: https://docs.morphllm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Codebase Search

> Search local repositories with WarpGrep

Search local code repositories on disk. WarpGrep takes a natural language query, runs multiple grep and file-read operations in a separate context window, and returns the relevant code.

### Why?

Use codebase search when your primary agent needs to do broad exploration across a local repository — finding implementations, understanding how modules connect, or locating code by description rather than exact pattern.

<Tip>
  See [complete agent examples](https://github.com/morphllm/examples/tree/main/warpgrep) for each framework — copy-paste ready.
</Tip>

## Quick Start

```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });
const anthropic = new Anthropic();

const grepTool = morph.anthropic.createWarpGrepTool({ repoRoot: '.' });

async function askCodebase(question: string) {
  const messages: Anthropic.MessageParam[] = [
    { role: 'user', content: question }
  ];
  let maxTurns = 5;

  while (maxTurns-- > 0) {
    const response = await anthropic.messages.create({
      model: 'claude-sonnet-4-5-20250929',
      max_tokens: 8192,
      tools: [grepTool],
      system: 'Use the search tool to find relevant code before answering. Cite file paths.',
      messages
    });

    // Model is done — return the final text
    if (response.stop_reason === 'end_turn') {
      return response.content.find(c => c.type === 'text')?.text;
    }

    // Otherwise, execute tool calls and feed results back
    messages.push({ role: 'assistant', content: response.content });

    const toolResults = [];
    for (const block of response.content) {
      if (block.type === 'tool_use') {
        const result = await grepTool.execute(block.input);
        toolResults.push({
          type: 'tool_result' as const,
          tool_use_id: block.id,
          content: grepTool.formatResult(result)
        });
      }
    }

    messages.push({ role: 'user', content: toolResults });
  }
}

await askCodebase('How does authentication work in this project?');
```

<Tabs>
  <Tab title="OpenAI">
    ```typescript theme={null}
    import OpenAI from 'openai';
    import { MorphClient } from '@morphllm/morphsdk';

    const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });
    const openai = new OpenAI();

    const grepTool = morph.openai.createWarpGrepTool({ repoRoot: '.' });

    async function askCodebase(question: string) {
      const messages: OpenAI.ChatCompletionMessageParam[] = [
        { role: 'user', content: question }
      ];
      let maxTurns = 5;

      while (maxTurns-- > 0) {
        const response = await openai.chat.completions.create({
          model: 'gpt-4o',
          tools: [grepTool],
          messages
        });

        const choice = response.choices[0];
        if (choice.finish_reason === 'stop') {
          return choice.message.content;
        }

        messages.push(choice.message);

        for (const toolCall of choice.message.tool_calls || []) {
          const result = await grepTool.execute(toolCall.function.arguments);
          messages.push({
            role: 'tool',
            tool_call_id: toolCall.id,
            content: grepTool.formatResult(result)
          });
        }
      }
    }
    ```
  </Tab>

  <Tab title="Vercel AI SDK">
    ```typescript theme={null}
    import { generateText, stepCountIs } from 'ai';
    import { anthropic } from '@ai-sdk/anthropic';
    import { MorphClient } from '@morphllm/morphsdk';

    const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });

    const grepTool = morph.vercel.createWarpGrepTool({ repoRoot: '.' });

    // Vercel AI SDK handles the tool loop automatically
    const result = await generateText({
      model: anthropic('claude-sonnet-4-5-20250929'),
      tools: { grep: grepTool },
      prompt: 'How does authentication work in this project?',
      stopWhen: stepCountIs(5)
    });
    ```
  </Tab>
</Tabs>

## Configuration

```typescript theme={null}
const grepTool = morph.openai.createWarpGrepTool({
  repoRoot: '.',
  excludes: ['dist', '*.test.ts'],
  includes: ['src/**/*.ts'],
});
```

| Option           | Default                    | Description                                                                                                   |
| ---------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `repoRoot`       | (required)                 | Root directory of the repository to search                                                                    |
| `excludes`       | (see below)                | Glob patterns to exclude                                                                                      |
| `includes`       | (all files)                | Glob patterns to include (e.g., `['src/**/*.ts', 'lib/**/*.js']`)                                             |
| `name`           | `codebase_search`          | Tool name exposed to the LLM                                                                                  |
| `description`    | (see SDK)                  | Tool description for the LLM                                                                                  |
| `remoteCommands` | (local)                    | Functions for remote sandbox execution ([see Sandbox Execution](/sdk/components/warp-grep/sandbox-execution)) |
| `morphApiUrl`    | `https://api.morphllm.com` | Override API base URL                                                                                         |
| `timeout`        | `30000`                    | Timeout in ms (also via `MORPH_WARP_GREP_TIMEOUT` env var)                                                    |

### Default Excludes

WarpGrep excludes common non-source directories by default:

* **Dependencies:** `node_modules`, `bower_components`, `.pnpm`, `.yarn`, `vendor`, `Pods`, `.bundle`
* **Build output:** `dist`, `build`, `.next`, `.nuxt`, `out`, `target`, `.output`
* **Python:** `__pycache__`, `.pytest_cache`, `.mypy_cache`, `.ruff_cache`, `.venv`, `venv`, `site-packages`
* **Version control:** `.git`, `.svn`, `.hg`
* **Lock files, minified files, source maps, and common binary formats**

Pass `excludes` to override these defaults. Your list **replaces** the defaults entirely — it does not merge with them.

<Tip>
  To search inside `node_modules` (e.g., debugging a library), pass `excludes: []`. See the [node\_modules example](https://github.com/morphllm/examples/tree/main/warpgrep/search-node-modules).
</Tip>

## Error Handling

```typescript theme={null}
const result = await grepTool.execute(toolUse.input);

if (!result.success) {
  console.error(result.error);
  // Common errors:
  // - "Search did not complete" — the model did not call finish within 4 turns
  // - "API error" — authentication or network issue
  // - "timeout" — search took longer than the configured timeout
}
```
