AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Report Generator

skill-curiouslearner-devkit-report-generator · by CuriousLearner

Generate professional markdown and HTML reports from data with charts, tables, and analysis.

No reviews yet
0 installs
27 views
0.0% view→install

Install

$ agentstack add skill-curiouslearner-devkit-report-generator

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-curiouslearner-devkit-report-generator)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
11mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Report Generator? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Report Generator Skill

Generate professional markdown and HTML reports from data with charts, tables, and analysis.

Instructions

You are a report generation expert. When invoked:

  1. Analyze Data:
  • Understand data structure and content
  • Identify key metrics and insights
  • Calculate statistics and trends
  • Detect patterns and anomalies
  • Generate executive summaries
  1. Create Report Structure:
  • Design clear, logical sections
  • Create table of contents
  • Add executive summary
  • Include detailed analysis
  • Provide recommendations
  1. Generate Visualizations:
  • Create tables for structured data
  • Generate charts (bar, line, pie, scatter)
  • Add badges and indicators
  • Include code blocks and examples
  • Format numbers and percentages
  1. Format Output:
  • Generate markdown reports
  • Create HTML reports with styling
  • Export to PDF
  • Add branding and customization
  • Ensure responsive design

Usage Examples

@report-generator data.csv
@report-generator --format html
@report-generator --template executive-summary
@report-generator --charts --pdf
@report-generator --compare baseline.json current.json

Report Types

Executive Summary Report

def generate_executive_summary(data, title="Executive Summary"):
    """
    Generate high-level executive summary report
    """
    from datetime import datetime

    report = f"""# {title}
**Generated:** {datetime.now().strftime('%B %d, %Y at %I:%M %p')}

---

## Key Highlights

"""

    # Calculate key metrics
    metrics = calculate_key_metrics(data)

    for metric in metrics:
        icon = "✅" if metric['status'] == 'good' else "⚠️" if metric['status'] == 'warning' else "❌"
        report += f"{icon} **{metric['name']}**: {metric['value']}\n"

    report += f"""

---

## Performance Overview

| Metric | Current | Previous | Change |
|--------|---------|----------|--------|
"""

    for metric in metrics:
        if 'previous' in metric:
            change = calculate_change(metric['current'], metric['previous'])
            arrow = "↑" if change > 0 else "↓" if change  0 else "red" if change  0:
        report += "| Column | Missing Count | Missing % |\n"
        report += "|--------|---------------|----------|\n"

        for col in missing[missing > 0].index:
            count = missing[col]
            pct = (count / len(df)) * 100
            report += f"| {col} | {count:,} | {pct:.1f}% |\n"
    else:
        report += "✅ No missing values detected.\n"

    report += "\n### Data Type Issues\n\n"

    # Check for potential type issues
    type_issues = []

    for col in df.select_dtypes(include=['object']):
        # Check if column should be numeric
        try:
            pd.to_numeric(df[col], errors='raise')
            type_issues.append(f"- `{col}` appears to be numeric but stored as string")
        except:
            pass

        # Check if column should be datetime
        try:
            pd.to_datetime(df[col], errors='raise')
            if df[col].str.contains(r'\d{4}-\d{2}-\d{2}').any():
                type_issues.append(f"- `{col}` appears to be datetime but stored as string")
        except:
            pass

    if type_issues:
        report += "\n".join(type_issues) + "\n"
    else:
        report += "✅ No data type issues detected.\n"

    report += """

---

## Statistical Summary

### Numeric Columns

"""

    # Add statistics for numeric columns
    numeric_cols = df.select_dtypes(include=[np.number]).columns

    if len(numeric_cols) > 0:
        stats = df[numeric_cols].describe()
        report += stats.to_markdown() + "\n"

        # Add additional statistics
        report += "\n### Additional Statistics\n\n"
        report += "| Column | Median | Mode | Std Dev | Variance |\n"
        report += "|--------|--------|------|---------|----------|\n"

        for col in numeric_cols:
            median = df[col].median()
            mode = df[col].mode().iloc[0] if not df[col].mode().empty else "N/A"
            std = df[col].std()
            var = df[col].var()

            report += f"| {col} | {median:.2f} | {mode} | {std:.2f} | {var:.2f} |\n"

    report += """

### Categorical Columns

"""

    categorical_cols = df.select_dtypes(include=['object']).columns

    if len(categorical_cols) > 0:
        for col in categorical_cols[:5]:  # Limit to first 5
            report += f"\n#### {col}\n\n"

            value_counts = df[col].value_counts().head(10)

            report += "| Value | Count | Percentage |\n"
            report += "|-------|-------|------------|\n"

            for value, count in value_counts.items():
                pct = (count / len(df)) * 100
                report += f"| {value} | {count:,} | {pct:.1f}% |\n"

    report += """

---

## Distributions

"""

    # Analyze distributions of numeric columns
    for col in numeric_cols[:5]:  # Limit to first 5
        report += f"\n### {col} Distribution\n\n"

        q1 = df[col].quantile(0.25)
        q2 = df[col].quantile(0.50)
        q3 = df[col].quantile(0.75)
        iqr = q3 - q1

        # Detect outliers
        lower_bound = q1 - 1.5 * iqr
        upper_bound = q3 + 1.5 * iqr
        outliers = df[(df[col]  upper_bound)]

        report += f"""
**Quartiles:**
- Q1 (25%): {q1:.2f}
- Q2 (50%, Median): {q2:.2f}
- Q3 (75%): {q3:.2f}
- IQR: {iqr:.2f}

**Outliers:** {len(outliers)} ({len(outliers)/len(df)*100:.1f}%)
- Lower bound: {lower_bound:.2f}
- Upper bound: {upper_bound:.2f}

"""

    report += """

---

## Correlations

"""

    if len(numeric_cols) > 1:
        corr_matrix = df[numeric_cols].corr()

        report += "\n### Correlation Matrix\n\n"
        report += corr_matrix.to_markdown() + "\n"

        # Find strong correlations
        report += "\n### Strong Correlations (|r| > 0.7)\n\n"

        strong_corr = []
        for i in range(len(corr_matrix.columns)):
            for j in range(i+1, len(corr_matrix.columns)):
                corr_val = corr_matrix.iloc[i, j]
                if abs(corr_val) > 0.7:
                    col1 = corr_matrix.columns[i]
                    col2 = corr_matrix.columns[j]
                    strong_corr.append((col1, col2, corr_val))

        if strong_corr:
            for col1, col2, corr_val in strong_corr:
                direction = "positive" if corr_val > 0 else "negative"
                report += f"- **{col1}** ↔ **{col2}**: {corr_val:.3f} ({direction})\n"
        else:
            report += "No strong correlations found.\n"

    report += """

---

## Insights

"""

    # Generate insights
    insights = generate_insights(df)

    for insight in insights:
        report += f"### {insight['title']}\n\n"
        report += f"{insight['description']}\n\n"

        if 'details' in insight:
            for detail in insight['details']:
                report += f"- {detail}\n"

        report += "\n"

    return report

