MorphClient
Unified client for all Morph tools.Copy
Ask AI
import { MorphClient } from '@morphllm/morphsdk';
const morph = new MorphClient({
apiKey?: string; // Default: process.env.MORPH_API_KEY
debug?: boolean; // Default: false (enables logging)
timeout?: number; // Default: varies by tool
retryConfig?: RetryConfig; // Optional retry configuration
});
Namespaces
Copy
Ask AI
morph.fastApply // FastApplyClient
morph.codebaseSearch // CodebaseSearchClient
morph.browser // BrowserClient
morph.git // MorphGit
Standalone Clients (Advanced)
Need custom configuration per tool? Use individual clients:Copy
Ask AI
import { BrowserClient, FastApplyClient } from '@morphllm/morphsdk';
// Browser with custom API URL
const browser = new BrowserClient({
apiKey: process.env.MORPH_API_KEY,
apiUrl: 'http://localhost:8000', // Custom endpoint
timeout: 180000
});
// FastApply with different settings
const fastApply = new FastApplyClient({
apiKey: process.env.MORPH_API_KEY,
timeout: 60000
});
Use when: You need tool-specific configuration that differs from defaults (custom URLs, different timeouts, etc.).
Fast Apply
morph.fastApply.execute(input, overrides?)
Edit files with AI-powered merge.
Copy
Ask AI
const result = await morph.fastApply.execute({
target_filepath: 'src/auth.ts',
baseDir: './my-project', // Optional: defaults to cwd
instructions: 'Add error handling',
code_edit: '// ... existing code ...\nif (!user) throw new Error("Invalid");\n// ... existing code ...'
}, {
// Optional overrides
generateUdiff: true,
autoWrite: true,
timeout: 60000
});
console.log(result.udiff);
console.log(result.changes); // { linesAdded, linesRemoved, linesModified }
Framework Adapters
Copy
Ask AI
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/anthropic';
const tool = createEditFileTool(morph.fastApply);
// OR with config: createEditFileTool({ morphApiKey: '...' })
Types
Copy
Ask AI
interface EditFileInput {
target_filepath: string;
instructions: string;
code_edit: string;
}
interface EditFileResult {
success: boolean;
filepath: string;
udiff?: string;
changes: {
linesAdded: number;
linesRemoved: number;
linesModified: number;
};
error?: string;
}
Codebase Search
morph.codebaseSearch.search(input, overrides?)
Semantic code search with 2-stage retrieval.
Copy
Ask AI
const result = await morph.codebaseSearch.search({
query: 'How does user authentication work?',
repoId: 'my-project', // Required per search
target_directories: ['src/auth'], // or [] for entire repo
explanation: 'Finding auth logic',
limit: 10
}, {
// Optional overrides
timeout: 60000,
searchUrl: 'https://custom-search.example.com'
});
console.log(result.results); // Top 10 code chunks
console.log(result.stats); // { totalResults, candidatesRetrieved, searchTimeMs }
Framework Adapters
Copy
Ask AI
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';
const tool = createCodebaseSearchTool({
client: morph.codebaseSearch,
repoId: 'my-project'
});
// OR with config: createCodebaseSearchTool({ repoId: 'my-project' })
Types
Copy
Ask AI
interface CodebaseSearchInput {
query: string;
target_directories: string[];
explanation: string;
limit?: number; // Default: 10
}
interface CodeSearchResult {
filepath: string; // "auth.ts::AuthService.login@L10-L25"
symbolPath: string; // "AuthService.login"
content: string; // Function/class code
language: string; // "typescript"
startLine: number;
endLine: number;
embeddingSimilarity: number; // 0-1
rerankScore: number; // 0-1 (higher = more relevant)
}
interface CodebaseSearchResult {
success: boolean;
results: CodeSearchResult[];
stats: {
totalResults: number;
candidatesRetrieved: number;
searchTimeMs: number;
};
error?: string;
}
Requires git push: Code must be pushed with MorphGit to generate embeddings before searching.
Git Operations
morph.git.*
Access the MorphGit client via morph.git.
Copy
Ask AI
// All standard git operations available
await morph.git.init({ repoId: 'my-project', dir: './project' });
await morph.git.clone({ repoId: 'my-project', dir: './project' });
await morph.git.add({ dir: './project', filepath: '.' });
await morph.git.commit({ dir: './project', message: 'Update' });
await morph.git.push({ dir: './project' });
await morph.git.pull({ dir: './project' });
Repository Management
Copy
Ask AI
// Initialize new repository
await morph.git.init({
repoId: string;
dir: string;
defaultBranch?: string; // Default: 'main'
});
// Clone existing repository
await morph.git.clone({
repoId: string;
dir: string;
branch?: string;
depth?: number;
singleBranch?: boolean; // Default: true
});
Basic Operations
Copy
Ask AI
// Stage files
await morph.git.add({
dir: string;
filepath: string; // Use '.' for all files
});
// Commit changes
const sha = await morph.git.commit({
dir: string;
message: string;
author?: { name: string; email: string; };
});
// Push to remote (triggers auto-embedding)
await morph.git.push({
dir: string;
remote?: string; // Default: 'origin'
branch?: string;
});
// Pull from remote
await morph.git.pull({
dir: string;
remote?: string;
branch?: string;
});
Status & History
Copy
Ask AI
// Get file status
const status = await morph.git.status({
dir: string;
filepath: string;
});
// Returns: 'modified' | '*added' | 'deleted' | 'unmodified' | 'absent'
// Get all file statuses
const matrix = await morph.git.statusMatrix({ dir: string });
// Returns: { filepath: string; status: string; }[]
// Get commit history
const commits = await morph.git.log({
dir: string;
depth?: number;
ref?: string;
});
Branching
Copy
Ask AI
// Create branch
await morph.git.branch({
dir: string;
name: string;
checkout?: boolean; // Default: false
});
// Checkout branch/commit
await morph.git.checkout({
dir: string;
ref: string;
});
// List all branches
const branches = await morph.git.listBranches({ dir: string });
// Get current branch
const current = await morph.git.currentBranch({ dir: string });
// Get commit hash
const hash = await morph.git.resolveRef({ dir: string; ref: 'HEAD' });
Auto-embedding on push: Every
git.push() triggers automatic embedding generation for semantic search (~8 seconds in background).Browser Automation
morph.browser.execute(input)
Execute browser automation tasks.
Copy
Ask AI
const result = await morph.browser.execute({
task: 'Test login with email test@example.com',
url: 'https://3000-xyz.e2b.dev',
max_steps: 15,
model: 'morph-computer-use-v0', // or 'gemini-flash-latest'
record_video: false,
viewport_width: 1280,
viewport_height: 720
});
console.log(result.success);
console.log(result.result);
console.log(result.steps_taken);
morph.browser.executeWithRecording(input)
Execute with recording and wait for video to be ready.
Copy
Ask AI
const result = await morph.browser.executeWithRecording({
task: 'Test checkout flow',
url: 'https://staging.myapp.com',
max_steps: 20,
record_video: true,
video_width: 1280,
video_height: 720,
repo_id: 'my-app', // Optional
commit_id: 'commit-uuid' // Optional
});
// Video is ready!
console.log(result.recording?.video_url);
console.log(result.recording?.file_size);
console.log(result.recording?.status); // 'COMPLETED'
Recording Management
Copy
Ask AI
// Get recording status
const recording = await morph.browser.getRecording(recordingId);
console.log(recording.status); // PENDING | PROCESSING | COMPLETED | ERROR
console.log(recording.video_url); // Presigned S3 URL (7 days)
console.log(recording.replay_url); // rrweb replay URL
console.log(recording.network_url); // Network logs
console.log(recording.console_url); // Console logs
// Wait for recording to complete
const recording = await morph.browser.waitForRecording(
recordingId,
{ timeout: 60000, pollInterval: 2000 }
);
// Get console errors with screenshots
const { errors, total_errors } = await morph.browser.getErrors(recordingId);
console.log(total_errors);
errors.forEach(e => {
console.log(e.type); // 'console' | 'network'
console.log(e.message);
console.log(e.screenshot_url); // Screenshot captured 500ms after error
console.log(e.url); // Page URL where error occurred
});
Framework Adapters
Copy
Ask AI
import { createBrowserTool } from '@morphllm/morphsdk/tools/browser/anthropic';
const tool = createBrowserTool(morph.browser);
// OR with config: createBrowserTool({ apiKey: '...' })
Types
Copy
Ask AI
interface BrowserTaskInput {
task: string;
url?: string;
max_steps?: number; // 1-50, default: 10
record_video?: boolean; // Default: false
video_width?: number; // Default: 1280
video_height?: number; // Default: 720
viewport_width?: number; // Default: 1280
viewport_height?: number; // Default: 720
repo_id?: string;
commit_id?: string;
}
interface BrowserTaskResult {
success: boolean;
result?: string;
steps_taken?: number;
execution_time_ms?: number;
recording_id?: string;
recording_status?: string;
replay_url?: string;
error?: string;
}
interface RecordingStatus {
id: string;
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'ERROR';
video_url?: string; // Presigned S3 URL (expires in 7 days)
replay_url?: string; // rrweb replay
file_size?: number;
total_events?: number;
created_at: string;
completed_at?: string;
error?: string;
}
Video limits: Videos are limited to 3 minutes. Presigned URLs expire after 7 days. Videos auto-delete after 30 days.
Environment Variables
Copy
Ask AI
# Required for most tools
MORPH_API_KEY=sk-your-key-here
# Optional overrides (advanced users only)
MORPH_API_URL=https://api.morphllm.com # Fast Apply API
MORPH_SEARCH_URL=http://embedrerank.morphllm.com:8081 # Search API
MORPH_ENVIRONMENT=DEV # Use localhost for browser worker
Import Patterns
Main SDK (Recommended)
Copy
Ask AI
// Unified client
import { MorphClient } from '@morphllm/morphsdk';
// Individual clients (for advanced use)
import {
BrowserClient,
FastApplyClient,
CodebaseSearchClient,
MorphGit
} from '@morphllm/morphsdk';
// All types
import type {
BrowserTaskInput,
EditFileInput,
CodebaseSearchInput,
// ... etc
} from '@morphllm/morphsdk';
Framework Adapters
Copy
Ask AI
// Anthropic
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/anthropic';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';
import { createBrowserTool } from '@morphllm/morphsdk/tools/browser/anthropic';
// OpenAI
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/openai';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/openai';
import { createBrowserTool } from '@morphllm/morphsdk/tools/browser/openai';
// Vercel
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/vercel';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/vercel';
import { createBrowserTool } from '@morphllm/morphsdk/tools/browser/vercel';
Error Handling
All tools return results withsuccess: boolean and optional error: string.
Copy
Ask AI
const result = await morph.fastApply.execute({ ... });
if (!result.success) {
console.error('Edit failed:', result.error);
// Handle error...
}
const searchResults = await morph.codebaseSearch.search({ ... });
if (!searchResults.success) {
console.error('Search failed:', searchResults.error);
}
Automatic retries: SDK automatically retries failed requests with exponential backoff for transient errors (rate limits, timeouts).