Initial commit
This commit is contained in:
189
skills/local-research/SKILL.md
Normal file
189
skills/local-research/SKILL.md
Normal file
@@ -0,0 +1,189 @@
|
||||
---
|
||||
name: local-research
|
||||
description: "This skill should be used when performing codebase research with markdown documentation persistence. Triggered by phrases like [local research], [quick research], [load local research], [init local research], [read local research ...]."
|
||||
---
|
||||
|
||||
# Local Research
|
||||
|
||||
## Overview
|
||||
|
||||
Perform comprehensive codebase research with persistent markdown documentation stored in `~/workspace/llm/research/`. This skill integrates multiple research tools including fast-repo-context skill, knowledge graph queries, and external resources to create structured research documentation.
|
||||
|
||||
Use absolute file path in research document for easy share across different projects/repos.
|
||||
|
||||
### Automation Script
|
||||
|
||||
The skill includes an automation script at `~/.claude/skills/local-research/scripts/research_ops.py` that handles:
|
||||
- Generating descriptive research names from user queries
|
||||
- Creating research directories and markdown files with timestamps
|
||||
- Listing and locating existing research files by keywords
|
||||
- Providing CLI interface for all research operations
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Need to research and analyze codebase structure and patterns
|
||||
- Want to create persistent research documentation
|
||||
- Need to load previous research findings
|
||||
- User says "local research", "quick research", or "load local research"
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Research Generation Process (when user explicitly requests new research)
|
||||
|
||||
1. **Generate Research Name**: Create descriptive research name based on user input as `<user-query>`, user input may contain typos, improve it.
|
||||
2. **Create Research File**: `python3 ~/.claude/skills/local-research/scripts/research_ops.py create "<user-query>"`
|
||||
3. **Ask Clarifying Questions**: Ask user for more details about research scope
|
||||
4. **Execute Research Workflow**: Use integrated tools to gather information
|
||||
5. **Document Findings**: Write results to research markdown file, use absolute file path when writting, do not use `~` path abbreviation.
|
||||
|
||||
### Loading Research Process (when user mention load or update doc, or provided doc keywords)
|
||||
|
||||
When user requests to "load local research" or similar:
|
||||
1. **List Research Files**: `python3 ~/.claude/skills/local-research/scripts/research_ops.py list`
|
||||
2. **Identify Target**: `python3 ~/.claude/skills/local-research/scripts/research_ops.py locate <keywords>`
|
||||
3. **Load Content**: Read and display the summary of relevant research markdown file
|
||||
|
||||
## Research Tools and Methods
|
||||
|
||||
### Primary Research Tools
|
||||
|
||||
1. **Fast Context Skill** (`fast-repo-context`):
|
||||
- load fast-repo-context skill
|
||||
- Use for comprehensive codebase understanding
|
||||
- Leverages repomix-generated XML for efficient searching
|
||||
|
||||
2. **Knowledge Graph** (`kg`):
|
||||
- Query related keywords and existing research
|
||||
- Use `mcp__kg__query_graph` with semantic search
|
||||
- Set `group_id` to organize research by project/topics
|
||||
|
||||
3. **External Resources**:
|
||||
- **Brightdata**: Use `mcp__brightdata__search_engine` for web research
|
||||
- **GitHub**: Use `mcp__github__search_code` or `mcp__github__search_repositories` for external code reference
|
||||
|
||||
### Research Execution Order
|
||||
|
||||
1. **Initialize Research Environment**:
|
||||
```bash
|
||||
python3 ~/.claude/skills/local-research/scripts/research_ops.py create "<user-query>"
|
||||
```
|
||||
|
||||
2. **Fast Context Analysis**:
|
||||
- Extract code structure, patterns, and key files
|
||||
- Document findings in research file
|
||||
|
||||
3. **Knowledge Graph Integration**:
|
||||
- Query `kg` for related information
|
||||
- Use semantic search with research keywords
|
||||
- Integrate findings into research documentation
|
||||
|
||||
4. **External Research** (if needed):
|
||||
- Use Brightdata for web research on related topics
|
||||
- Use GitHub tools for external examples and best practices
|
||||
- Add external insights to research file
|
||||
|
||||
## Research Documentation Structure
|
||||
|
||||
Each research markdown file should follow this structure:
|
||||
|
||||
```markdown
|
||||
# <Research Name>
|
||||
|
||||
- **Created**: <timestamp>
|
||||
- **Research Query**: <original user input>
|
||||
|
||||
## Executive Summary
|
||||
<brief overview of findings>
|
||||
|
||||
## Codebase Analysis
|
||||
<findings from fast-repo-context>
|
||||
|
||||
## Knowledge Graph Insights
|
||||
<related information from kg queries>
|
||||
|
||||
## External Research
|
||||
<findings from web/github research if applicable>
|
||||
|
||||
## Key Findings
|
||||
<important discoveries and insights>
|
||||
|
||||
## Recommendations
|
||||
<actionable recommendations based on research>
|
||||
|
||||
## Files Referenced
|
||||
<list of key files analyzed>
|
||||
|
||||
## Next Steps
|
||||
<suggested follow-up actions>
|
||||
```
|
||||
|
||||
- Note: file path in the research doc must use absolute path, do not use `~` abbreviation, because this doc will be shared across different project/repos.
|
||||
|
||||
## Loading Research
|
||||
|
||||
When user wants to load existing research:
|
||||
|
||||
1. **Available Research**: List all research files with timestamps
|
||||
2. **Search Matching**: Match user keywords to research names/content
|
||||
3. **Display Findings**: Present the complete research file content
|
||||
|
||||
### Script Commands
|
||||
|
||||
```bash
|
||||
# Create new research file
|
||||
python3 ~/.claude/skills/local-research/scripts/research_ops.py create "<user-query>"
|
||||
|
||||
# List all research files (sorted by timestamp)
|
||||
python3 ~/.claude/skills/local-research/scripts/research_ops.py list
|
||||
|
||||
# Locate research file by keywords
|
||||
python3 ~/.claude/skills/local-research/scripts/research_ops.py locate <keywords...>
|
||||
|
||||
# Read specific research file
|
||||
cat ~/workspace/llm/research/<research-name>-<timestamp>.md
|
||||
```
|
||||
|
||||
## Integration with Other Skills
|
||||
|
||||
### Fast Context Integration
|
||||
- Always invoke `fast-repo-context` skill for codebase analysis
|
||||
- Follow its mandatory checklist: check repomix freshness, search XML, then optionally KG
|
||||
- Document steps completed in research file
|
||||
|
||||
### Knowledge Graph Integration
|
||||
- Use consistent `group_id` for related research projects
|
||||
- Store research summaries in KG for future retrieval
|
||||
- Query KG before starting new research to avoid duplication
|
||||
|
||||
## Research Naming Conventions
|
||||
|
||||
Generate descriptive research names:
|
||||
- Convert user input to kebab-case
|
||||
- Include domain/technology focus
|
||||
- Example inputs to names:
|
||||
- "analyze authentication system" → "authentication-system-analysis"
|
||||
- "react performance issues" → "react-performance-investigation"
|
||||
- "api design patterns" → "api-design-patterns-research"
|
||||
|
||||
## Error Handling
|
||||
|
||||
- If research directory creation fails, check permissions and path
|
||||
- If fast-repo-context claude skill is unavailable, fall back to direct code search
|
||||
- If external resources are unreachable, continue with internal research
|
||||
- Always document any limitations or issues encountered
|
||||
|
||||
# Example
|
||||
|
||||
<example>
|
||||
<user>
|
||||
please load local research on "authentication system analysis" and update the document with any new findings.
|
||||
</user>
|
||||
|
||||
<assistant>
|
||||
```bash
|
||||
python3 ~/.claude/skills/local-research/scripts/research_ops.py locate authentication system analysis
|
||||
```
|
||||
Good, found the research file at `<file-path>`. Now loading the content and summarizing the key points for you.
|
||||
</assistant>
|
||||
</example>
|
||||
236
skills/local-research/scripts/research_ops.py
Executable file
236
skills/local-research/scripts/research_ops.py
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Research Helper Script for Local Research Skill
|
||||
|
||||
This script provides utility functions for managing research files,
|
||||
generating timestamps, and handling research naming conventions.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def generate_research_name(user_input: str) -> str:
|
||||
"""
|
||||
Generate a descriptive research name based on user input.
|
||||
|
||||
Args:
|
||||
user_input: The original user query/description
|
||||
|
||||
Returns:
|
||||
A kebab-case research name
|
||||
"""
|
||||
# Remove common prefixes and normalize
|
||||
input_clean = user_input.lower()
|
||||
prefixes_to_remove = [
|
||||
"analyze ",
|
||||
"investigate ",
|
||||
"research ",
|
||||
"look at ",
|
||||
"examine ",
|
||||
"study ",
|
||||
"explore ",
|
||||
"understand ",
|
||||
]
|
||||
|
||||
for prefix in prefixes_to_remove:
|
||||
if input_clean.startswith(prefix):
|
||||
input_clean = input_clean[len(prefix) :]
|
||||
|
||||
# Map common patterns to descriptive names
|
||||
pattern_map = {
|
||||
"auth": "authentication",
|
||||
"api": "api",
|
||||
"db": "database",
|
||||
"ui": "user-interface",
|
||||
"ux": "user-experience",
|
||||
"perf": "performance",
|
||||
"sec": "security",
|
||||
"test": "testing",
|
||||
"config": "configuration",
|
||||
}
|
||||
|
||||
# Split into words and process each
|
||||
words = input_clean.split()
|
||||
processed_terms = []
|
||||
|
||||
for word in words:
|
||||
# Remove punctuation and apply pattern mapping
|
||||
word_clean = re.sub(r"[^a-z0-9-]", "", word)
|
||||
if word_clean:
|
||||
# Apply pattern mapping
|
||||
if word_clean in pattern_map:
|
||||
word_clean = pattern_map[word_clean]
|
||||
processed_terms.append(word_clean)
|
||||
|
||||
# Remove duplicates while preserving order
|
||||
seen = set()
|
||||
unique_terms = []
|
||||
for term in processed_terms:
|
||||
if term not in seen:
|
||||
seen.add(term)
|
||||
unique_terms.append(term)
|
||||
|
||||
# Join with hyphens and limit length
|
||||
research_name = "-".join(unique_terms)
|
||||
if len(research_name) > 80:
|
||||
research_name = "-".join(unique_terms[:5])
|
||||
|
||||
return research_name or "research"
|
||||
|
||||
|
||||
def create_research_file(research_name: str, user_query: str) -> str:
|
||||
"""
|
||||
Create a new research file with timestamp and return the path.
|
||||
|
||||
Args:
|
||||
research_name: The generated research name
|
||||
user_query: The original user query
|
||||
|
||||
Returns:
|
||||
Path to the created research file
|
||||
"""
|
||||
# Create research directory
|
||||
research_dir = Path.home() / "workspace" / "llm" / "research"
|
||||
research_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Generate timestamp
|
||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
|
||||
# Create file path
|
||||
filename = f"{research_name}-{timestamp}.md"
|
||||
filepath = research_dir / filename
|
||||
|
||||
# Create file with initial header
|
||||
with open(filepath, "w") as f:
|
||||
f.write(f"# {research_name.replace('-', ' ').title()}\n")
|
||||
f.write(f"- **Created**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
f.write(f"- **Research Query**: {user_query}\n\n")
|
||||
f.write("## Executive Summary\n\n")
|
||||
f.write("## Codebase Analysis\n\n")
|
||||
f.write("## Knowledge Graph Insights\n\n")
|
||||
f.write("## External Research\n\n")
|
||||
f.write("## Key Findings\n\n")
|
||||
f.write("## Recommendations\n\n")
|
||||
f.write("## Files Referenced\n\n")
|
||||
f.write("## Next Steps\n\n")
|
||||
|
||||
return str(filepath)
|
||||
|
||||
|
||||
def list_research_files() -> list:
|
||||
"""
|
||||
List all research files sorted by timestamp (newest first).
|
||||
|
||||
Returns:
|
||||
List of file paths sorted by modification time
|
||||
"""
|
||||
research_dir = Path.home() / "workspace" / "llm" / "research"
|
||||
if not research_dir.exists():
|
||||
return []
|
||||
|
||||
files = []
|
||||
for file_path in research_dir.glob("*.md"):
|
||||
files.append((file_path.stat().st_mtime, file_path))
|
||||
|
||||
# Sort by modification time (newest first)
|
||||
files.sort(key=lambda x: x[0], reverse=True)
|
||||
return [file_path for _, file_path in files]
|
||||
|
||||
|
||||
def locate_research_file(keywords: list) -> str:
|
||||
"""
|
||||
Find research file matching keywords.
|
||||
|
||||
Args:
|
||||
keywords: List of keywords to search for
|
||||
|
||||
Returns:
|
||||
Path to the best matching file or None if not found
|
||||
"""
|
||||
files = list_research_files()
|
||||
if not files:
|
||||
return None
|
||||
|
||||
if not keywords:
|
||||
# Return most recent file
|
||||
return str(files[0]) if files else None
|
||||
|
||||
# Simple keyword matching in filename and content
|
||||
best_match = None
|
||||
best_score = 0
|
||||
|
||||
for file_path in files:
|
||||
score = 0
|
||||
filename = file_path.name.lower()
|
||||
|
||||
# Check filename match
|
||||
for keyword in keywords:
|
||||
keyword_lower = keyword.lower()
|
||||
if keyword_lower in filename:
|
||||
score += 3
|
||||
|
||||
# Check content match
|
||||
try:
|
||||
with open(file_path, "r") as f:
|
||||
content = f.read().lower()
|
||||
for keyword in keywords:
|
||||
keyword_lower = keyword.lower()
|
||||
if keyword_lower in content:
|
||||
score += 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
best_match = file_path
|
||||
|
||||
return str(best_match) if best_match else None
|
||||
|
||||
|
||||
def main():
|
||||
"""CLI interface for the research helper."""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python research_helper.py <command> [args...]")
|
||||
print("Commands:")
|
||||
print(" create <user_query> - Create new research file")
|
||||
print(" list - List all research files")
|
||||
print(" locate <keywords...> - Locate research file by keywords")
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
if command == "create":
|
||||
if len(sys.argv) < 3:
|
||||
print("Error: create command requires user query")
|
||||
sys.exit(1)
|
||||
|
||||
user_query = " ".join(sys.argv[2:])
|
||||
research_name = generate_research_name(user_query)
|
||||
filepath = create_research_file(research_name, user_query)
|
||||
print(filepath)
|
||||
|
||||
elif command == "list":
|
||||
files = list_research_files()
|
||||
for file_path in files:
|
||||
print(f"{file_path}")
|
||||
|
||||
elif command == "locate":
|
||||
keywords = sys.argv[2:] if len(sys.argv) > 2 else []
|
||||
filepath = locate_research_file(keywords)
|
||||
if filepath:
|
||||
print(filepath)
|
||||
else:
|
||||
print("No matching research file found")
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
print(f"Error: Unknown command '{command}'")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user