Skip to main content
This page covers how to execute WarpGrep’s tools (grep, read, list directory) in a remote sandbox, so your agent can search code that lives in a cloud environment. If you haven’t set up WarpGrep as a tool yet, start with the Agent Tool guide first.

Remote Commands

The simplest way to run WarpGrep in a sandbox. Provide three functions that execute shell commands remotely — the SDK handles all parsing.
import { MorphClient } from '@morphllm/morphsdk';

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

const grepTool = morph.anthropic.createWarpGrepTool({
  repoRoot: '/home/user/repo',
  remoteCommands: {
    grep: async (pattern, path, glob) => { /* run rg remotely */ },
    read: async (path, start, end) => { /* read file remotely */ },
    listDir: async (path, maxDepth) => { /* list dir remotely */ },
  },
});
The SDK parses the raw output for you:
  • grep — return ripgrep stdout (path:line:content format with -C 1 context lines)
  • read — return raw file content (SDK adds line numbers)
  • listDir — return one path per line (find command output)

Platform Examples

See complete, runnable examples for each platform:

Custom Providers

A provider is a set of tool implementations (grep, read, list directory) that override WarpGrep’s defaults. WarpGrep ships with built-in tools for Linux, macOS, and Windows. If your code runs in a non-standard environment — or you need to replace the built-in tools entirely — implement the WarpGrepProvider interface. Most users should use remoteCommands above instead.

Provider Interface

interface WarpGrepProvider {
  grep: (args: {
    pattern: string;
    path: string;
    glob?: string;
  }) => Promise<{ lines: string[]; error?: string }>;

  read: (args: {
    path: string;
    start?: number;
    end?: number;
  }) => Promise<{ lines: string[]; error?: string }>;

  listDirectory: (args: {
    path: string;
    maxDepth?: number;
  }) => Promise<Array<{
    name: string;
    path: string;
    type: 'file' | 'directory';
    depth: number;
  }>>;
}

Required Output Formats

grep — ripgrep-style output:
{ lines: [
  'src/auth/login.ts:45:export function authenticate(user: User) {',
  'src/auth/login.ts-46-  return validateCredentials(user);',
]}
// Match lines use `:`, context lines use `-`
read — numbered lines:
{ lines: [
  '1|import { User } from "./types";',
  '2|import { hash } from "./crypto";',
]}
// Format: lineNumber|content
listDirectory — structured entries:
[
  { name: 'auth', path: 'src/auth', type: 'directory', depth: 1 },
  { name: 'login.ts', path: 'src/auth/login.ts', type: 'file', depth: 2 },
]

Usage

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

const provider: WarpGrepProvider = {
  grep: async ({ pattern, path, glob }) => {
    const results = await myCustomGrep(pattern, path, glob);
    return { lines: results };
  },
  read: async ({ path, start, end }) => {
    const content = await myCustomRead(path, start, end);
    return { lines: content.split('\n').map((l, i) => `${(start || 1) + i}|${l}`) };
  },
  listDirectory: async ({ path, maxDepth }) => {
    return await myCustomListDir(path, maxDepth);
  },
};

const morph = new MorphClient({ apiKey: process.env.MORPH_API_KEY });
const result = await morph.warpGrep.execute({
  query: 'Find auth middleware',
  repoRoot: '/path/to/repo',
  provider,
});
Custom providers work with streaming (streamSteps: true).