Claude-skill-registry data-insights
Generate actionable insights from transaction data. Use when implementing insight generators, anomaly detection, or data analysis features for financial/tax tracking applications.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/data-insights" ~/.claude/skills/majiayu000-claude-skill-registry-data-insights && rm -rf "$T"
manifest:
skills/data/data-insights/SKILL.mdsource content
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
- Pure Functions: Each insight generator should be a pure function taking transactions and returning insights
- Configurable Thresholds: Make trigger thresholds configurable via parameters
- Efficient Queries: Compute all insights in a single pass when possible
- Test with Edge Cases: Empty data, single transaction, all same merchant, etc.
- Sort by Severity: Return insights sorted by severityScore descending