def generate_insights(df):
    """Generate data insights"""
    insights = []

    # Insight: Completeness
    missing_pct = (df.isnull().sum().sum() / (len(df) * len(df.columns))) * 100

    if missing_pct  0:
        insights.append({
            "title": f"⚠️ Duplicate Records Found",
            "description": f"Found {dup_count:,} duplicate rows ({dup_count/len(df)*100:.1f}% of dataset)",
            "details": [
                "Consider removing duplicates for accurate analysis",
                "Review business logic for duplicate handling"
            ]
        })

    return insights

Performance Report

def generate_performance_report(metrics, baseline=None):
    """
    Generate performance comparison report
    """

    report = f"""# Performance Report
**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

---

## Summary

"""

    if baseline:
        report += "### Comparison with Baseline\n\n"

        report += "| Metric | Current | Baseline | Change | Status |\n"
        report += "|--------|---------|----------|--------|--------|\n"

        for metric_name, current_value in metrics.items():
            if metric_name in baseline:
                baseline_value = baseline[metric_name]
                change = ((current_value - baseline_value) / baseline_value) * 100

                if abs(change)  0:
                    status = "🟢 Improved" if is_improvement(metric_name, change) else "🔴 Degraded"
                else:
                    status = "🔴 Degraded" if is_improvement(metric_name, change) else "🟢 Improved"

                report += f"| {metric_name} | {current_value:.2f} | {baseline_value:.2f} | {change:+.1f}% | {status} |\n"

    else:
        report += "### Current Metrics\n\n"

        report += "| Metric | Value | Status |\n"
        report += "|--------|-------|--------|\n"

        for metric_name, value in metrics.items():
            threshold = get_threshold(metric_name)
            status = evaluate_metric(value, threshold)

            report += f"| {metric_name} | {value:.2f} | {status} |\n"

    report += """

---

## Detailed Analysis

"""

    for metric_name, value in metrics.items():
        report += f"### {metric_name}\n\n"

        if baseline and metric_name in baseline:
            baseline_value = baseline[metric_name]
            change = ((value - baseline_value) / baseline_value) * 100

            report += f"- **Current:** {value:.2f}\n"
            report += f"- **Baseline:** {baseline_value:.2f}\n"
            report += f"- **Change:** {change:+.1f}%\n\n"

            if abs(change) > 10:
                report += f"⚠️ Significant change detected. "
                report += "Review recent changes that may have impacted this metric.\n\n"

        else:
            report += f"- **Value:** {value:.2f}\n\n"

    return report

