find_tool_patterns
Analyze tool usage patterns, workflows, and successful practices from Claude Code conversation history to identify effective approaches.
Instructions
Analyze tool usage patterns, workflows, and successful practices
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tool_name | No | Optional specific tool name to analyze | |
| pattern_type | No | Type of patterns: tools, workflows, or solutions | tools |
| limit | No | Maximum number of patterns (default: 12) |
Implementation Reference
- src/index.ts:375-391 (handler)MCP CallToolRequest handler for find_tool_patterns: delegates to UniversalHistorySearchEngine.getToolPatterns, formats with BeautifulFormatter
case 'find_tool_patterns': { const universalResult = await this.universalEngine.getToolPatterns( args?.tool_name as string, (args?.limit as number) || 12 ); const patternType = (args?.pattern_type as string) || 'tools'; const formattedResult = this.formatter.formatToolPatterns( universalResult.results as any, args?.tool_name as string, patternType ); return { content: [{ type: 'text', text: formattedResult }], }; } - src/index.ts:207-229 (schema)Input schema definition for find_tool_patterns tool in ListTools response
name: 'find_tool_patterns', description: 'Analyze tool usage patterns, workflows, and successful practices', inputSchema: { type: 'object', properties: { tool_name: { type: 'string', description: 'Optional specific tool name to analyze', }, pattern_type: { type: 'string', description: 'Type of patterns: tools, workflows, or solutions', enum: ['tools', 'workflows', 'solutions'], default: 'tools', }, limit: { type: 'number', description: 'Maximum number of patterns (default: 12)', default: 12, }, }, }, }, - src/search.ts:1061-1293 (helper)Core implementation in HistorySearchEngine.getToolPatterns: scans conversation history, identifies tool usage patterns and workflows, constructs ToolPattern results
async getToolPatterns(toolName?: string, limit: number = 20): Promise<ToolPattern[]> { const toolMap = new Map<string, CompactMessage[]>(); const workflowMap = new Map<string, CompactMessage[]>(); try { const projectDirs = await findProjectDirectories(); const limitedDirs = projectDirs.slice(0, 15); // Focus on core Claude Code tools that GLOBAL would recognize const coreTools = new Set([ 'Edit', 'Read', 'Bash', 'Grep', 'Glob', 'Write', 'Task', 'MultiEdit', 'Notebook', ]); // PARALLEL PROCESSING: Process all projects concurrently const projectResults = await Promise.allSettled( limitedDirs.map(async (projectDir) => { const jsonlFiles = await findJsonlFiles(projectDir); const limitedFiles = jsonlFiles.slice(0, 8); const projectToolMap = new Map<string, CompactMessage[]>(); const projectWorkflowMap = new Map<string, CompactMessage[]>(); // PARALLEL: Process files within project simultaneously const fileResults = await Promise.allSettled( limitedFiles.map(async (file) => { const messages = await this.parser.parseJsonlFile(projectDir, file); // Extract individual tool usage patterns for (const msg of messages) { if (msg.context?.toolsUsed?.length) { for (const tool of msg.context.toolsUsed) { // If toolName specified, only track that tool // Otherwise, track all core tools const shouldTrack = toolName ? tool === toolName : coreTools.has(tool); if (shouldTrack) { if (!projectToolMap.has(tool)) { projectToolMap.set(tool, []); } projectToolMap.get(tool)!.push(msg); } } } } // Extract workflow patterns (tool sequences) for (let i = 0; i < messages.length - 1; i++) { const current = messages[i]; const next = messages[i + 1]; if (current.context?.toolsUsed?.length && next.context?.toolsUsed?.length) { // Create focused workflow patterns for (const currentTool of current.context.toolsUsed) { for (const nextTool of next.context.toolsUsed) { // If toolName specified, workflow must involve that tool // Otherwise, workflows between core tools const shouldTrack = toolName ? currentTool === toolName || nextTool === toolName : coreTools.has(currentTool) && coreTools.has(nextTool); if (shouldTrack) { const workflowKey = `${currentTool} → ${nextTool}`; if (!projectWorkflowMap.has(workflowKey)) { projectWorkflowMap.set(workflowKey, []); } projectWorkflowMap.get(workflowKey)!.push(current, next); } } } } } // Also create longer sequences for complex workflows for (let i = 0; i < messages.length - 2; i++) { const first = messages[i]; const second = messages[i + 1]; const third = messages[i + 2]; if ( first.context?.toolsUsed?.length && second.context?.toolsUsed?.length && third.context?.toolsUsed?.length ) { for (const firstTool of first.context.toolsUsed) { for (const secondTool of second.context.toolsUsed) { for (const thirdTool of third.context.toolsUsed) { // If toolName specified, 3-step workflow must involve that tool const shouldTrack = toolName ? firstTool === toolName || secondTool === toolName || thirdTool === toolName : coreTools.has(firstTool) && coreTools.has(secondTool) && coreTools.has(thirdTool); if (shouldTrack) { const workflowKey = `${firstTool} → ${secondTool} → ${thirdTool}`; if (!projectWorkflowMap.has(workflowKey)) { projectWorkflowMap.set(workflowKey, []); } projectWorkflowMap.get(workflowKey)!.push(first, second, third); } } } } } } }) ); return { tools: projectToolMap, workflows: projectWorkflowMap }; }) ); // Aggregate results from parallel processing for (const result of projectResults) { if (result.status === 'fulfilled') { // Aggregate individual tools for (const [tool, messages] of result.value.tools.entries()) { if (!toolMap.has(tool)) { toolMap.set(tool, []); } toolMap.get(tool)!.push(...messages); } // Aggregate workflows for (const [workflow, messages] of result.value.workflows.entries()) { if (!workflowMap.has(workflow)) { workflowMap.set(workflow, []); } workflowMap.get(workflow)!.push(...messages); } } } const patterns: ToolPattern[] = []; // ENHANCED: Create diverse patterns like GLOBAL showing related tools with workflows const toolFrequency = new Map<string, number>(); // First pass: Calculate tool frequencies for prioritization for (const [tool, messages] of toolMap.entries()) { toolFrequency.set(tool, messages.length); } // Add diverse individual tool patterns (different tools, not just highest frequency) const usedTools = new Set<string>(); for (const [tool, messages] of Array.from(toolMap.entries()).sort( (a, b) => b[1].length - a[1].length )) { if (messages.length >= 1 && !usedTools.has(tool) && patterns.length < limit) { const uniqueMessages = SearchHelpers.deduplicateByContent(messages); // Extract actual patterns and practices instead of generic text const actualPatterns = this.extractActualToolPatterns(tool, uniqueMessages); const actualPractices = this.extractActualBestPractices(tool, uniqueMessages); patterns.push({ toolName: tool, successfulUsages: uniqueMessages.slice(0, 10), commonPatterns: actualPatterns.length > 0 ? actualPatterns : [`${tool} usage pattern`], bestPractices: actualPractices.length > 0 ? actualPractices : [`${tool} used ${uniqueMessages.length}x successfully`], }); usedTools.add(tool); } } // Add related workflow patterns for each tool (like GLOBAL's approach) for (const tool of usedTools) { // Find workflows involving this tool for (const [workflow, messages] of workflowMap.entries()) { if (workflow.includes(tool) && workflow.includes('→') && messages.length >= 1) { const uniqueMessages = SearchHelpers.deduplicateByContent(messages); // Only add if not already added and we have space if (!patterns.some((p) => p.toolName === workflow) && patterns.length < limit) { patterns.push({ toolName: workflow, successfulUsages: uniqueMessages.slice(0, 10), commonPatterns: [workflow], bestPractices: [`${workflow} workflow (${uniqueMessages.length}x successful)`], }); } } } } // If we still have space, add any remaining high-frequency workflows for (const [workflow, messages] of Array.from(workflowMap.entries()).sort( (a, b) => b[1].length - a[1].length )) { if (workflow.includes('→') && messages.length >= 1 && patterns.length < limit) { if (!patterns.some((p) => p.toolName === workflow)) { const uniqueMessages = SearchHelpers.deduplicateByContent(messages); patterns.push({ toolName: workflow, successfulUsages: uniqueMessages.slice(0, 10), commonPatterns: [workflow], bestPractices: [`${workflow} workflow (${uniqueMessages.length}x successful)`], }); } } } // Sort to prioritize individual tools, then their related workflows return patterns .sort((a, b) => { const aIsWorkflow = a.toolName.includes('→'); const bIsWorkflow = b.toolName.includes('→'); // Individual tools first, then workflows, then by usage frequency if (aIsWorkflow !== bIsWorkflow) { return aIsWorkflow ? 1 : -1; } return b.successfulUsages.length - a.successfulUsages.length; }) .slice(0, limit); } catch (error) { console.error('Tool pattern search error:', error); return []; } } - src/universal-engine.ts:1426-1446 (helper)UniversalHistorySearchEngine.getToolPatterns delegates to HistorySearchEngine.getToolPatterns
async getToolPatterns(toolName?: string, limit?: number): Promise<UniversalSearchResult> { await this.initialize(); const claudeCodePatterns = await this.claudeCodeEngine.getToolPatterns(toolName, limit || 12); if (!this.claudeDesktopAvailable) { return { source: 'claude-code', results: claudeCodePatterns as any, enhanced: false, }; } // For tool patterns, Desktop doesn't have tool usage data, so we focus on Code // But we mark as enhanced if Desktop is available for future Desktop tool analysis return { source: 'claude-code', results: claudeCodePatterns as any, enhanced: this.claudeDesktopAvailable, }; } - src/formatter.ts:643-671 (helper)BeautifulFormatter.formatToolPatterns: formats and ranks tool pattern results for output
formatToolPatterns( patterns: ToolPattern[], toolName?: string, _patternType: string = 'tools' ): string { const filter = toolName ? `"${toolName}"` : 'all'; const header = `${robots.toolPatterns} ${filter} | ${patterns.length} patterns`; if (patterns.length === 0) { return `${header}\n\n{"patterns":[]}`; } const rankedPatterns = this.rankToolPatternsByValue(patterns); const topPatterns = rankedPatterns.slice(0, 8); const structured = { tool: toolName || 'all', patterns: topPatterns.map((p) => ({ name: p.toolName, uses: p.successfulUsages.length, workflow: p.commonPatterns[0] || null, practice: p.bestPractices[0] || null, example: p.successfulUsages[0]?.content || null, ctx: p.successfulUsages[0]?.context || null, })), }; return `${header}\n\n${JSON.stringify(structured, null, 2)}`; }