list_recent_sessions
Browse recent Claude conversation sessions with smart activity detection and summaries to track work history and find past solutions.
Instructions
Browse recent sessions with smart activity detection and summaries
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of sessions (default: 10) | |
| project | No | Optional project name to filter sessions | |
| include_summary | No | Include intelligent session summaries (default: true) |
Implementation Reference
- src/index.ts:340-353 (handler)MCP tool handler for 'list_recent_sessions': extracts parameters, calls UniversalHistorySearchEngine.getRecentSessions, formats with BeautifulFormatter.formatRecentSessions, and returns formatted text content.case 'list_recent_sessions': { const limit = (args?.limit as number) || 10; const project = args?.project as string; const universalResult = await this.universalEngine.getRecentSessions(limit, project); const formattedResult = this.formatter.formatRecentSessions( universalResult.results as any, project ); return { content: [{ type: 'text', text: formattedResult }], }; }
- src/index.ts:159-180 (schema)Input schema and registration for 'list_recent_sessions' tool in ListToolsRequest handler.name: 'list_recent_sessions', description: 'Browse recent sessions with smart activity detection and summaries', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number of sessions (default: 10)', default: 10, }, project: { type: 'string', description: 'Optional project name to filter sessions', }, include_summary: { type: 'boolean', description: 'Include intelligent session summaries (default: true)', default: true, }, }, }, },
- src/search.ts:1295-1377 (handler)Core implementation of getRecentSessions in HistorySearchEngine: scans recent .jsonl files across projects in parallel, extracts session metadata (duration, tools, accomplishments, etc.), sorts by recency, limits to requested number.async getRecentSessions(limit: number = 10): Promise<any[]> { try { // OPTIMIZED: Fast session discovery with parallel processing and early termination const projectDirs = await findProjectDirectories(); // PERFORMANCE: Limit projects and use parallel processing like GLOBAL const limitedDirs = projectDirs.slice(0, 10); // Limit projects for speed // PARALLEL PROCESSING: Process projects concurrently const projectResults = await Promise.allSettled( limitedDirs.map(async (projectDir) => { const jsonlFiles = await findJsonlFiles(projectDir); const decodedPath = projectDir.replace(/-/g, '/'); const projectName = decodedPath.split('/').pop() || 'unknown'; // PERFORMANCE: Limit files per project and process in parallel const limitedFiles = jsonlFiles.slice(0, 5); // Limit files for speed const sessionResults = await Promise.allSettled( limitedFiles.map(async (file) => { const messages = await this.parser.parseJsonlFile(projectDir, file); if (messages.length === 0) return null; // Fast extraction of session data const toolsUsed = [...new Set(messages.flatMap((m) => m.context?.toolsUsed || []))]; const startTime = messages[0]?.timestamp; const endTime = messages[messages.length - 1]?.timestamp; // Quick duration calculation let realDuration = 0; if (startTime && endTime) { realDuration = Math.round( (new Date(endTime).getTime() - new Date(startTime).getTime()) / 60000 ); } // Extract accomplishments - what was actually done const accomplishments = this.extractSessionAccomplishments(messages); return { session_id: file.replace('.jsonl', ''), project_path: decodedPath, project_dir: projectDir, project_name: projectName, message_count: messages.length, duration_minutes: realDuration, end_time: endTime, start_time: startTime, tools_used: toolsUsed.slice(0, 5), // Limit tools for speed assistant_count: messages.filter((m) => m.type === 'assistant').length, error_count: messages.filter((m) => m.context?.errorPatterns?.length).length, session_quality: this.calculateSessionQuality(messages, toolsUsed, []), accomplishments: accomplishments.slice(0, 3), // Top 3 accomplishments }; }) ); // Collect successful session results return sessionResults .filter((result) => result.status === 'fulfilled' && result.value) .map((result) => (result as PromiseFulfilledResult<any>).value); }) ); // Flatten and collect all sessions const realSessions: any[] = []; for (const result of projectResults) { if (result.status === 'fulfilled') { realSessions.push(...result.value); } } // Sort by real end time return realSessions .filter((s) => s.end_time) // Only sessions with real timestamps .sort((a, b) => new Date(b.end_time).getTime() - new Date(a.end_time).getTime()) .slice(0, limit); } catch (error) { console.error('Recent sessions error:', error); return []; } }
- src/formatter.ts:739-763 (helper)Formatter for recent sessions results: ranks by productivity, structures JSON output with session details (id, ts, duration, messages, project, tools, accomplishments), adds robot emoji header.formatRecentSessions(sessions: any[], project?: string): string { const filter = project ? `"${project}"` : 'all'; const header = `${robots.sessions} ${filter} | ${sessions.length} sessions`; if (sessions.length === 0) { return `${header}\n\n{"sessions":[]}`; } const rankedSessions = this.rankSessionsByProductivity(sessions); const topSessions = rankedSessions.slice(0, 10); const structured = { sessions: topSessions.map((s) => ({ id: s.session_id?.substring(0, 8) || null, ts: this.formatTimestamp(s.end_time || s.start_time), duration: s.duration_minutes || 0, messages: s.message_count || 0, project: s.project_path?.split('/').pop() || null, tools: s.tools_used || null, accomplishments: s.accomplishments || null, })), }; return `${header}\n\n${JSON.stringify(structured, null, 2)}`; }
- src/universal-engine.ts:1403-1424 (helper)UniversalHistorySearchEngine.getRecentSessions: delegates to HistorySearchEngine.getRecentSessions, adds enhanced flag if Claude Desktop available (though no Desktop sessions currently).// Universal methods for all tools async getRecentSessions(limit?: number, project?: string): Promise<UniversalSearchResult> { await this.initialize(); const claudeCodeSessions = await this.claudeCodeEngine.getRecentSessions(limit || 10); if (!this.claudeDesktopAvailable) { return { source: 'claude-code', results: claudeCodeSessions as any, enhanced: false, }; } // For sessions, Desktop doesn't have traditional sessions, so we focus on Code // But we mark as enhanced if Desktop is available for future Desktop session support return { source: 'claude-code', results: claudeCodeSessions as any, enhanced: this.claudeDesktopAvailable, }; }