diff --git a/packages/cli/src/ui/utils/clipboardUtils.ts b/packages/cli/src/ui/utils/clipboardUtils.ts index c0aa1a262..ab1465f73 100644 --- a/packages/cli/src/ui/utils/clipboardUtils.ts +++ b/packages/cli/src/ui/utils/clipboardUtils.ts @@ -394,8 +394,8 @@ async function saveLinuxClipboardImage( } /** - * Cleans up old temporary clipboard image files - * Removes files older than 1 hour + * Cleans up old temporary clipboard image files using LRU strategy + * Keeps maximum 100 images, when exceeding removes 50 oldest files to reduce cleanup frequency * @param targetDir The target directory where temp files are stored */ export async function cleanupOldClipboardImages( @@ -405,7 +405,11 @@ export async function cleanupOldClipboardImages( const baseDir = targetDir || process.cwd(); const tempDir = path.join(baseDir, 'clipboard'); const files = await fs.readdir(tempDir); - const oneHourAgo = Date.now() - 60 * 60 * 1000; + const MAX_IMAGES = 100; + const CLEANUP_COUNT = 50; + + // Filter clipboard image files and get their stats + const imageFiles: Array<{ name: string; path: string; atime: number }> = []; for (const file of files) { if ( @@ -421,9 +425,27 @@ export async function cleanupOldClipboardImages( ) { const filePath = path.join(tempDir, file); const stats = await fs.stat(filePath); - if (stats.atimeMs < oneHourAgo) { - await fs.unlink(filePath); - } + imageFiles.push({ + name: file, + path: filePath, + atime: stats.atimeMs, + }); + } + } + + // If exceeds limit, remove CLEANUP_COUNT oldest files to reduce cleanup frequency + if (imageFiles.length > MAX_IMAGES) { + // Sort by access time (oldest first) + imageFiles.sort((a, b) => a.atime - b.atime); + + // Remove CLEANUP_COUNT oldest files (or all excess files if less than CLEANUP_COUNT) + const removeCount = Math.min( + CLEANUP_COUNT, + imageFiles.length - MAX_IMAGES + CLEANUP_COUNT, + ); + const filesToRemove = imageFiles.slice(0, removeCount); + for (const file of filesToRemove) { + await fs.unlink(file.path); } } } catch {