> ## Documentation Index
> Fetch the complete documentation index at: https://docs.morphllm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Examples

> Production-ready agent patterns

Copy-paste examples for real-world AI agent use cases. All code is tested and production-ready.

## Cursor Clone

Build a code editor with AI assistance that searches and edits autonomously.

```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
import { MorphClient } from '@morphllm/morphsdk';
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/anthropic';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';

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

// Create tools from MorphClient namespaces
const searchTool = createCodebaseSearchTool({ 
  client: morph.codebaseSearch, 
  repoId: 'my-project' 
});
const editTool = createEditFileTool(morph.fastApply);

async function codeWithAI(instruction: string) {
  const messages = [{ role: "user", content: instruction }];
  let maxTurns = 10;
  
  while (maxTurns-- > 0) {
    const response = await anthropic.messages.create({
      model: "claude-sonnet-4-20250514",
      max_tokens: 4096,
      tools: [searchTool, editTool],
      messages
    });
    
    if (response.stop_reason === 'end_turn') break;
    
    // Handle tool calls
    messages.push({ role: 'assistant', content: response.content });
    
    const toolResults = [];
    for (const block of response.content) {
      if (block.type === 'tool_use') {
        const tool = block.name === 'edit_file' ? editTool : searchTool;
        const result = await tool.execute(block.input);
        toolResults.push({
          type: 'tool_result',
          tool_use_id: block.id,
          content: tool.formatResult(result)
        });
      }
    }
    
    messages.push({ role: 'user', content: toolResults });
  }
}

// Usage examples
await codeWithAI("Add logging to all database queries");
await codeWithAI("Refactor auth code to use middleware");
await codeWithAI("Add TypeScript types to all API routes");
```

**What it does:** Agent searches codebase → makes edits → verifies → repeats until done. No manual intervention needed.

***

## PR Review Bot

Automated code review with full codebase context. Catches security issues, performance problems, and suggests improvements.

```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';

async function reviewPR(repoId: string, prDiff: string, changedFiles: string[]) {
  const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
  
  const response = await client.messages.create({
    model: "claude-sonnet-4-5-20250514",
    tools: [createCodebaseSearchTool({ repoId })],
    messages: [{
      role: "user", 
      content: `Review this pull request:

Files: ${changedFiles.join(', ')}

${prDiff}

Provide:
1. Security issues
2. Performance concerns  
3. Code quality feedback
4. Suggestions

Search the codebase for context if needed.`
    }]
  });
  
  return response.content;
}

// GitHub Actions workflow
const diff = process.env.PR_DIFF;
const files = process.env.PR_FILES?.split(',') || [];
const review = await reviewPR('my-repo', diff, files);

// Post as PR comment
await octokit.issues.createComment({
  owner: 'your-org',
  repo: 'your-repo',
  issue_number: prNumber,
  body: review
});
```

<Accordion title="GitHub Actions YAML" icon="github">
  ```yaml theme={null}
  name: AI Code Review
  on: pull_request

  jobs:
    review:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-node@v4
        - run: npm install @morphllm/morphsdk @anthropic-ai/sdk
        - run: node review.js
          env:
            MORPH_API_KEY: ${{ secrets.MORPH_API_KEY }}
            ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  ```
</Accordion>

***

## Self-Healing Agent

Autonomous bug fixing: agent finds the issue, patches code, and verifies the fix with browser tests.

```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
import { MorphClient } from '@morphllm/morphsdk';
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';

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

async function selfHeal(bugReport: string, testUrl: string) {
  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 12000,
    tools: [
      createCodebaseSearchTool({ client: morph.codebaseSearch, repoId: 'my-app' }),
      createEditFileTool(morph.fastApply),
      createBrowserTool(morph.browser)
    ],
    messages: [{
      role: "user",
      content: `Bug: ${bugReport}

1. Search for relevant code
2. Identify the issue  
3. Apply a fix
4. Test at ${testUrl}
5. Report results`
    }]
  });
  
  // Agent autonomously: searches → fixes → tests → reports
  return response;
}

// Examples
await selfHeal('Checkout button not responding', 'https://staging.myapp.com');
await selfHeal('Login fails with Google OAuth', 'https://3000-xyz.e2b.dev');
await selfHeal('Search results not displaying', 'https://preview.vercel.app');
```

**How it works:** Agent searches codebase for bug location → makes the fix → tests in browser → reports success/failure with video proof.

***

## CI/CD E2E Testing

Natural language E2E tests that run on every PR. Get video recordings of failures automatically.

