Skip to main content
Search code with Warp Grep WarpGrep is a code search subagent—a specialized AI model that searches your codebase and returns only relevant code. Instead of your main agent running grep and accumulating context, WarpGrep does intelligent multi-step searching in a separate context window and returns clean results. How it works: Your agent calls WarpGrep with a natural language query. WarpGrep’s model reasons about what to search, runs up to 24 tool calls (grep, read, list_dir) across 4 turns in under 6 seconds, and returns the relevant code sections. Your main agent’s context stays clean. The SDK provides adapters for Anthropic, OpenAI, Google Gemini, and Vercel AI SDK.

Quick Start

import Anthropic from '@anthropic-ai/sdk';
import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: "YOUR_API_KEY" });
const anthropic = new Anthropic();

// Tool inherits API key from MorphClient
const grepTool = morph.anthropic.createWarpGrepTool({ repoRoot: '.' });

const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  max_tokens: 12000,
  tools: [grepTool],
  messages: [{ role: 'user', content: 'Find authentication middleware' }]
});

// Execute tool call
const toolUse = response.content.find(c => c.type === 'tool_use');
if (toolUse) {
  const result = await grepTool.execute(toolUse.input);
  console.log(grepTool.formatResult(result));
}

How It Works

You ask a natural language question about your codebase:
const result = await morph.warpGrep.execute({
  query: 'Find where billing invoices are generated and emailed',
  repoRoot: '.'
});
WarpGrep is a subagent—a specialized model that runs in its own context window. Here’s what happens:
  1. Your agent calls WarpGrep with a natural language query
  2. WarpGrep’s model receives the query + your repo’s directory structure
  3. Multi-turn search — The model reasons and executes up to 8 parallel tool calls per turn:
    • grep — ripgrep pattern matching
    • read — read specific file sections
    • list_dir — explore directories
  4. Refinement — Based on results, it refines searches across up to 4 turns (24 total tool calls)
  5. Return — Only the relevant code sections come back to your main agent
Why a subagent? When your main agent searches directly, grep results accumulate in its context. After several searches, irrelevant code crowds out important information and performance degrades. WarpGrep keeps your main agent’s context clean. See benchmarks for performance data.

Direct Usage

Use without an AI agent:
const result = await morph.warpGrep.execute({
  query: 'Find authentication middleware',
  repoRoot: '.',
  excludes: ['node_modules', '.git', 'dist']
});

console.log(result.success); // true
console.log(`Found ${result.contexts?.length} relevant sections`);

Remote Execution (Sandbox Support)

When your code lives in a remote sandbox (E2B, Modal, Daytona, Docker, SSH), use the remoteCommands option. You provide three simple functions that return raw stdout — the SDK handles all parsing.
import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: "YOUR_API_KEY" });

// Create tool with remoteCommands for use with LLMs
const grepTool = morph.anthropic.createWarpGrepTool({
  repoRoot: '/home/user/repo',
  remoteCommands: {
    grep: async (pattern, path, glob) => {
      const r = await sandbox.run(`rg --no-heading --line-number '${pattern}' '${path}'`);
      return r.stdout;
    },
    read: async (path, start, end) => {
      const r = await sandbox.run(`sed -n '${start},${end}p' '${path}'`);
      return r.stdout;
    },
    listDir: async (path, maxDepth) => {
      const r = await sandbox.run(`find '${path}' -maxdepth ${maxDepth}`);
      return r.stdout;
    },
  },
});

// Use with Anthropic, OpenAI, or Vercel AI SDK
const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  tools: [grepTool],
  messages: [{ role: 'user', content: 'Find auth middleware' }]
});
The SDK parses the raw output for you:
  • grep → expects ripgrep format (path:line:content)
  • read → expects raw file content (SDK adds line numbers)
  • listDir → expects one path per line (from find command)

Platform Examples

import { Sandbox } from "@e2b/code-interpreter";
import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: "YOUR_API_KEY" });
const sandbox = await Sandbox.create();
const repoDir = "/home/user/repo";

