
Usage
- 14 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
usage is a skill that tracks LLM token usage, estimates cost, and reports usage analytics across sessions and users.
About
usage tracks LLM token consumption and estimates spend across sessions, users, and models. A developer building an AI agent uses it to record input/output tokens, compute per-model costs, and produce usage summaries or footers. It persists data to SQLite, Postgres, or memory.
- Tracks token usage and estimates cost per session, user, and model
- Stores usage in SQLite, Postgres, or memory
- Exposes chat commands and a TypeScript createUsageService API
Usage by the numbers
- 14 all-time installs (skills.sh)
- Ranked #11,296 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
usage capabilities & compatibility
- Capabilities
- token optimization · data analysis
- Works with
- postgres
- Use cases
- token optimization · data analysis
What usage says it does
Track token usage, estimate costs, and analyze AI consumption across sessions and users.
storage: 'sqlite', // 'sqlite' | 'postgres' | 'memory'
npx skills add https://github.com/alsk1992/cloddsbot --skill usageAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 14 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Track token usage and estimate LLM cost per session, user, and model in an AI agent.
Who is it for?
Developers instrumenting an AI agent who need per-user and per-model token cost tracking.
When should I use this skill?
You need to record token usage and estimate LLM spend for a session or user.
What you get
- usage summary
- cost estimate
By the numbers
- storage options: sqlite, postgres, or memory
- usage periods: day, week, month, all
Files
Usage - Complete API Reference
Track token usage, estimate costs, and analyze AI consumption across sessions and users.
---
Chat Commands
View Usage
/usage Current session usage
/usage today Today's total usage
/usage week This week's usage
/usage month This month's usageDetailed Breakdown
/usage breakdown [today] Cost breakdown by model
/usage by-model Usage by AI model (alias)
/usage by-user Usage by user
/usage history [days] Historical usage (default 7 days)
/usage estimate <model> <in> <out> Estimate cost for tokens
/usage user <id> [today] User-specific usageManagement
/usage reset Clear all usage data---
TypeScript API Reference
Create Usage Service
import { createUsageService } from 'clodds/usage';
const usage = createUsageService({
// Storage
storage: 'sqlite', // 'sqlite' | 'postgres' | 'memory'
dbPath: './usage.db',
// Pricing (per 1M tokens)
pricing: {
'claude-3-opus': { input: 15.00, output: 75.00 },
'claude-3-sonnet': { input: 3.00, output: 15.00 },
'claude-3-haiku': { input: 0.25, output: 1.25 },
'gpt-4': { input: 30.00, output: 60.00 },
'gpt-4o': { input: 5.00, output: 15.00 },
},
// Footer mode
footerMode: 'tokens', // 'off' | 'tokens' | 'full'
});Record Usage
// Record a request
await usage.record({
userId: 'user-123',
sessionId: 'session-456',
model: 'claude-3-sonnet',
inputTokens: 1500,
outputTokens: 800,
durationMs: 2300,
cached: false,
});Get Session Usage
const session = await usage.getSessionUsage('session-456');
console.log(`Session: ${session.sessionId}`);
console.log(`Requests: ${session.requests}`);
console.log(`Input tokens: ${session.inputTokens.toLocaleString()}`);
console.log(`Output tokens: ${session.outputTokens.toLocaleString()}`);
console.log(`Total tokens: ${session.totalTokens.toLocaleString()}`);
console.log(`Est. cost: $${session.estimatedCost.toFixed(4)}`);
console.log(`Duration: ${session.totalDurationMs}ms`);Get User Usage
const user = await usage.getUserUsage('user-123', {
period: 'month', // 'day' | 'week' | 'month' | 'all'
});
console.log(`User: ${user.userId}`);
console.log(`Sessions: ${user.sessions}`);
console.log(`Total tokens: ${user.totalTokens.toLocaleString()}`);
console.log(`Est. cost: $${user.estimatedCost.toFixed(2)}`);Get Total Usage
const total = await usage.getTotalUsage({
from: '2024-01-01',
to: '2024-01-31',
});
console.log(`Total requests: ${total.requests}`);
console.log(`Total tokens: ${total.totalTokens.toLocaleString()}`);
console.log(`Total cost: $${total.estimatedCost.toFixed(2)}`);Usage by Model
const byModel = await usage.getUsageByModel({
period: 'month',
});
for (const [model, stats] of Object.entries(byModel)) {
console.log(`${model}:`);
console.log(` Requests: ${stats.requests}`);
console.log(` Tokens: ${stats.totalTokens.toLocaleString()}`);
console.log(` Cost: $${stats.cost.toFixed(2)}`);
}Format Footer
// Get formatted usage footer for messages
const footer = usage.formatFooter({
inputTokens: 1500,
outputTokens: 800,
model: 'claude-3-sonnet',
});
// Output: "Tokens: 1.5k in / 800 out | Cost: ~$0.02"Format Summary
// Get formatted summary
const summary = await usage.formatSummary({
userId: 'user-123',
period: 'today',
});
console.log(summary);
// "Today: 15 requests | 45k tokens | ~$0.85"Estimate Cost
// Estimate cost for a request
const cost = usage.estimateCost({
model: 'claude-3-opus',
inputTokens: 5000,
outputTokens: 2000,
});
console.log(`Estimated cost: $${cost.toFixed(4)}`);---
Model Pricing (per 1M tokens)
| Model | Input | Output |
|---|---|---|
| claude-3-opus | $15.00 | $75.00 |
| claude-3-sonnet | $3.00 | $15.00 |
| claude-3-haiku | $0.25 | $1.25 |
| gpt-4 | $30.00 | $60.00 |
| gpt-4o | $5.00 | $15.00 |
| gpt-4o-mini | $0.15 | $0.60 |
---
Footer Modes
| Mode | Output |
|---|---|
off | No usage shown |
tokens | Tokens: 1.5k in / 800 out |
full | `Tokens: 1.5k in / 800 out |
---
Budget Alerts
// Set monthly budget
usage.setBudget({
userId: 'user-123',
monthly: 50.00, // $50/month
alertAt: [0.5, 0.8, 0.95], // Alert at 50%, 80%, 95%
});
// Check budget status
const budget = await usage.checkBudget('user-123');
console.log(`Budget: $${budget.limit}`);
console.log(`Used: $${budget.used.toFixed(2)} (${budget.percent}%)`);
console.log(`Remaining: $${budget.remaining.toFixed(2)}`);---
Best Practices
1. Monitor regularly — Check usage weekly 2. Set budgets — Prevent unexpected costs 3. Use appropriate models — Haiku for simple tasks 4. Cache when possible — Reduce duplicate queries 5. Review by user — Identify heavy users
/**
* Usage CLI Skill
*
* Commands:
* /usage - Show usage summary (all time)
* /usage today - Today's usage
* /usage week - Last 7 days usage
* /usage month - Last 30 days usage
* /usage breakdown [today] - Cost breakdown by model
* /usage by-model - Break down usage by model
* /usage by-user - Break down usage by user
* /usage history - Usage history over time
* /usage estimate <model> <in> <out> - Estimate cost
* /usage user <id> [today] - User-specific usage
* /usage reset - Clear all usage data
*/
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'summary';
try {
const { createUsageService } = await import('../../../usage/index');
const { initDatabase } = await import('../../../db/index');
const db = await initDatabase();
const service = createUsageService(db);
switch (cmd) {
case 'summary':
case 'all': {
const summary = service.getTotalUsage(false);
return service.formatSummary(summary);
}
case 'today': {
const summary = service.getTotalUsage(true);
if (summary.totalRequests === 0) {
return '**Today\'s Usage**\n\nNo usage recorded today.';
}
return `**Today's Usage**\n\n` +
`Requests: ${summary.totalRequests}\n` +
`Input tokens: ${summary.totalInputTokens.toLocaleString()}\n` +
`Output tokens: ${summary.totalOutputTokens.toLocaleString()}\n` +
`Total tokens: ${summary.totalTokens.toLocaleString()}\n` +
`Estimated cost: $${summary.estimatedCost.toFixed(4)}`;
}
case 'week': {
const sinceDate = new Date();
sinceDate.setDate(sinceDate.getDate() - 7);
sinceDate.setHours(0, 0, 0, 0);
const summary = getUsageSince(db, sinceDate);
if (summary.totalRequests === 0) {
return '**Last 7 Days Usage**\n\nNo usage recorded this week.';
}
return `**Last 7 Days Usage**\n\n` +
`Requests: ${summary.totalRequests}\n` +
`Input tokens: ${summary.totalInputTokens.toLocaleString()}\n` +
`Output tokens: ${summary.totalOutputTokens.toLocaleString()}\n` +
`Total tokens: ${summary.totalTokens.toLocaleString()}\n` +
`Estimated cost: $${summary.estimatedCost.toFixed(4)}`;
}
case 'month': {
const sinceDate = new Date();
sinceDate.setDate(sinceDate.getDate() - 30);
sinceDate.setHours(0, 0, 0, 0);
const summary = getUsageSince(db, sinceDate);
if (summary.totalRequests === 0) {
return '**Last 30 Days Usage**\n\nNo usage recorded this month.';
}
return `**Last 30 Days Usage**\n\n` +
`Requests: ${summary.totalRequests}\n` +
`Input tokens: ${summary.totalInputTokens.toLocaleString()}\n` +
`Output tokens: ${summary.totalOutputTokens.toLocaleString()}\n` +
`Total tokens: ${summary.totalTokens.toLocaleString()}\n` +
`Estimated cost: $${summary.estimatedCost.toFixed(4)}`;
}
case 'by-model':
case 'breakdown':
case 'costs':
case 'models': {
const todayOnly = parts[1]?.toLowerCase() === 'today';
const summary = service.getTotalUsage(todayOnly);
if (summary.totalRequests === 0) {
return `**Cost Breakdown${todayOnly ? ' (Today)' : ''}**\n\nNo usage recorded.`;
}
const lines = [`**Cost Breakdown${todayOnly ? ' (Today)' : ''}**\n`];
for (const [model, data] of Object.entries(summary.byModel)) {
const modelShort = model.split('-').slice(1, 3).join('-');
const totalTokens = data.inputTokens + data.outputTokens;
lines.push(
`**${modelShort}**\n` +
` Requests: ${data.requests}\n` +
` Input: ${data.inputTokens.toLocaleString()} tokens\n` +
` Output: ${data.outputTokens.toLocaleString()} tokens\n` +
` Total: ${totalTokens.toLocaleString()} tokens\n` +
` Cost: $${data.cost.toFixed(4)}`
);
}
lines.push(
`\n**Total: $${summary.estimatedCost.toFixed(4)}** (${summary.totalTokens.toLocaleString()} tokens across ${summary.totalRequests} requests)`
);
return lines.join('\n');
}
case 'by-user': {
const records = db.query<{
user_id: string;
req_count: number;
total_input: number;
total_output: number;
total_cost: number;
}>(`SELECT user_id, COUNT(*) as req_count,
SUM(input_tokens) as total_input,
SUM(output_tokens) as total_output,
SUM(estimated_cost) as total_cost
FROM usage_records GROUP BY user_id ORDER BY total_cost DESC`, []);
if (!records.length) {
return '**Usage by User**\n\nNo usage recorded.';
}
const lines = ['**Usage by User**\n'];
for (const row of records) {
const totalTokens = row.total_input + row.total_output;
lines.push(
`**${row.user_id}**\n` +
` Requests: ${row.req_count}\n` +
` Tokens: ${totalTokens.toLocaleString()}\n` +
` Cost: $${row.total_cost.toFixed(4)}`
);
}
return lines.join('\n');
}
case 'history': {
const days = parseInt(parts[1] || '7', 10);
const sinceDate = new Date();
sinceDate.setDate(sinceDate.getDate() - days);
sinceDate.setHours(0, 0, 0, 0);
const records = db.query<{
day: string;
req_count: number;
total_tokens: number;
total_cost: number;
}>(`SELECT date(timestamp / 1000, 'unixepoch', 'localtime') as day,
COUNT(*) as req_count,
SUM(total_tokens) as total_tokens,
SUM(estimated_cost) as total_cost
FROM usage_records
WHERE timestamp >= ?
GROUP BY day ORDER BY day ASC`, [sinceDate.getTime()]);
if (!records.length) {
return `**Usage History (${days} days)**\n\nNo usage recorded.`;
}
const lines = [`**Usage History (${days} days)**\n`];
for (const row of records) {
const bar = '|'.repeat(Math.min(Math.ceil(row.total_cost * 100), 30));
lines.push(
`${row.day} | ${row.req_count} reqs | ${row.total_tokens.toLocaleString()} tokens | $${row.total_cost.toFixed(4)} ${bar}`
);
}
return lines.join('\n');
}
case 'estimate': {
// Estimate cost for a hypothetical request
const model = parts[1] || 'claude-sonnet-4-20250514';
const inputTokens = parseInt(parts[2] || '1000', 10);
const outputTokens = parseInt(parts[3] || '500', 10);
const cost = service.estimateCost(model, inputTokens, outputTokens);
const modelShort = model.split('-').slice(1, 3).join('-');
return `**Cost Estimate**\n\n` +
`Model: ${modelShort}\n` +
`Input: ${inputTokens.toLocaleString()} tokens\n` +
`Output: ${outputTokens.toLocaleString()} tokens\n` +
`Estimated cost: $${cost.toFixed(6)}`;
}
case 'user': {
const userId = parts[1] || 'default';
const todayOnly = parts[2]?.toLowerCase() === 'today';
const summary = service.getUserUsage(userId, todayOnly);
if (summary.totalRequests === 0) {
return `**User Usage: ${userId}**\n\nNo usage recorded.`;
}
return `**User Usage: ${userId}${todayOnly ? ' (Today)' : ''}**\n\n` +
service.formatSummary(summary);
}
case 'reset': {
// Reset by dropping and recreating the table
db.run('DELETE FROM usage_records');
return '**Usage Reset**\n\nAll usage records cleared.';
}
default:
return helpText();
}
} catch (error) {
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
/** Helper: query usage since a given date using raw DB query */
function getUsageSince(db: any, since: Date) {
const records = db.query(
`SELECT model, input_tokens, output_tokens, estimated_cost
FROM usage_records WHERE timestamp >= ?`,
[since.getTime()]
) as Array<{ model: string; input_tokens: number; output_tokens: number; estimated_cost: number }>;
let totalInputTokens = 0;
let totalOutputTokens = 0;
let estimatedCost = 0;
for (const r of records) {
totalInputTokens += r.input_tokens;
totalOutputTokens += r.output_tokens;
estimatedCost += r.estimated_cost;
}
return {
totalRequests: records.length,
totalInputTokens,
totalOutputTokens,
totalTokens: totalInputTokens + totalOutputTokens,
estimatedCost,
};
}
function helpText(): string {
return `**Usage Commands**
/usage - Usage summary (all time)
/usage today - Today's usage
/usage week - Last 7 days usage
/usage month - Last 30 days usage
/usage breakdown [today] - Cost breakdown by model
/usage by-model - Break down by model
/usage by-user - Break down by user
/usage history [days] - Usage history over time
/usage estimate <model> <in> <out> - Estimate cost
/usage user <id> [today] - User-specific usage
/usage reset - Clear all usage data`;
}
export default {
name: 'usage',
description: 'Token usage tracking, cost estimation, and usage analytics',
commands: ['/usage'],
handle: execute,
};