```typescript theme={null}
import { MorphClient } from '@morphllm/morphsdk';

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

async function runE2ETests(previewUrl: string, commitSha: string) {
  const tests = [
    "Test user can sign up with email and password",
    "Test user can login with valid credentials",
    "Test checkout flow with test credit card",
    "Test settings page loads and can update profile"
  ];
  
  const results = await Promise.all(
    tests.map(task => 
      morph.browser.execute({ 
        task, 
        url: previewUrl,
        maxSteps: 15,
        recordVideo: true
      })
    )
  );
  
  const failed = results.filter(r => !r.success);
  
  if (failed.length > 0) {
    // Get recordings and embed videos in PR
    const failureReports = await Promise.all(
      failed.map(async (r, i) => {
        if (r.recordingId) {
          const rec = await morph.browser.getRecording(r.recordingId);
          return {
            test: tests[i],
            videoUrl: rec.videoUrl,
            error: r.error
          };
        }
        return { test: tests[i], error: r.error };
      })
    );
    
    // Post to GitHub PR with embedded videos
    const { Octokit } = require('@octokit/rest');
    const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
    
    const prBody = `## ❌ ${failed.length} Test${failed.length > 1 ? 's' : ''} Failed

${failureReports.map(f => `
### ${f.test}
${f.error ? `**Error:** ${f.error}` : ''}

${f.videoUrl ? `
<video src="${f.videoUrl}" controls width="100%">
  <a href="${f.videoUrl}">Watch video</a>
</video>` : ''}
`).join('\n---\n')}`;

    await octokit.issues.createComment({
      owner: process.env.GITHUB_REPOSITORY_OWNER,
      repo: process.env.GITHUB_REPOSITORY?.split('/')[1],
      issue_number: parseInt(process.env.PR_NUMBER),
      body: prBody
    });
      
    throw new Error(`${failed.length} tests failed - see PR comment for videos`);
  }
  
  console.log('✅ All tests passed!');
  return results;
}

// Vercel preview integration
await runE2ETests(
  process.env.VERCEL_URL,
  process.env.VERCEL_GIT_COMMIT_SHA
);
```

<Tip>
  **Cost**: \~\$0.10 per test suite run. Videos auto-delete after 7 days. Contact support for higher concurrency limits.
</Tip>

<Accordion title="Example PR Comment with Embedded Video" icon="github">
  When tests fail, the video is embedded directly in the PR comment:

  ```markdown theme={null}
  ## ❌ 1 Test Failed

  ### Test checkout flow with test credit card
  **Error:** Checkout button not found after 15 steps

  <video src="https://morph-recordings.s3.amazonaws.com/..." controls width="100%">
    <a href="https://morph-recordings.s3.amazonaws.com/...">Watch video</a>
  </video>
  ```

  GitHub renders this as a playable video directly in the PR. No need to click links.
</Accordion>

***

## Test Debugging

When tests fail, get instant video replay with console errors and network logs.

```typescript theme={null}
import { MorphClient } from '@morphllm/morphsdk';

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

async function debugTest() {
  const result = await morph.browser.execute({
    task: "Complete checkout flow with test card",
    url: "https://staging.myapp.com",
    recordVideo: true,
    maxSteps: 30
  });

  if (!result.success) {
    console.error('❌ Test failed:', result.error);
    
    if (result.recordingId) {
      const recording = await morph.browser.getRecording(result.recordingId);
      const errors = await morph.browser.getErrors(result.recordingId);
      
      console.log('Debug info:');
      console.log('  Video:', recording.videoUrl);
      console.log('  Console logs:', recording.consoleUrl);
      console.log('  Network:', recording.networkUrl);
      console.log(`  ${errors.totalErrors} errors found`);
      
      // Post to GitHub issue with embedded video
      const { Octokit } = require('@octokit/rest');
      const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
      
      await octokit.issues.createComment({
        owner: 'your-org',
        repo: 'your-repo',
        issue_number: process.env.ISSUE_NUMBER,
        body: `## Test Failed: Checkout Flow

**Error:** ${result.error}

### Video Replay
<video src="${recording.videoUrl}" controls width="100%">
  <a href="${recording.videoUrl}">Watch video</a>
</video>

### Console Errors
${errors.totalErrors > 0 ? errors.errors.slice(0, 3).map(e => 
  `- **${e.type}:** ${e.message}`
).join('\n') : 'No console errors'}

[Full console logs](${recording.consoleUrl}) | [Network logs](${recording.networkUrl})`
      });
    }
  }
}
```

**Video embeds in GitHub:** GitHub renders `<video>` tags natively, so your team sees failures instantly in issues/PRs.

***

## Agentic GitHub App

Autonomous GitHub bot that resolves issues, creates PRs, and explains changes.

