| name | file-operation-optimization |
| description | Strategies for efficient file reading, caching, and operation planning. Use when reading multiple files, performing code investigation, or when same files are accessed multiple times to reduce file operation overhead by 30-40%. |
File Operation Optimization
Overview
Strategies for efficient file reading, caching, and operation planning. Reduces redundant file reads and improves code investigation efficiency.
Problem: Same files read 4-8 times in single tasks (e.g., GameScene.ts read multiple times), multiple grep searches on same files, no file content caching.
Solution: Cache file contents after first read, plan file operations upfront, batch related operations, use semantic search instead of multiple greps.
Impact: Reduce file operation overhead by 30-40%, improve code investigation efficiency.
File Caching Patterns
Pattern 1: Cache After First Read
Cache file contents in agent context after first read:
const fileCache = new Map<string, string>();
function getFileContent(path: string): string {
if (!fileCache.has(path)) {
const content = read_file(path);
fileCache.set(path, content);
}
return fileCache.get(path)!;
}
const gameScene = getFileContent('src/scenes/GameScene.ts');
const gameSceneAgain = getFileContent('src/scenes/GameScene.ts');
Pattern 2: Invalidate Cache on Modification
Re-read file only when modified:
const fileModifications = new Map<string, number>();
function readFileWithCache(path: string, modificationTime: number): string {
const cached = fileCache.get(path);
const lastModified = fileModifications.get(path) || 0;
if (!cached || modificationTime > lastModified) {
const content = read_file(path);
fileCache.set(path, content);
fileModifications.set(path, modificationTime);
return content;
}
return cached;
}
Pattern 3: Cache Between Operations
Reuse cached content for subsequent operations:
const gameScene = read_file('src/scenes/GameScene.ts');
const lines = gameScene.split('\n');
const functions = lines.filter(line => line.includes('function'));
const classes = lines.filter(line => line.includes('class'));
Pre-Planning Strategies
Pattern 1: Analyze Required Files Upfront
Create file reading plan before starting implementation:
const task = read_file('task.md');
const requiredFiles = analyzeTaskRequirements(task);
const readingPlan = [
'src/scenes/GameScene.ts',
'src/scenes/MainMenu.ts',
'src/types/GameState.ts',
'src/utils/mazeGenerator.ts',
];
const files = await Promise.all(
readingPlan.map(file => read_file(file))
);
Pattern 2: Map File Dependencies
Identify file dependencies before reading:
const dependencies = {
'GameScene.ts': ['GameState.ts', 'mazeGenerator.ts'],
'MainMenu.ts': ['GameState.ts'],
'GameState.ts': [],
'mazeGenerator.ts': [],
};
function readWithDependencies(file: string, read: Set<string> = new Set()) {
if (read.has(file)) return;
const deps = dependencies[file] || [];
for (const dep of deps) {
readWithDependencies(dep, read);
}
read_file(file);
read.add(file);
}
Pattern 3: Plan File Operations
Plan all file operations before execution:
const fileOperations = {
read: [
'src/scenes/GameScene.ts',
'src/scenes/MainMenu.ts',
],
search: [
{ pattern: 'GameState', files: 'src/**/*.ts' },
{ pattern: 'generateMaze', files: 'src/**/*.ts' },
],
edit: [
'src/scenes/GameScene.ts',
],
};
const files = await Promise.all(
fileOperations.read.map(file => read_file(file))
);
const searchResults = await Promise.all(
fileOperations.search.map(({ pattern, files }) =>
codebase_search(`Where is ${pattern} used?`, files)
)
);
Reading Strategy
Pattern 1: Read Full Files Once
Read full files once, analyze in memory:
read_file('GameScene.ts', { offset: 0, limit: 50 });
read_file('GameScene.ts', { offset: 50, limit: 50 });
read_file('GameScene.ts', { offset: 100, limit: 50 });
const fullFile = read_file('GameScene.ts');
const lines = fullFile.split('\n');
const functions = extractFunctions(lines);
const classes = extractClasses(lines);
Pattern 2: Use Semantic Search
Use semantic search instead of multiple grep operations:
grep('GameState', 'src/**/*.ts');
grep('gameState', 'src/**/*.ts');
grep('GameStateType', 'src/**/*.ts');
codebase_search('How is GameState used throughout the codebase?');
Pattern 3: Combine Grep Operations
Combine related grep searches where possible:
grep('TILE_SIZE', 'src/**/*.ts');
grep('TILE_WIDTH', 'src/**/*.ts');
grep('TILE_HEIGHT', 'src/**/*.ts');
codebase_search('Where are tile size constants defined and used?');
grep('TILE_(SIZE|WIDTH|HEIGHT)', 'src/**/*.ts');
Operation Batching
Pattern 1: Group by Purpose
Group file reads by purpose:
const taskFiles = [
'task.md',
'progress.txt',
];
const codeFiles = [
'src/scenes/GameScene.ts',
'src/scenes/MainMenu.ts',
'src/types/GameState.ts',
];
const [taskData, codeData] = await Promise.all([
Promise.all(taskFiles.map(f => read_file(f))),
Promise.all(codeFiles.map(f => read_file(f))),
]);
Pattern 2: Parallel Independent Reads
Read independent files in parallel:
const file1 = read_file('file1.ts');
const file2 = read_file('file2.ts');
const file3 = read_file('file3.ts');
const [file1, file2, file3] = await Promise.all([
read_file('file1.ts'),
read_file('file2.ts'),
read_file('file3.ts'),
]);
Pattern 3: Batch Related Operations
Batch related file operations together:
async function analyzeCodebase() {
const files = await Promise.all([
read_file('src/scenes/GameScene.ts'),
read_file('src/scenes/MainMenu.ts'),
read_file('src/types/GameState.ts'),
]);
const patterns = await Promise.all([
codebase_search('How does scene navigation work?'),
codebase_search('Where is GameState used?'),
]);
return { files, patterns };
}
Best Practices
- Cache after first read: Store file contents in context
- Invalidate on modification: Re-read only when files change
- Plan upfront: Analyze required files before starting
- Read full files: Read once, analyze in memory
- Use semantic search: Instead of multiple greps
- Batch operations: Group related file reads
- Parallel reads: Read independent files simultaneously
- Reuse cached content: Don't re-read same files
Common Pitfalls
Pitfall 1: Re-reading Same Files
Problem: Reading same file multiple times
Solution: Cache file contents
read_file('GameScene.ts');
read_file('GameScene.ts');
read_file('GameScene.ts');
const gameScene = read_file('GameScene.ts');
Pitfall 2: Multiple Grep Searches
Problem: Multiple separate grep operations on same files
Solution: Use semantic search or combine greps
grep('pattern1', 'src/**/*.ts');
grep('pattern2', 'src/**/*.ts');
grep('pattern3', 'src/**/*.ts');
codebase_search('Where are pattern1, pattern2, and pattern3 used?');
Pitfall 3: No Planning
Problem: Reading files incrementally without plan
Solution: Plan file operations upfront
read_file('file1.ts');
read_file('file2.ts');
read_file('file3.ts');
const files = await Promise.all([
read_file('file1.ts'),
read_file('file2.ts'),
read_file('file3.ts'),
]);
Pitfall 4: Partial Reads
Problem: Reading files in chunks instead of full read
Solution: Read full files once
read_file('file.ts', { offset: 0, limit: 100 });
read_file('file.ts', { offset: 100, limit: 100 });
const fullFile = read_file('file.ts');
Integration with Other Skills
timeout-prevention-operation-batching: Uses batching patterns for file operations
refactoring-workflow-optimization: Uses file caching during refactoring
file-edit-batching: Coordinates with file reading strategies
Related Skills
timeout-prevention-operation-batching - Operation batching patterns
refactoring-workflow-optimization - Refactoring with file optimization
file-edit-batching - File editing strategies
Remember
- Cache files: Store contents after first read
- Plan upfront: Analyze required files before starting
- Read full files: Read once, analyze in memory
- Use semantic search: Instead of multiple greps
- Batch operations: Group related file reads
- Parallel reads: Read independent files simultaneously
- Reuse cache: Don't re-read same files