claude-statusline-powerline
Version:
Beautiful powerline-style statusline for Claude Code with git integration, session tracking, and cost monitoring
233 lines • 8.45 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsageDatabase = void 0;
exports.get_usage_db = get_usage_db;
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
const fs = __importStar(require("node:fs"));
const os = __importStar(require("node:os"));
const path = __importStar(require("node:path"));
class UsageDatabase {
constructor() {
// Store database in Claude config directory
const claude_dir = path.join(os.homedir(), '.claude');
if (!fs.existsSync(claude_dir)) {
fs.mkdirSync(claude_dir, { recursive: true });
}
this.db_path = path.join(claude_dir, 'statusline-usage.db');
this.db = new better_sqlite3_1.default(this.db_path);
this.initialize_schema();
}
initialize_schema() {
// Create sessions table
this.db.exec(`
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT UNIQUE NOT NULL,
model TEXT NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
input_tokens INTEGER DEFAULT 0,
output_tokens INTEGER DEFAULT 0,
cache_tokens INTEGER DEFAULT 0,
cost REAL DEFAULT 0.0,
project_dir TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// Create daily summaries table
this.db.exec(`
CREATE TABLE IF NOT EXISTS daily_summaries (
date TEXT PRIMARY KEY,
total_sessions INTEGER DEFAULT 0,
total_input_tokens INTEGER DEFAULT 0,
total_output_tokens INTEGER DEFAULT 0,
total_cache_tokens INTEGER DEFAULT 0,
total_cost REAL DEFAULT 0.0,
models_used TEXT DEFAULT '[]',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// Create indexes for performance
this.db.exec(`
CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date(start_time));
CREATE INDEX IF NOT EXISTS idx_sessions_model ON sessions(model);
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_dir);
`);
}
record_session(session) {
const stmt = this.db.prepare(`
INSERT OR REPLACE INTO sessions (
session_id, model, start_time, end_time,
input_tokens, output_tokens, cache_tokens, cost, project_dir
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(session.session_id, session.model, session.start_time, session.end_time, session.input_tokens, session.output_tokens, session.cache_tokens, session.cost, session.project_dir);
// Update daily summary
this.update_daily_summary(session.start_time);
}
update_daily_summary(timestamp) {
const date = timestamp.split('T')[0]; // Extract YYYY-MM-DD
const daily_stats = this.db
.prepare(`
SELECT
COUNT(*) as total_sessions,
SUM(input_tokens) as total_input_tokens,
SUM(output_tokens) as total_output_tokens,
SUM(cache_tokens) as total_cache_tokens,
SUM(cost) as total_cost,
GROUP_CONCAT(DISTINCT model) as models_used
FROM sessions
WHERE date(start_time) = ?
`)
.get(date);
this.db
.prepare(`
INSERT OR REPLACE INTO daily_summaries (
date, total_sessions, total_input_tokens, total_output_tokens,
total_cache_tokens, total_cost, models_used
) VALUES (?, ?, ?, ?, ?, ?, ?)
`)
.run(date, daily_stats.total_sessions || 0, daily_stats.total_input_tokens || 0, daily_stats.total_output_tokens || 0, daily_stats.total_cache_tokens || 0, daily_stats.total_cost || 0.0, JSON.stringify((daily_stats.models_used || '').split(',').filter(Boolean)));
}
get_usage_summary() {
const today = new Date().toISOString().split('T')[0];
const week_ago = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
.toISOString()
.split('T')[0];
const month_ago = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
.toISOString()
.split('T')[0];
// Get today's summary
const today_summary = this.db
.prepare(`
SELECT * FROM daily_summaries WHERE date = ?
`)
.get(today) || {
date: today,
total_sessions: 0,
total_input_tokens: 0,
total_output_tokens: 0,
total_cache_tokens: 0,
total_cost: 0,
models_used: '[]',
};
// Get week summary
const week_stats = this.db
.prepare(`
SELECT
SUM(total_sessions) as total_sessions,
SUM(total_input_tokens) as total_input_tokens,
SUM(total_output_tokens) as total_output_tokens,
SUM(total_cache_tokens) as total_cache_tokens,
SUM(total_cost) as total_cost
FROM daily_summaries
WHERE date >= ?
`)
.get(week_ago);
const week_summary = {
date: week_ago,
total_sessions: week_stats?.total_sessions || 0,
total_input_tokens: week_stats?.total_input_tokens || 0,
total_output_tokens: week_stats?.total_output_tokens || 0,
total_cache_tokens: week_stats?.total_cache_tokens || 0,
total_cost: week_stats?.total_cost || 0,
models_used: '[]',
};
// Get month summary
const month_stats = this.db
.prepare(`
SELECT
SUM(total_sessions) as total_sessions,
SUM(total_input_tokens) as total_input_tokens,
SUM(total_output_tokens) as total_output_tokens,
SUM(total_cache_tokens) as total_cache_tokens,
SUM(total_cost) as total_cost
FROM daily_summaries
WHERE date >= ?
`)
.get(month_ago);
const month_summary = {
date: month_ago,
total_sessions: month_stats?.total_sessions || 0,
total_input_tokens: month_stats?.total_input_tokens || 0,
total_output_tokens: month_stats?.total_output_tokens || 0,
total_cache_tokens: month_stats?.total_cache_tokens || 0,
total_cost: month_stats?.total_cost || 0,
models_used: '[]',
};
// Get recent sessions
const recent_sessions = this.db
.prepare(`
SELECT * FROM sessions
ORDER BY start_time DESC
LIMIT 5
`)
.all();
return {
today: today_summary,
week: week_summary,
month: month_summary,
recent_sessions,
};
}
get_session(session_id) {
try {
const session = this.db
.prepare(`SELECT * FROM sessions WHERE session_id = ?`)
.get(session_id);
return session || null;
}
catch (error) {
return null;
}
}
close() {
this.db.close();
}
}
exports.UsageDatabase = UsageDatabase;
// Singleton instance
let db_instance = null;
function get_usage_db() {
if (!db_instance) {
db_instance = new UsageDatabase();
}
return db_instance;
}
//# sourceMappingURL=usage-db.js.map