Skip to main content
AI agents edit files using // ... existing code ... markers instead of sending full files. Morph merges server-side at 10,500 tokens/s. Why this matters: Traditional search-replace uses 40% more tokens and takes more turns. Fast Apply is instant.

Installation

npm install @morphllm/morphsdk

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();

// Tool inherits API key from MorphClient
const tool = morph.anthropic.createEditFileTool();

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-5-20250929",
  max_tokens: 12000,
  tools: [tool],
  messages: [{ 
    role: "user", 
    content: "Add error handling to src/auth.ts" 
  }]
});
The instructions parameter provides crucial context for ambiguous edits, helping the apply model make correct decisions and achieve near perfect accuracy. Have the parent model generate the instructions.

How It Works

Agent outputs lazy edit:
async function login(email: string, password: string) {
  // ... existing code ...
  
  if (!user) {
    throw new Error('Invalid credentials');
  }
  
  // ... existing code ...
}
Morph merges into your actual file:
@@ -12,6 +12,10 @@
   const user = await db.findUser(email);
+  
+  if (!user) {
+    throw new Error('Invalid credentials');
+  }
   
   return createSession(user);
Key: The // ... existing code ... markers tell Morph where to insert changes without sending the full file.

Direct Usage

Use without an agent:
const result = await morph.fastApply.execute({
  target_filepath: 'src/auth.ts',
  instructions: 'I will add null check',
  code_edit: '// ... existing code ...\nif (!user) throw new Error("Not found");\n// ... existing code ...'
});

console.log(result.success); // true
console.log(`+${result.changes.linesAdded} -${result.changes.linesRemoved}`);

Code-in/Code-out (Sandbox Support)

Use applyEdit when you manage your own filesystem or work in sandboxes like E2B, Modal, or Daytona:
import { applyEdit } from '@morphllm/morphsdk';

// Read file yourself (from sandbox, memory, etc.)
const originalCode = await sandbox.readFile('src/auth.ts');

const result = await applyEdit({
  originalCode,
  codeEdit: '// ... existing code ...\nif (!user) throw new Error("Not found");\n// ... existing code ...',
  instructions: 'Add null check',
  filepath: 'src/auth.ts'  // Optional, for udiff context
});

if (result.success) {
  // Write file yourself
  await sandbox.writeFile('src/auth.ts', result.mergedCode);
  console.log(result.udiff);  // View the diff
}
applyEdit returns mergedCode instead of writing to disk—perfect for sandbox environments where you control file I/O.

Configuration

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

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

const tool = morph.openai.createEditFileTool({
  baseDir: './src',       // Default: process.cwd()
  autoWrite: true,        // Auto-write files (default: true)
  generateUdiff: true     // Return diff (default: true)
});

API

Input (EditFileInput):
{
  target_filepath: string,  // Relative to baseDir
  instructions: string,     // What the model is changing
  code_edit: string         // Code with // ... existing code ...
}
Returns (EditFileResult):
{
  success: boolean,
  filepath: string,
  changes: { linesAdded, linesRemoved, linesModified },
  udiff?: string,
  error?: string
}
All types are exported from the SDK root:
import type { 
  EditFileInput, 
  EditFileResult, 
  ApplyEditInput, 
  ApplyEditResult,
  EditChanges 
} from '@morphllm/morphsdk';

Error Handling

if (!result.success) {
  console.error(result.error);
  // "File not found" | "Invalid filepath" | "API error"
}