Quick Start
- Anthropic
- OpenAI
- Gemini
- Vercel AI SDK
- Standalone
Copy
Ask AI
import Anthropic from '@anthropic-ai/sdk';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/anthropic';
const anthropic = new Anthropic();
const grepTool = createWarpGrepTool({
repoRoot: '.',
morphApiKey: process.env.MORPH_API_KEY
});
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));
}
Copy
Ask AI
import OpenAI from 'openai';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/openai';
const openai = new OpenAI();
const grepTool = createWarpGrepTool({
repoRoot: '.',
morphApiKey: process.env.MORPH_API_KEY
});
const response = await openai.chat.completions.create({
model: 'gpt-4o',
tools: [grepTool],
messages: [{ role: 'user', content: 'Find authentication middleware' }]
});
// Execute tool call
const toolCall = response.choices[0].message.tool_calls?.[0];
if (toolCall) {
const result = await grepTool.execute(toolCall.function.arguments);
console.log(grepTool.formatResult(result));
}
Copy
Ask AI
import { GoogleGenerativeAI, FunctionCallingMode } from '@google/generative-ai';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const grepTool = createWarpGrepTool({
repoRoot: '.',
morphApiKey: process.env.MORPH_API_KEY
});
const model = genAI.getGenerativeModel({
model: 'gemini-2.0-flash',
tools: [{ functionDeclarations: [grepTool] }],
toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.AUTO } }
});
const chat = model.startChat();
const response = await chat.sendMessage('Find authentication middleware');
// Handle function call
const call = response.response.functionCalls()?.[0];
if (call) {
const result = await grepTool.execute(call.args);
// Send result back to model
await chat.sendMessage([{
functionResponse: {
name: call.name,
response: { result: grepTool.formatResult(result) }
}
}]);
}
Copy
Ask AI
import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/vercel';
const grepTool = createWarpGrepTool({
repoRoot: '.',
morphApiKey: process.env.MORPH_API_KEY
});
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: { grep: grepTool },
prompt: 'Find authentication middleware'
});
Copy
Ask AI
import { WarpGrepClient } from '@morphllm/morphsdk/tools/warp-grep';
const client = new WarpGrepClient({ morphApiKey: process.env.MORPH_API_KEY });
const result = await client.execute({
query: 'Find authentication middleware',
repoRoot: '.'
});
if (result.success) {
for (const ctx of result.contexts) {
console.log(`File: ${ctx.file}`);
console.log(ctx.content);
}
}
Remote Execution
When your code lives in a remote sandbox (E2B, Modal, Daytona, Docker, SSH), use theremoteCommands option. You provide three simple functions that return raw stdout — the SDK handles all parsing.
The remoteCommands option works with all SDK adapters:
- Anthropic
- OpenAI
- Gemini
- Vercel AI SDK
Copy
Ask AI
import Anthropic from '@anthropic-ai/sdk';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/anthropic';
const anthropic = new Anthropic();
const grepTool = createWarpGrepTool({
repoRoot: '/home/user/repo',
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path, glob) => {
const r = await sandbox.run(`rg --no-heading '${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;
},
},
});
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 4096,
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));
}
Copy
Ask AI
import OpenAI from 'openai';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/openai';
const openai = new OpenAI();
const grepTool = createWarpGrepTool({
repoRoot: '/home/user/repo',
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path, glob) => {
const r = await sandbox.run(`rg --no-heading '${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;
},
},
});
const response = await openai.chat.completions.create({
model: 'gpt-4o',
tools: [grepTool],
messages: [{ role: 'user', content: 'Find authentication middleware' }]
});
// Execute tool call
const toolCall = response.choices[0].message.tool_calls?.[0];
if (toolCall) {
const result = await grepTool.execute(toolCall.function.arguments);
console.log(grepTool.formatResult(result));
}
Copy
Ask AI
import { GoogleGenerativeAI, FunctionCallingMode } from '@google/generative-ai';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/gemini';
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const grepTool = createWarpGrepTool({
repoRoot: '/home/user/repo',
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path, glob) => {
const r = await sandbox.run(`rg --no-heading '${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;
},
},
});
const model = genAI.getGenerativeModel({
model: 'gemini-2.0-flash',
tools: [{ functionDeclarations: [grepTool] }],
toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.AUTO } }
});
const chat = model.startChat();
const response = await chat.sendMessage('Find authentication middleware');
// Handle function call
const call = response.response.functionCalls()?.[0];
if (call) {
const result = await grepTool.execute(call.args);
await chat.sendMessage([{
functionResponse: {
name: call.name,
response: { result: grepTool.formatResult(result) }
}
}]);
}
Copy
Ask AI
import { generateText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/vercel';
const grepTool = createWarpGrepTool({
repoRoot: '/home/user/repo',
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path, glob) => {
const r = await sandbox.run(`rg --no-heading '${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;
},
},
});
// Vercel AI SDK handles tool execution automatically
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: { grep: grepTool },
prompt: 'Find authentication 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 (fromfindcommand)
Platform Examples
- E2B
- Modal
- Daytona
- Docker/SSH
Copy
Ask AI
import { Sandbox } from "@e2b/code-interpreter";
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/anthropic';
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 = createWarpGrepTool({
repoRoot: repoDir,
morphApiKey: process.env.MORPH_API_KEY,
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 || '';
},
},
});
// Now use grepTool with Anthropic, OpenAI, Gemini, or Vercel AI SDK
Copy
Ask AI
import { ModalClient } from "modal";
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/openai';
const modal = new ModalClient();
const sandbox = await modal.sandboxes.create(app, image);
const repoDir = "/home/repo";
const grepTool = createWarpGrepTool({
repoRoot: repoDir,
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path) => {
const proc = await sandbox.exec([
"rg", "--no-heading", "--line-number", pattern, path
]);
return await proc.stdout.readText();
},
read: async (path, start, end) => {
const proc = await sandbox.exec(["sed", "-n", `${start},${end}p`, path]);
return await proc.stdout.readText();
},
listDir: async (path, maxDepth) => {
const proc = await sandbox.exec([
"find", path, "-maxdepth", String(maxDepth)
]);
return await proc.stdout.readText();
},
},
});
// Now use grepTool with Anthropic, OpenAI, Gemini, or Vercel AI SDK
Copy
Ask AI
import { Daytona } from "@daytonaio/sdk";
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/vercel';
const daytona = new Daytona({ apiKey: process.env.DAYTONA_API_KEY });
const sandbox = await daytona.create({ language: 'python' });
const repoDir = "/home/daytona/repo";
const grepTool = createWarpGrepTool({
repoRoot: repoDir,
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path) => {
const r = await sandbox.process.executeCommand(
`rg --no-heading --line-number '${pattern}' '${path}'`,
repoDir
);
return r.result || '';
},
read: async (path, start, end) => {
const r = await sandbox.process.executeCommand(
`sed -n '${start},${end}p' '${path}'`,
repoDir
);
return r.result || '';
},
listDir: async (path, maxDepth) => {
const r = await sandbox.process.executeCommand(
`find '${path}' -maxdepth ${maxDepth}`,
repoDir
);
return r.result || '';
},
},
});
// Now use grepTool with Anthropic, OpenAI, Gemini, or Vercel AI SDK
Copy
Ask AI
import { NodeSSH } from 'node-ssh';
import { createWarpGrepTool } from '@morphllm/morphsdk/tools/warp-grep/anthropic';
const ssh = new NodeSSH();
await ssh.connect({ host: 'your-server.com', username: 'user', privateKey: '...' });
const repoDir = "/home/user/repo";
const grepTool = createWarpGrepTool({
repoRoot: repoDir,
morphApiKey: process.env.MORPH_API_KEY,
remoteCommands: {
grep: async (pattern, path) => {
const result = await ssh.execCommand(
`rg --no-heading --line-number '${pattern}' '${path}'`,
{ cwd: repoDir }
);
return result.stdout || '';
},
read: async (path, start, end) => {
const result = await ssh.execCommand(`sed -n '${start},${end}p' '${path}'`);
return result.stdout || '';
},
listDir: async (path, maxDepth) => {
const result = await ssh.execCommand(`find '${path}' -maxdepth ${maxDepth}`);
return result.stdout || '';
},
},
});
// Now use grepTool with Anthropic, OpenAI, Gemini, or Vercel AI SDK
Your sandbox needs
ripgrep (rg) installed for the grep function. Most sandbox providers support installing it via apt-get install ripgrep.Customize Tool Name and Description
Override the default tool name and description:Copy
Ask AI
const grepTool = createWarpGrepTool({
repoRoot: '.',
morphApiKey: process.env.MORPH_API_KEY,
name: 'code_search',
description: 'Search for code patterns in the repository'
});
| Option | Default | Description |
|---|---|---|
name | warpgrep_codebase_search | Tool name exposed to the LLM |
description | (see SDK) | Tool description for the LLM |
Response Types
Both direct usage and tool usage return the same structure:Copy
Ask AI
interface 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
Copy
Ask AI
const result = await grepTool.execute({ query: 'Find auth middleware' });
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
Copy
Ask AI
import type {
WarpGrepResult,
WarpGrepContext,
WarpGrepToolConfig,
RemoteCommands,
// For custom provider implementations
WarpGrepProvider,
GrepResult,
ReadResult,
ListDirectoryEntry,
} from '@morphllm/morphsdk/tools/warp-grep';
Advanced: Custom Provider
For maximum control, implement the fullWarpGrepProvider interface:
Copy
Ask AI
import type { WarpGrepProvider } from '@morphllm/morphsdk/tools/warp-grep';
import { runWarpGrep } from '@morphllm/morphsdk/tools/warp-grep';
const provider: WarpGrepProvider = {
grep: async ({ pattern, path, glob }) => {
// Return { lines: ['path:line:content', ...] }
return { lines: [...] };
},
read: async ({ path, start, end }) => {
// Return { lines: ['1|content', '2|content', ...] }
return { lines: [...] };
},
listDirectory: async ({ path, maxDepth }) => {
// Return array of entries
return [{ name: 'file.ts', path: 'src/file.ts', type: 'file', depth: 1 }];
},
};
const result = await runWarpGrep({
query: 'Find authentication middleware',
repoRoot: '/path/to/repo',
provider,
morphApiKey: process.env.MORPH_API_KEY,
});
Most users should use
remoteCommands instead. Only use WarpGrepProvider if you need to customize the output format or add caching/batching logic.