def is_improvement(metric_name, change):
    """Determine if change is improvement based on metric type"""
    # Lower is better for these metrics
    lower_is_better = ['response_time', 'error_rate', 'latency', 'load_time']

    for pattern in lower_is_better:
        if pattern in metric_name.lower():
            return change  0

HTML Report Generation

def generate_html_report(data, title="Report", template="default"):
    """
    Generate styled HTML report
    """

    # CSS styles
    css = """
    
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }

        .report-container {
            background: white;
            padding: 40px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        h1 {
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 10px;
        }

        h2 {
            color: #34495e;
            margin-top: 30px;
            border-left: 4px solid #3498db;
            padding-left: 10px;
        }

        h3 {
            color: #7f8c8d;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }

        th {
            background: #3498db;
            color: white;
            padding: 12px;
            text-align: left;
            font-weight: 600;
        }

        td {
            padding: 10px 12px;
            border-bottom: 1px solid #ecf0f1;
        }

        tr:hover {
            background: #f8f9fa;
        }

        .metric-card {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 8px;
            margin: 10px 0;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }

        .metric-value {
            font-size: 2em;
            font-weight: bold;
        }

        .metric-label {
            font-size: 0.9em;
            opacity: 0.9;
        }

        .badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 12px;
            font-size: 0.85em;
            font-weight: 600;
        }

        .badge-success {
            background: #2ecc71;
            color: white;
        }

        .badge-warning {
            background: #f39c12;
            color: white;
        }

        .badge-danger {
            background: #e74c3c;
            color: white;
        }

        .chart-container {
            margin: 30px 0;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 8px;
        }

        code {
            background: #f4f4f4;
            padding: 2px 6px;
            border-radius: 3px;
            font-family: 'Courier New', monospace;
        }

        pre {
            background: #2c3e50;
            color: #ecf0f1;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
        }

        .timestamp {
            color: #7f8c8d;
            font-size: 0.9em;
        }
    
    """

    # Generate HTML content
    html = f"""
    
    
    
        
        
        {title}
        {css}
        
    
    
        
            {title}
            Generated: {datetime.now().strftime('%B %d, %Y at %I:%M %p')}

            {generate_html_content(data)}
        
    
    
    """

    return html

def generate_html_content(data):
    """Generate HTML content from data"""

    html = ""

    # Key metrics section
    if 'metrics' in data:
        html += "Key Metrics"
        html += ''

        for metric in data['metrics']:
            html += f"""
            
                {metric['name']}
                {metric['value']}
            
            """

        html += ""

    # Table data
    if 'table' in data:
        html += "Data Table"
        html += generate_html_table(data['table'])

    # Charts
    if 'charts' in data:
        for chart in data['charts']:
            html += f'{chart["title"]}'
            html += ''
            html += generate_chart_html(chart)
            html += ''

    return html

def generate_html_table(table_data):
    """Generate HTML table from data"""

    html = ""

    # Header
    if 'headers' in table_data:
        html += ""
        for header in table_data['headers']:
            html += f"{header}"
        html += ""

    # Rows
    html += ""
    for row in table_data.get('rows', []):
        html += ""
        for cell in row:
            html += f"{cell}"
        html += ""
    html += ""

    html += ""
    return html

def generate_chart_html(chart_data):
    """Generate Chart.js chart"""

    chart_id = f"chart_{abs(hash(chart_data['title']))}"

    html = f''
    html += f"""
    
        var ctx = document.getElementById('{chart_id}').getContext('2d');
        var chart = new Chart(ctx, {{
            type: '{chart_data.get('type', 'bar')}',
            data: {{
                labels: {chart_data['labels']},
                datasets: [{{
                    label: '{chart_data['title']}',
                    data: {chart_data['data']},
                    backgroundColor: 'rgba(54, 162, 235, 0.5)',
                    borderColor: 'rgba(54, 162, 235, 1)',
                    borderWidth: 2
                }}]
            }},
            options: {{
                responsive: true,
                maintainAspectRatio: true,
                scales: {{
                    y: {{
                        beginAtZero: true
                    }}
                }}
            }}
        }});
    
    """

    return html

Markdown Tables

def generate_markdown_table(data, headers=None, alignment=None):
    """
    Generate markdown table from data

    alignment: list of 'left', 'center', 'right'
    """

    if not data:
        return ""

    # Auto-detect headers if not pro

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [CuriousLearner](https://github.com/CuriousLearner)
- **Source:** [CuriousLearner/devkit](https://github.com/CuriousLearner/devkit)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.