Skip to main content
Prerequisite: You’ll need an account on Morph to access embeddings for larger repositories.

The Right Tool for the Right Size

Code retrieval should be simple by default, sophisticated when necessary. The approach depends entirely on your repository size:

Small Repos (<200 files)

Agent Search: Let Claude navigate file paths and symbols directly

Large Repos (200+ files)

Retrieval Funnel: Embeddings → Reranking → Agent Reading
For repositories under 200 files, skip the complexity. Use agent search where you give Claude three simple tools:

The Three Essential Tools

{
  "name": "list_dir",
  "description": "List directory contents to understand project structure",
  "parameters": {
    "properties": {
      "relative_workspace_path": {
        "description": "Path to list contents of, relative to workspace root",
        "type": "string"
      }
    }
  }
}
Let Claude explore the file structure naturally.
{
  "name": "file_search", 
  "description": "Find files by partial filename match",
  "parameters": {
    "properties": {
      "query": {
        "description": "Partial filename to search for",
        "type": "string"
      }
    }
  }
}
When Claude knows roughly what file it’s looking for.
{
  "name": "read_file",
  "description": "Read file contents with optional line range",
  "parameters": {
    "properties": {
      "target_file": {
        "description": "Path to the file to read",
        "type": "string"
      },
      "start_line": {
        "description": "Optional: Start reading from this line",
        "type": "integer"
      },
      "end_line": {
        "description": "Optional: Stop reading at this line", 
        "type": "integer"
      }
    }
  }
}
Let Claude decide what to read based on what it discovers.
{
  "name": "semantic_grep",
  "description": "Search for code semantically similar to a query using embeddings",
  "parameters": {
    "properties": {
      "query": {
        "description": "Natural language description of code to find",
        "type": "string"
      },
      "file_patterns": {
        "description": "Optional: File patterns to search within (e.g., '*.py', '*.ts')",
        "type": "array"
      }
    }
  }
}
When Claude needs to find code by meaning, not just filename.
async function semanticGrep(query: string, filePatterns?: string[]) {
  // 1. Claude outputs semantic query: "error handling for API calls"
  // 2. Embed the query
  const queryEmbedding = await embed(query);
  
  // 3. Compare against pre-embedded file chunks
  const matches = await findSimilar(queryEmbedding, {
    patterns: filePatterns,
    threshold: 0.7,
    limit: 10
  });
  
  return matches; // Claude gets semantic matches to explore
}
Benefits:
  • Zero setup time
  • No indexing required
  • Claude makes intelligent choices about what to read
  • Works perfectly for most development scenarios

Large Repositories: The Retrieval Funnel

When you hit 200+ files, raw agent search becomes inefficient. Use the retrieval funnel:
1

🔍 Cast Wide Net

Embeddings: Find 50-100 potentially relevant code chunks using Morph Embeddings
2

⚡ Focus Down

Reranking: Narrow to the 5-10 most relevant pieces using Morph Rerank
3

🧠 Agent Reading

Claude: Inspect the ranked results and decide what to read in full

Implementation: The Funnel Approach

import { OpenAI } from 'openai';

const openai = new OpenAI({
  apiKey: process.env.MORPH_API_KEY,
  baseURL: 'https://api.morphllm.com/v1'
});

async function retrievalFunnel(query: string) {
  // Step 1: Cast wide net with embeddings
  const embedding = await openai.embeddings.create({
    model: "morph-embedding-v3",
    input: query
  });
  
  const wideResults = await vectorSearch(embedding, { limit: 50 });
  
  // Step 2: Focus with reranking  
  const reranked = await openai.completions.create({
    model: "morph-rerank-v3",
    documents: wideResults.map(r => r.content),
    query: query,
    top_k: 8
  });
  
  // Step 3: Let Claude decide what to read
  return provideCandidatesToClaude(reranked.data);
}

When to Use Each Approach

Decision Tree

Repository size?
├── < 200 files → Agent Search
│   ├── Basic: list_dir + file_search + read_file
│   └── +semantic_grep for meaning-based search (optional)
└── 200+ files → Retrieval Funnel
    ├── < 1000 files → Basic embeddings + rerank
    └── 1000+ files → Add AST parsing + hybrid search

Best Practices

  • Begin with agent search for any new project
  • Only add complexity when Claude starts missing relevant code
  • Most projects never need embeddings
  • Switch to retrieval funnel when search becomes slow/inaccurate
  • Usually happens around 200-500 files depending on structure
  • Monitor Claude’s success rate in finding relevant code
  • Even with embeddings, let Claude make final reading decisions
  • Provide candidates, not conclusions
  • Claude’s reasoning beats pure similarity matching

Performance Expectations

Typical Performance

Repository SizeApproachSearch TimeSuccess Rate
< 200 filesAgent Search< 5 seconds95%+
200-1000 filesBasic Funnel< 10 seconds90%+
1000+ filesAdvanced Funnel< 15 seconds85%+
The key insight: Most code retrieval problems are solved by giving Claude the right navigation tools, not by throwing embeddings at everything. Ready to implement? Get your API key for repositories that need the retrieval funnel, or just start with agent search for everything else.