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

Why Agent Search Works for Small Repos

// Simple implementation - minimal setup needed
async function agentSearch(query: string) {
  // 1. Claude explores with list_dir
  // 2. Claude searches with file_search if needed
  // 3. Claude uses semantic_grep for meaning-based search (optional)
  // 4. Claude reads relevant files with read_file
  // 5. Claude has full context to answer
  
  return "Let Claude navigate naturally";
}

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-v2",
    input: query
  });
  
  const wideResults = await vectorSearch(embedding, { limit: 50 });
  
  // Step 2: Focus with reranking  
  const reranked = await openai.completions.create({
    model: "morph-rerank-v2",
    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

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.