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.
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.
Quick Start
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?');
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)
});
}
}
}
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)
});
Configuration
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) |
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.
To search inside node_modules (e.g., debugging a library), pass excludes: []. See the node_modules example.
Error Handling
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
}