Iterative Retrieval
Credit
Original pattern by Affaan Mustafa.
This version keeps the same core idea and adds clearer steps and safety checks.
Purpose
Use this skill when a sub-agent needs local project context.
A sub-agent may not know:
- Which files matter
- What names the project uses
- Where a feature starts
- Which tests or types support it
Do not send the whole project. Do not guess once and stop. Search in small rounds.
Do not use the web or make outside calls. Search only the local project data that the user allowed you to read.
The Four-Step Loop
Run this loop up to three times:
- Search for likely files.
- Review each result.
- Refine the search.
- Repeat until the context is enough.
Step 1: Search
Start with the task words and likely file paths.
const query = {
patterns: ["src/**/*.ts", "lib/**/*.ts"],
keywords: ["auth", "user", "session", "token"],
excludes: ["node_modules/**", "dist/**", "*.test.ts"]
};
const files = await retrieveLocalFiles(query);Use project search tools when they exist. Follow the project rules in AGENTS.md, CLAUDE.md, or similar files.
Start broad, but set clear limits:
- Search likely source folders first.
- Skip build output and vendor code.
- Limit the number and size of results.
- Search file names, code names, and task words.
- Do not read secret files, key files, or hidden login data.
Step 2: Review
Score each file from 0 to 1.
function reviewFiles(files, task) {
return files.map(file => ({
path: file.path,
score: scoreFile(file, task),
reason: explainScore(file, task),
gaps: findMissingContext(file, task)
}));
}Use these score bands:
0.8to1.0: Directly handles the task0.5to0.79: Has a needed type, call, rule, or test0.2to0.49: May help, but is not central- Below
0.2: Not useful for this task
Give a short reason for each kept file. A name match alone is not enough. Check what the file does.
Look for gaps such as:
- The caller is missing
- A shared type is missing
- A config value is missing
- The matching test is missing
- The code uses another name for the same idea
- A generated file points to a real source file
Step 3: Refine
Use what you learned to make the next search better.
function refineQuery(review, oldQuery) {
return {
patterns: unique([
...oldQuery.patterns,
...findRelatedPaths(review)
]),
keywords: unique([
...oldQuery.keywords,
...findProjectTerms(review)
]),
excludes: unique([
...oldQuery.excludes,
...findSafeExcludes(review)
]),
focus: unique(
review.flatMap(item => item.gaps)
)
};
}Refine with facts from the code:
- Add names of called functions.
- Add imported type names.
- Add route, event, table, or config names.
- Search for callers and tests.
- Search for the project term when it differs from the task term.
- Exclude a whole path only when it is clearly not useful.
Do not keep adding the same words. If a new search would be the same as the last one, stop.
Step 4: Repeat or Stop
Stop when the files answer these questions:
- Where does the behavior start?
- Where is the main behavior defined?
- What data, type, or config does it use?
- Is there a test or example?
- Is any key link still missing?
Three good files may be enough. Do not require a fixed file count.
async function iterativeRetrieve(task, maxRounds = 3) {
let query = createInitialQuery(task);
let best = [];
let lastQuery = null;
for (let round = 1; round <= maxRounds; round++) {
if (sameQuery(query, lastQuery)) break;
const files = await retrieveLocalFiles(query);
const review = reviewFiles(files, task);
best = mergeWithoutCopies(
best,
review.filter(item => item.score >= 0.7)
);
if (hasEnoughContext(best, review, task)) {
return makeContextReport(best, review, round);
}
lastQuery = query;
query = refineQuery(review, query);
}
return makeContextReport(best, [], maxRounds);
}Never hide missing context. If three rounds are not enough, return the best files and list the open gaps.
Edge Cases
No Results
Check for:
- A different word used by the project
- A different file type
- A different source folder
- A symbol name from an error or stack trace
- A route, test, import, or config that points to the code
If there are still no results, say so. Do not make up file names.
Too Many Results
Narrow by:
- Source folder
- Exact function or type name
- Caller or import link
- File type
- Test name
- Route or config key
Read small parts first. Do not load every full file.
Very Large Files
Read the matching function and nearby code. Then read its imports, callers, or tests as needed.
Generated or Vendor Files
Do not use them as the main source when a real source file exists. Use them only to find that source.
Duplicate Files
Keep one copy of the same content. Note if files are mirrors or generated copies.
Mixed Languages
Search both the task word and the terms found in code. Keep the final report in English.
Secrets or Private Data
Do not read or return secrets, tokens, cookies, private keys, or login files. A matching secret file is not valid task context.
Broken Links
If an import, file path, or named symbol does not exist, report the broken link. Do not guess what it should contain.
Unclear Task
Start with the exact words in the task. If two very different meanings remain after one round, ask one short question before going deeper.
Concrete Example
Task:
Fix the bug where an expired login token is not renewed.Round 1:
Search:
Paths: src/**
Words: token, auth, expired, renew
Found:
src/auth/auth.ts 0.90
src/auth/token-store.ts 0.82
src/users/user.ts 0.25
Learned:
The project uses "refresh" instead of "renew".
auth.ts calls refreshSession().
The caller and tests are still missing.Round 2:
Search:
Words: refreshSession, refresh token, session
Focus: callers and tests
Found:
src/session/session-manager.ts 0.95
test/session-refresh.test.ts 0.88
Stop:
The start, main code, token store, and test are known.Return:
## Context Found
- `src/auth/auth.ts`: Checks token age and starts refresh.
- `src/auth/token-store.ts`: Reads and saves token data.
- `src/session/session-manager.ts`: Defines `refreshSession`.
- `test/session-refresh.test.ts`: Tests expired token refresh.
## Open Gaps
None.Sub-Agent Prompt
Use this prompt when you send the task:
Find the local files needed for this task.
1. Search with task words and likely paths.
2. Score each file from 0 to 1.
3. State why each kept file matters.
4. List any missing caller, type, config, or test.
5. Refine and search again.
6. Stop when the code path is clear, or after three rounds.
7. Return files with a score of 0.7 or more.
8. If context is still missing, say what is missing.
9. Do not read secrets or use the web.Final Output
Return a short report with:
- The files to give the sub-agent
- One reason per file
- The number of rounds used
- Any open gaps
- Any files skipped for safety or because they were made by a build step
Do not return low-score files just to make the list longer.
Related Work
- Affaan Mustafa's Longform Guide, in the sub-agent coordination part
- The
continuous-learningskill - Agent files in
~/.claude/agents/