// Clone repo and install ripgrep
await sandbox.commands.run(`git clone --depth 1 https://github.com/example/repo ${repoDir}`);
await sandbox.commands.run("apt-get update && apt-get install -y ripgrep");

const grepTool = morph.anthropic.createWarpGrepTool({
  repoRoot: repoDir,
  remoteCommands: {
    grep: async (pattern, path) => {
      const r = await sandbox.commands.run(
        `rg --no-heading --line-number '${pattern}' '${path}'`,
        { cwd: repoDir }
      );
      return r.stdout || '';
    },
    read: async (path, start, end) => {
      const r = await sandbox.commands.run(`sed -n '${start},${end}p' '${path}'`);
      return r.stdout || '';
    },
    listDir: async (path, maxDepth) => {
      const r = await sandbox.commands.run(
        `find '${path}' -maxdepth ${maxDepth} -not -path '*/node_modules/*'`
      );
      return r.stdout || '';
    },
  },
});

// Use with Anthropic
const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  tools: [grepTool],
  messages: [{ role: 'user', content: 'Find authentication middleware' }]
});
Your sandbox needs ripgrep (rg) installed for the grep function. Most sandbox providers support installing it via apt-get install ripgrep.

Configuration

import { MorphClient } from '@morphllm/morphsdk';

const morph = new MorphClient({ apiKey: "YOUR_API_KEY" });

const grepTool = morph.openai.createWarpGrepTool({
  repoRoot: '.',
  excludes: ['node_modules', '.git', 'dist'],  // Glob patterns to exclude
  includes: ['src/**/*.ts'],                    // Glob patterns to include
  name: 'code_search',                          // Custom tool name
  description: 'Search for code patterns'       // Custom description
});
OptionDefaultDescription
repoRoot(required)Root directory of the repository to search
excludes['node_modules', '.git']Glob patterns to exclude from search
includes(all files)Glob patterns to include in search
namewarpgrep_codebase_searchTool name exposed to the LLM
description(see SDK)Tool description for the LLM
remoteCommands(local)Functions for remote sandbox execution
morphApiUrlhttps://api.morphllm.comOverride API base URL for proxies
timeout30000Timeout for model calls in ms (also configurable via MORPH_WARP_GREP_TIMEOUT env var)

API

Input (WarpGrepInput):
{
  query: string,            // Natural language search query
  repoRoot: string,         // Root directory to search
  excludes?: string[],      // Glob patterns to exclude
  includes?: string[],      // Glob patterns to include
  remoteCommands?: {        // For sandbox environments
    grep: (pattern, path, glob?) => Promise<string>,
    read: (path, start, end) => Promise<string>,
    listDir: (path, maxDepth) => Promise<string>,
  },
}
Returns (WarpGrepResult):
{
  success: boolean,
  contexts?: Array<{
    file: string,     // File path relative to repo root
    content: string,  // Relevant code section
  }>,
  summary?: string,   // Summary of findings
  error?: string,     // Error message if failed
}

Handling Results

const result = await morph.warpGrep.execute({
  query: 'Find auth middleware',
  repoRoot: '.'
});

if (result.success) {
  console.log(`Found ${result.contexts.length} relevant sections`);
  
  for (const ctx of result.contexts) {
    console.log(`\n--- ${ctx.file} ---`);
    console.log(ctx.content);
  }
} else {
  console.error(`Search failed: ${result.error}`);
}

Type Exports

import { 
  warpGrepInputSchema,
  executeToolCall,
  WARP_GREP_TOOL_NAME,
  WARP_GREP_DESCRIPTION,
} from '@morphllm/morphsdk/tools/warp-grep';

import type { 
  WarpGrepResult, 
  WarpGrepContext,
  WarpGrepInput,
  WarpGrepToolConfig,
  WarpGrepInputSchema,
  RemoteCommands,
} from '@morphllm/morphsdk';

Error Handling

const result = await morph.warpGrep.execute({
  query: 'Find auth',
  repoRoot: '.'
});

if (!result.success) {
  console.error(result.error);
  // "Search did not complete" | "API error" | etc.
}