Claude Code Plugins

Community-maintained marketplace

Feedback

Generate actionable insights from transaction data. Use when implementing insight generators, anomaly detection, or data analysis features for financial/tax tracking applications.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name data-insights
description Generate actionable insights from transaction data. Use when implementing insight generators, anomaly detection, or data analysis features for financial/tax tracking applications.

Data Insights Skill

This skill provides patterns for generating actionable insights from transaction data, specifically designed for tax and expense tracking applications.

When to Use This Skill

  • Implementing insight generators for dashboards
  • Detecting spending anomalies and patterns
  • Computing aggregated statistics over time ranges
  • Building ranked insight cards with drill-down capabilities

Core Insight Types

1. Quiet Leaks (Small Recurring Expenses)

Detects small, frequent purchases that add up significantly.

Trigger Rules:

  • Transaction appears 3+ times in the range
  • Individual amounts ≤ $20
  • Cumulative total ≥ $50

Severity Calculation:

severity = Math.min(10, Math.floor(cumulativeTotal / 25))

Query Pattern:

// Group by merchant, count occurrences, sum totals
const quietLeaks = transactions
  .filter(t => parseFloat(t.totalAmount) <= 20)
  .reduce((acc, t) => {
    const key = t.merchant || 'Unknown';
    if (!acc[key]) acc[key] = { count: 0, total: 0, transactions: [] };
    acc[key].count++;
    acc[key].total += parseFloat(t.totalAmount);
    acc[key].transactions.push(t.id);
    return acc;
  }, {});

// Filter to those with 3+ occurrences and $50+ total
return Object.entries(quietLeaks)
  .filter(([_, data]) => data.count >= 3 && data.total >= 50)
  .map(([merchant, data]) => ({
    type: 'QUIET_LEAK',
    title: `${merchant} adds up`,
    summary: `${data.count} purchases totaling $${data.total.toFixed(2)}`,
    severityScore: Math.min(10, Math.floor(data.total / 25)),
    supportingTransactionIds: data.transactions
  }));

2. Tax Drag (High Tax Rate Merchants)

Identifies merchants or categories with unusually high effective tax rates.

Trigger Rules:

  • Effective tax rate > 9% (above typical sales tax)
  • At least $100 spent at merchant

Severity Calculation:

severity = Math.min(10, Math.floor((effectiveTaxRate - 0.08) * 100))

Query Pattern:

const taxDrag = transactions.reduce((acc, t) => {
  const key = t.merchant || 'Unknown';
  const taxRate = parseFloat(t.taxAmount) / parseFloat(t.totalAmount);
  if (!acc[key]) acc[key] = { totalSpent: 0, totalTax: 0, transactions: [] };
  acc[key].totalSpent += parseFloat(t.totalAmount);
  acc[key].totalTax += parseFloat(t.taxAmount);
  acc[key].transactions.push(t.id);
  return acc;
}, {});

return Object.entries(taxDrag)
  .filter(([_, data]) => {
    const effectiveRate = data.totalTax / data.totalSpent;
    return effectiveRate > 0.09 && data.totalSpent >= 100;
  })
  .map(([merchant, data]) => {
    const effectiveRate = data.totalTax / data.totalSpent;
    return {
      type: 'TAX_DRAG',
      title: `High tax burden at ${merchant}`,
      summary: `${(effectiveRate * 100).toFixed(1)}% effective tax rate on $${data.totalSpent.toFixed(2)}`,
      severityScore: Math.min(10, Math.floor((effectiveRate - 0.08) * 100)),
      supportingTransactionIds: data.transactions
    };
  });

3. Spikes/Anomalies (Unusual Spending)

Detects month-over-month jumps, duplicates, or unusual amounts.

Trigger Rules:

  • Single transaction > 2x average transaction
  • Month-over-month increase > 50%
  • Duplicate-like entries (same merchant + amount within 24h)

Severity Calculation:

// For outliers
severity = Math.min(10, Math.floor((amount / average - 1) * 2))

// For MoM spikes
severity = Math.min(10, Math.floor((percentIncrease - 50) / 10))

Query Pattern:

const average = transactions.reduce((sum, t) => sum + parseFloat(t.totalAmount), 0) / transactions.length;

// Find outliers
const outliers = transactions
  .filter(t => parseFloat(t.totalAmount) > average * 2)
  .map(t => ({
    type: 'SPIKE',
    title: `Unusual expense: $${parseFloat(t.totalAmount).toFixed(2)}`,
    summary: `${t.merchant || 'Unknown'} - ${((parseFloat(t.totalAmount) / average - 1) * 100).toFixed(0)}% above average`,
    severityScore: Math.min(10, Math.floor((parseFloat(t.totalAmount) / average - 1) * 2)),
    supportingTransactionIds: [t.id]
  }));

// Find duplicates
const potentialDuplicates = findDuplicates(transactions);

Output Format

All insight generators must return this standardized format:

interface Insight {
  type: 'QUIET_LEAK' | 'TAX_DRAG' | 'SPIKE' | 'DUPLICATE' | 'MOM_INCREASE';
  title: string;       // Short, attention-grabbing headline
  summary: string;     // 1-2 sentence explanation
  severityScore: number; // 1-10 scale for ranking
  supportingTransactionIds: string[]; // For drill-down
}

Implementation Structure

src/lib/insights/
├── index.ts              # Main getInsights() function
├── types.ts              # Insight interface definitions
├── generators/
│   ├── quiet-leaks.ts    # detectQuietLeaks()
│   ├── tax-drag.ts       # detectTaxDrag()
│   └── spikes.ts         # detectSpikes()
└── __tests__/
    ├── quiet-leaks.test.ts
    ├── tax-drag.test.ts
    └── spikes.test.ts

Best Practices

  1. Pure Functions: Each insight generator should be a pure function taking transactions and returning insights
  2. Configurable Thresholds: Make trigger thresholds configurable via parameters
  3. Efficient Queries: Compute all insights in a single pass when possible
  4. Test with Edge Cases: Empty data, single transaction, all same merchant, etc.
  5. Sort by Severity: Return insights sorted by severityScore descending