General
usage-tracking-specialist - Claude MCP Skill
Usage Tracking Specialist
SEO Guide: Enhance your AI agent with the usage-tracking-specialist tool. This Model Context Protocol (MCP) server allows Claude Desktop and other LLMs to usage tracking specialist... Download and configure this skill to unlock new capabilities for your AI workflow.
Documentation
SKILL.md# Usage Tracking Specialist
You are an expert in usage-based billing, quota management, and performance-optimized tracking systems. Your mission is to implement AI generation tracking and limit enforcement for id8composer.
## Your Expertise
- Usage tracking architecture
- Quota management and limit enforcement
- High-performance database queries
- Caching strategies for usage data
- Rate limiting and throttling
## Current Assignment: Implement AI Generation Usage Tracking
### Problem Analysis
**Current State**:
- `/Users/eddiebelaval/Development/id8/id8composer-rebuild/src/lib/billing/plans.ts` defines `aiGenerationsPerMonth` limits (50 for FREE, unlimited for PRO/ENTERPRISE)
- No actual tracking of AI generations exists
- Users can bypass limits
- `/Users/eddiebelaval/Development/id8/id8composer-rebuild/src/components/billing/usage-indicator.tsx` shows mock data (line 83-84)
**Database**:
- `usage_tracking` table already exists (created in migration 20251030)
- Schema: id, user_id, type, count, period_start, period_end, metadata
### Your Solution
#### Task 1: Create Usage Tracking Service
**Create**: `/Users/eddiebelaval/Development/id8/id8composer-rebuild/src/lib/usage/usage-tracker.ts`
**Core Functions**:
```typescript
import { createClient } from '@/lib/supabase/server';
import { getUserTier } from '@/lib/billing/subscription-manager';
import { PRICING_PLANS } from '@/lib/billing/plans';
export type UsageType = 'ai_generation' | 'export' | 'kb_file';
/**
* Track a usage event for a user
*/
export async function trackUsage(
userId: string,
type: UsageType,
metadata?: Record<string, any>
): Promise<void> {
const supabase = createClient();
// Get current billing period (monthly)
const now = new Date();
const periodStart = new Date(now.getFullYear(), now.getMonth(), 1);
const periodEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0);
try {
// Upsert usage record (increment count if exists)
const { error } = await supabase
.from('usage_tracking')
.upsert({
user_id: userId,
type,
period_start: periodStart.toISOString(),
period_end: periodEnd.toISOString(),
count: 1, // Will be incremented by trigger or manual query
metadata: metadata || {},
}, {
onConflict: 'user_id,type,period_start',
// Increment count on conflict
});
if (error) {
console.error('Failed to track usage:', error);
// Don't throw - usage tracking failure shouldn't block user
}
} catch (error) {
console.error('Usage tracking error:', error);
}
}
/**
* Get current usage for a user in current billing period
*/
export async function getCurrentUsage(
userId: string,
type: UsageType
): Promise<number> {
const supabase = createClient();
const now = new Date();
const periodStart = new Date(now.getFullYear(), now.getMonth(), 1);
const { data, error } = await supabase
.from('usage_tracking')
.select('count')
.eq('user_id', userId)
.eq('type', type)
.gte('period_start', periodStart.toISOString())
.single();
if (error || !data) {
return 0;
}
return data.count || 0;
}
/**
* Check if user has exceeded their tier's limit for a usage type
*/
export async function checkUsageLimit(
userId: string,
type: UsageType
): Promise<{ allowed: boolean; current: number; limit: number; tier: string }> {
// Get user's tier
const tier = await getUserTier(userId);
// Get tier limits
const limits = PRICING_PLANS[tier]?.limits;
// Get limit for this usage type
const limit = type === 'ai_generation'
? limits?.aiGenerationsPerMonth
: type === 'export'
? limits?.exportsPerMonth // Add this to plans.ts if missing
: limits?.kbFiles;
// -1 means unlimited
if (limit === -1) {
return { allowed: true, current: 0, limit: -1, tier };
}
// Get current usage
const current = await getCurrentUsage(userId, type);
// Check if under limit
const allowed = current < limit;
return { allowed, current, limit, tier };
}
/**
* Enforce usage limit - throws error if exceeded
*/
export async function enforceUsageLimit(
userId: string,
type: UsageType
): Promise<void> {
const { allowed, current, limit, tier } = await checkUsageLimit(userId, type);
if (!allowed) {
const error = new Error(
`Usage limit exceeded for ${type}. Your ${tier} plan allows ${limit} per month. You've used ${current}.`
);
error.name = 'UsageLimitExceeded';
throw error;
}
}
```
#### Task 2: Integrate with AI Generation Endpoints
**Find AI generation endpoints** (likely in `/Users/eddiebelaval/Development/id8/id8composer-rebuild/src/app/api/ai/` or similar)
**Add tracking + enforcement**:
```typescript
import { enforceUsageLimit, trackUsage } from '@/lib/usage/usage-tracker';
export async function POST(req: Request) {
const { user } = await getUser(); // Your auth method
try {
// 1. Check limit BEFORE generating
await enforceUsageLimit(user.id, 'ai_generation');
// 2. Generate AI content
const result = await generateAIContent(...);
// 3. Track usage AFTER successful generation
await trackUsage(user.id, 'ai_generation', {
prompt_tokens: result.usage.prompt_tokens,
completion_tokens: result.usage.completion_tokens,
model: result.model,
});
return NextResponse.json(result);
} catch (error) {
if (error.name === 'UsageLimitExceeded') {
return NextResponse.json(
{
error: error.message,
code: 'USAGE_LIMIT_EXCEEDED',
upgrade_url: '/settings/billing',
},
{ status: 402 } // Payment Required
);
}
throw error;
}
}
```
**Files to update**:
- Search for AI generation endpoints
- Add tracking to each endpoint
- Ensure proper error handling
#### Task 3: Update Usage Indicator UI
**Modify**: `/Users/eddiebelaval/Development/id8/id8composer-rebuild/src/components/billing/usage-indicator.tsx`
**Replace mock data (lines 83-84) with real usage**:
```typescript
import { useEffect, useState } from 'react';
import { getCurrentUsage } from '@/lib/usage/usage-tracker';
import { useAuth } from '@/hooks/use-auth';
import { PRICING_PLANS } from '@/lib/billing/plans';
export function UsageIndicator() {
const { user, subscription } = useAuth();
const [usage, setUsage] = useState({ ai_generation: 0, export: 0, kb_file: 0 });
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUsage() {
if (!user) return;
const [aiUsage, exportUsage, kbUsage] = await Promise.all([
getCurrentUsage(user.id, 'ai_generation'),
getCurrentUsage(user.id, 'export'),
getCurrentUsage(user.id, 'kb_file'),
]);
setUsage({
ai_generation: aiUsage,
export: exportUsage,
kb_file: kbUsage,
});
setLoading(false);
}
fetchUsage();
}, [user]);
if (loading) return <div>Loading usage...</div>;
const tier = subscription?.tier || 'FREE';
const limits = PRICING_PLANS[tier]?.limits;
return (
<div className="space-y-4">
<UsageBar
label="AI Generations"
current={usage.ai_generation}
limit={limits.aiGenerationsPerMonth}
/>
<UsageBar
label="KB Files"
current={usage.kb_file}
limit={limits.kbFiles}
/>
{/* Add more usage bars */}
</div>
);
}
function UsageBar({ label, current, limit }: { label: string; current: number; limit: number }) {
const percentage = limit === -1 ? 0 : (current / limit) * 100;
const isUnlimited = limit === -1;
return (
<div>
<div className="flex justify-between text-sm mb-1">
<span>{label}</span>
<span>
{current} / {isUnlimited ? '∞' : limit}
</span>
</div>
{!isUnlimited && (
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className={`h-2 rounded-full ${percentage >= 90 ? 'bg-red-500' : 'bg-blue-500'}`}
style={{ width: `${Math.min(percentage, 100)}%` }}
/>
</div>
)}
</div>
);
}
```
#### Task 4: Add Database Function for Atomic Increment
**Create**: `/Users/eddiebelaval/Development/id8/id8composer-rebuild/supabase/migrations/20251110_usage_tracking_increment.sql`
```sql
-- Atomic increment function for usage tracking
CREATE OR REPLACE FUNCTION increment_usage(
p_user_id UUID,
p_type TEXT,
p_period_start TIMESTAMPTZ,
p_period_end TIMESTAMPTZ,
p_metadata JSONB DEFAULT '{}'::jsonb
)
RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO public.usage_tracking (
id, user_id, type, period_start, period_end, count, metadata, created_at, updated_at
) VALUES (
gen_random_uuid(), p_user_id, p_type, p_period_start, p_period_end, 1, p_metadata, NOW(), NOW()
)
ON CONFLICT (user_id, type, period_start)
DO UPDATE SET
count = usage_tracking.count + 1,
metadata = p_metadata,
updated_at = NOW();
END;
$$;
```
Update `trackUsage()` to use this function via RPC call.
## Deliverables
1. ✅ Usage tracking service: `src/lib/usage/usage-tracker.ts`
2. ✅ Database function: `supabase/migrations/20251110_usage_tracking_increment.sql`
3. ✅ AI endpoints updated with tracking + enforcement
4. ✅ Usage indicator UI showing real data
5. ✅ Tests: `src/lib/usage/__tests__/usage-tracker.test.ts`
6. ✅ Proper error handling (402 Payment Required when limit exceeded)
## Success Criteria
- FREE users blocked after 50 AI generations
- PRO/ENTERPRISE users have unlimited access
- Usage displays accurately in UI
- Tracking doesn't slow down API responses
- Limits reset monthly
- Atomic increments prevent race conditions
## Testing Checklist
- [ ] FREE user generates 50 AI responses → works
- [ ] FREE user tries 51st generation → 402 error with upgrade link
- [ ] PRO user generates 100+ responses → works
- [ ] Usage indicator shows correct counts
- [ ] Usage resets on 1st of month
- [ ] Concurrent requests don't double-count
## Performance Considerations
- Use database indexes on (user_id, type, period_start)
- Cache current usage in memory for 1 minute
- Use atomic increments to prevent race conditions
- Don't block requests on usage tracking failures
Begin your work now. Focus on accuracy, performance, and user experience when limits are hit.Signals
Information
- Repository
- eddiebe147/claude-settings
- Author
- eddiebe147
- Last Sync
- 1/18/2026
- Repo Updated
- 1/16/2026
- Created
- 1/17/2026
Reviews (0)
No reviews yet. Be the first to review this skill!
Related Skills
upgrade-nodejs
Upgrading Bun's Self-Reported Node.js Version
cursorrules
CrewAI Development Rules
cn-check
Install and run the Continue CLI (`cn`) to execute AI agent checks on local code changes. Use when asked to "run checks", "lint with AI", "review my changes with cn", or set up Continue CI locally.
CLAUDE
CLAUDE.md
Related Guides
Bear Notes Claude Skill: Your AI-Powered Note-Taking Assistant
Learn how to use the bear-notes Claude skill. Complete guide with installation instructions and examples.
Mastering tmux with Claude: A Complete Guide to the tmux Claude Skill
Learn how to use the tmux Claude skill. Complete guide with installation instructions and examples.
OpenAI Whisper API Claude Skill: Complete Guide to AI-Powered Audio Transcription
Learn how to use the openai-whisper-api Claude skill. Complete guide with installation instructions and examples.