```typescript theme={null}
import { Octokit } from '@octokit/rest';
import { MorphClient } from '@morphllm/morphsdk';
import Anthropic from '@anthropic-ai/sdk';
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/anthropic';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';

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

async function handleIssue(issue: { number: number; title: string; body: string }) {
  const branchName = `fix-${issue.number}`;
  
  // Clone and create branch
  await morph.git.clone({ 
    url: 'https://github.com/your-org/your-repo',
    dir: './temp' 
  });
  await morph.git.checkout({ 
    dir: './temp', 
    branch: branchName,
    create: true 
  });
  
  // Agent autonomously fixes the issue
  let messages = [{
    role: "user" as const,
    content: `Fix issue #${issue.number}: ${issue.title}\n\n${issue.body}\n\nSearch codebase, apply fix, explain changes.`
  }];
  
  for (let i = 0; i < 10; i++) {
    const response = await anthropic.messages.create({
      model: "claude-sonnet-4-20250514",
      max_tokens: 4096,
      tools: [
        createCodebaseSearchTool({ client: morph.codebaseSearch, repoId: 'main-repo' }),
        createEditFileTool(morph.fastApply)
      ],
      messages
    });
    
    if (response.stop_reason === 'end_turn') {
      // Extract explanation for PR body
      const explanation = response.content.find(c => c.type === 'text')?.text || '';
      break;
    }
    
    // Handle tool calls and continue...
  }
  
  // Commit and push
  await morph.git.add({ dir: './temp', files: ['.'] });
  await morph.git.commit({ 
    dir: './temp', 
    message: `Fix #${issue.number}: ${issue.title}` 
  });
  await morph.git.push({ 
    dir: './temp',
    remote: 'origin',
    branch: branchName
  });
  
  // Create PR
  const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
  const pr = await octokit.pulls.create({
    owner: 'your-org',
    repo: 'your-repo',
    title: `Fix: ${issue.title}`,
    head: branchName,
    base: 'main',
    body: `Fixes #${issue.number}\n\n## Changes\n\n${explanation}`
  });
  
  console.log(`Created PR #${pr.data.number}`);
}
```

<Accordion title="Deploying as GitHub App" icon="rocket">
  1. Create GitHub App with repo access
  2. Deploy this code to Vercel/Railway/Fly
  3. Set webhook URL to your deployment
  4. Add `MORPH_API_KEY`, `ANTHROPIC_API_KEY`, `GITHUB_TOKEN` to env
  5. Bot automatically handles new issues

  **What to add:**

  * Human approval workflow before merging
  * Tests run on PR before merge
  * Fallback to request help if agent is stuck
</Accordion>

***

## Code Migration

Migrate entire codebases between frameworks with consistent patterns.

```typescript theme={null}
import { MorphClient } from '@morphllm/morphsdk';
import Anthropic from '@anthropic-ai/sdk';
import { createEditFileTool } from '@morphllm/morphsdk/tools/fastapply/anthropic';
import { createCodebaseSearchTool } from '@morphllm/morphsdk/tools/codebase-search/anthropic';
import { glob } from 'glob';

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

async function migrateFramework(from: string, to: string) {
  const files = await glob('src/**/*.{js,jsx,ts,tsx}');
  console.log(`Found ${files.length} files to migrate`);
  
  const searchTool = createCodebaseSearchTool({ 
    client: morph.codebaseSearch, 
    repoId: 'my-app' 
  });
  const editTool = createEditFileTool(morph.fastApply);
  
  let migrated = 0;
  for (const file of files) {
    try {
      const response = await anthropic.messages.create({
        model: "claude-sonnet-4-20250514",
        max_tokens: 4096,
        tools: [searchTool, editTool],
        messages: [{
          role: "user",
          content: `Migrate ${file} from ${from} to ${to}.
          
Search for migration patterns in other files to stay consistent.`
        }]
      });
      
      // Handle tool calls in loop until complete
      // ... (tool handling logic)
      
      migrated++;
      console.log(`✅ ${migrated}/${files.length} - ${file}`);
    } catch (error) {
      console.error(`❌ Failed: ${file}`, error);
    }
  }
  
  console.log(`\n✅ Migrated ${migrated}/${files.length} files`);
}

// Migrate React to Solid.js
await migrateFramework('React', 'Solid.js');
```

**Use cases:** React → Vue, JavaScript → TypeScript, Class components → Hooks, REST → GraphQL

***

## More Examples

<CardGroup cols={2}>
  <Card title="Documentation Bot" icon="book">
    Auto-generate docs from code
  </Card>

  <Card title="Security Auditor" icon="shield">
    Scan for vulnerabilities
  </Card>

  <Card title="Refactoring Agent" icon="code-branch">
    Large-scale code cleanup
  </Card>

  <Card title="Test Generator" icon="flask">
    Generate unit & E2E tests
  </Card>
</CardGroup>

## Need Help?

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/sdk/reference">
    Complete API docs
  </Card>

  <Card title="Dashboard" icon="chart-line" href="https://morphllm.com/dashboard">
    Get API keys & monitor usage
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/morph">
    Ask questions & share builds
  </Card>

  <Card title="Support" icon="headset" href="mailto:support@morphllm.com">
    Email us for help
  </Card>
</CardGroup>
