mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 08:13:37 +00:00
feat: add Claude usage tracking via CLI
Adds a Claude usage tracking feature that displays session, weekly, and Sonnet usage stats. Uses the Claude CLI's /usage command to fetch data (no API key required). Features: - Usage popover in board header showing session, weekly, and Sonnet limits - Progress bars with color-coded status (green/orange/red) - Auto-refresh with configurable interval - Caching of usage data with stale indicator - Settings section for refresh interval configuration Server: - ClaudeUsageService: Executes Claude CLI via PTY (expect) to fetch usage - New /api/claude/usage endpoint UI: - ClaudeUsagePopover component with usage cards - ClaudeUsageSection in settings for configuration - Integration with app store for persistence
This commit is contained in:
44
apps/server/src/routes/claude/index.ts
Normal file
44
apps/server/src/routes/claude/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { ClaudeUsageService } from "../../services/claude-usage-service.js";
|
||||
|
||||
export function createClaudeRoutes(): Router {
|
||||
const router = Router();
|
||||
const service = new ClaudeUsageService();
|
||||
|
||||
// Get current usage (fetches from Claude CLI)
|
||||
router.get("/usage", async (req: Request, res: Response) => {
|
||||
try {
|
||||
// Check if Claude CLI is available first
|
||||
const isAvailable = await service.isAvailable();
|
||||
if (!isAvailable) {
|
||||
res.status(503).json({
|
||||
error: "Claude CLI not found",
|
||||
message: "Please install Claude Code CLI and run 'claude login' to authenticate"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const usage = await service.fetchUsageData();
|
||||
res.json(usage);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unknown error";
|
||||
|
||||
if (message.includes("Authentication required") || message.includes("token_expired")) {
|
||||
res.status(401).json({
|
||||
error: "Authentication required",
|
||||
message: "Please run 'claude login' to authenticate"
|
||||
});
|
||||
} else if (message.includes("timed out")) {
|
||||
res.status(504).json({
|
||||
error: "Command timed out",
|
||||
message: "The Claude CLI took too long to respond"
|
||||
});
|
||||
} else {
|
||||
console.error("Error fetching usage:", error);
|
||||
res.status(500).json({ error: message });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
35
apps/server/src/routes/claude/types.ts
Normal file
35
apps/server/src/routes/claude/types.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Claude Usage types for CLI-based usage tracking
|
||||
*/
|
||||
|
||||
export type ClaudeUsage = {
|
||||
sessionTokensUsed: number;
|
||||
sessionLimit: number;
|
||||
sessionPercentage: number;
|
||||
sessionResetTime: string; // ISO date string
|
||||
sessionResetText: string; // Raw text like "Resets 10:59am (Asia/Dubai)"
|
||||
|
||||
weeklyTokensUsed: number;
|
||||
weeklyLimit: number;
|
||||
weeklyPercentage: number;
|
||||
weeklyResetTime: string; // ISO date string
|
||||
weeklyResetText: string; // Raw text like "Resets Dec 22 at 7:59pm (Asia/Dubai)"
|
||||
|
||||
opusWeeklyTokensUsed: number;
|
||||
opusWeeklyPercentage: number;
|
||||
opusResetText: string; // Raw text like "Resets Dec 27 at 9:59am (Asia/Dubai)"
|
||||
|
||||
costUsed: number | null;
|
||||
costLimit: number | null;
|
||||
costCurrency: string | null;
|
||||
|
||||
lastUpdated: string; // ISO date string
|
||||
userTimezone: string;
|
||||
};
|
||||
|
||||
export type ClaudeStatus = {
|
||||
indicator: {
|
||||
color: "green" | "yellow" | "orange" | "red" | "gray";
|
||||
};
|
||||
description: string;
|
||||
};
|
||||
Reference in New Issue
Block a user