tokens-metric 0.4.4 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,9 @@ export function codexHome() {
14
14
  export function codexSessionsDir() {
15
15
  return join(codexHome(), 'sessions');
16
16
  }
17
+ export function isCodexInstalled() {
18
+ return existsSync(codexHome());
19
+ }
17
20
  /**
18
21
  * Detect whether Claude Code is installed, the user is logged in, and best-
19
22
  * effort what plan they're on. All signals are LOCAL and BEST-EFFORT — we
package/dist/tui/index.js CHANGED
@@ -6,7 +6,7 @@ import { createInterface } from 'node:readline';
6
6
  import { spawnSync } from 'node:child_process';
7
7
  import { findActiveTranscript, findActiveCodexTranscript, listTranscripts } from '../core/parser.js';
8
8
  import { tailTranscript } from '../core/tailer.js';
9
- import { detectAuth } from '../core/detect.js';
9
+ import { detectAuth, isCodexInstalled } from '../core/detect.js';
10
10
  import { categoryCostUSD, contextWindowSize, estimateCostUSD, fmtNumber, fmtUSD } from '../core/format.js';
11
11
  import { buildHistory, bucketCostUSD, bucketTokens, bucketTopModel, getTodaySessions, } from '../core/history.js';
12
12
  import { totalTokens } from '../core/types.js';
@@ -29,6 +29,7 @@ const BAR_WIDTH = 20;
29
29
  function App() {
30
30
  const { exit } = useApp();
31
31
  const [auth] = useState(() => detectAuth());
32
+ const [codexDetected] = useState(() => isCodexInstalled());
32
33
  // Claude source
33
34
  const [claudeStats, setClaudeStats] = useState(null);
34
35
  const [claudePath, setClaudePath] = useState(null);
@@ -235,19 +236,19 @@ function App() {
235
236
  const lastTailAt = claudeLastTailAt && codexLastTailAt
236
237
  ? Math.max(claudeLastTailAt, codexLastTailAt)
237
238
  : claudeLastTailAt ?? codexLastTailAt;
238
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Header, { auth: auth, sessionsToday: today.sessions, projectsToday: today.projects, lastTailAt: lastTailAt, startedAt: startedAtRef.current, now: now, updateAvailable: updateAvailable }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [claudeStats
239
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Header, { auth: auth, codexDetected: codexDetected, sessionsToday: today.sessions, projectsToday: today.projects, lastTailAt: lastTailAt, startedAt: startedAtRef.current, now: now, updateAvailable: updateAvailable }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [claudeStats
239
240
  ? _jsx(SessionStatusBar, { stats: claudeStats, ratePerSec: claudeRate, now: now, series: claudeSeries })
240
241
  : !codexStats && _jsx(SessionStatusBar, { stats: null, ratePerSec: 0, now: now, series: claudeSeries }), codexStats && (_jsx(Box, { marginTop: claudeStats ? 1 : 0, children: _jsx(SessionStatusBar, { stats: codexStats, ratePerSec: codexRate, now: now, series: codexSeries }) }))] }), _jsx(Box, { marginTop: 1, children: _jsx(TabBar, { focusedTab: focusedTab, openTab: openTab }) }), openTab !== null && (_jsxs(Box, { marginTop: 1, children: [openTab === 1 && (_jsx(BreakdownPanel, { stats: primaryStats, series: primarySeries, ratePerSec: primaryRate })), openTab === 2 && _jsx(HistoryPanel, { history: history }), openTab === 3 && _jsx(TodaySessionsPanel, { sessions: todaySessions, now: now }), openTab === 4 && (_jsx(TranscriptsPanel, { transcripts: transcripts, activePath: claudePath, now: now }))] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [_jsx(Text, { color: "magenta", children: "q" }), " quit \u00B7", ' ', _jsx(Text, { color: "magenta", children: "\u2190\u2192" }), " move \u00B7", ' ', _jsx(Text, { color: "magenta", children: "enter" }), " open/close \u00B7", ' ', _jsx(Text, { color: "magenta", children: "1\u20134" }), " jump \u00B7 pricing is", ' ', _jsx(Text, { italic: true, children: "API-equivalent" }), ", not your real bill on a subscription"] }) })] }));
241
242
  }
242
243
  // ── Header ───────────────────────────────────────────────────────────────────
243
- function Header({ auth, sessionsToday, projectsToday, lastTailAt, startedAt, now, updateAvailable, }) {
244
+ function Header({ auth, codexDetected, sessionsToday, projectsToday, lastTailAt, startedAt, now, updateAvailable, }) {
244
245
  const ok = auth.installed && auth.loggedIn;
245
246
  const dot = ok ? 'green' : auth.installed ? 'yellow' : 'red';
246
247
  const tailAgo = lastTailAt ? `updated ${timeAgo(now - lastTailAt)} ago` : 'waiting…';
247
248
  const tailIsLive = !!lastTailAt && now - lastTailAt < 10_000;
248
249
  const tailColor = !lastTailAt ? 'gray' : tailIsLive ? 'green' : 'yellow';
249
250
  const tailStatusText = !lastTailAt ? '' : tailIsLive ? '● live' : '⚠ stale';
250
- return (_jsxs(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: "\u258C tokens-metric " }), _jsxs(Text, { dimColor: true, children: ["v", pkg.version, " \u2014 real-time Claude Code usage"] })] }), _jsx(Box, { marginTop: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: dot, children: "\u25CF" }), ' ', auth.installed ? 'Claude Code detected' : 'Claude Code NOT detected', _jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { children: sessionsToday }), _jsx(Text, { dimColor: true, children: ` ${plural(sessionsToday, 'session', 'sessions')} · ` }), _jsx(Text, { children: projectsToday }), _jsx(Text, { dimColor: true, children: ` ${plural(projectsToday, 'project', 'projects')} today` })] }) }), _jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: "watching ~/.claude/projects \u00B7 " }), tailStatusText ? _jsxs(Text, { color: tailColor, children: [tailStatusText, " "] }) : null, _jsx(Text, { dimColor: true, children: tailAgo }), _jsx(Text, { dimColor: true, children: ' · uptime ' }), _jsx(Text, { children: timeAgo(now - startedAt) })] }), updateAvailable && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\u26A1 Update available: " }), _jsxs(Text, { dimColor: true, children: ["v", pkg.version] }), _jsx(Text, { color: "yellow", children: " \u2192 " }), _jsxs(Text, { color: "yellow", bold: true, children: ["v", updateAvailable] }), _jsx(Text, { dimColor: true, children: " npm install -g tokens-metric" })] }))] }));
251
+ return (_jsxs(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: "\u258C tokens-metric " }), _jsxs(Text, { dimColor: true, children: ["v", pkg.version, " \u2014 real-time Claude Code usage"] })] }), _jsx(Box, { marginTop: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: dot, children: "\u25CF" }), ' ', auth.installed ? 'Claude Code detected' : 'Claude Code NOT detected', _jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { color: codexDetected ? 'green' : 'red', children: "\u25CF" }), ' ', codexDetected ? 'Codex detected' : 'Codex NOT detected', _jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { children: sessionsToday }), _jsx(Text, { dimColor: true, children: ` ${plural(sessionsToday, 'session', 'sessions')} · ` }), _jsx(Text, { children: projectsToday }), _jsx(Text, { dimColor: true, children: ` ${plural(projectsToday, 'project', 'projects')} today` })] }) }), _jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: "watching ~/.claude/projects \u00B7 " }), tailStatusText ? _jsxs(Text, { color: tailColor, children: [tailStatusText, " "] }) : null, _jsx(Text, { dimColor: true, children: tailAgo }), _jsx(Text, { dimColor: true, children: ' · uptime ' }), _jsx(Text, { children: timeAgo(now - startedAt) })] }), updateAvailable && (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: "\u26A1 Update available: " }), _jsxs(Text, { dimColor: true, children: ["v", pkg.version] }), _jsx(Text, { color: "yellow", children: " \u2192 " }), _jsxs(Text, { color: "yellow", bold: true, children: ["v", updateAvailable] }), _jsx(Text, { dimColor: true, children: " npm install -g tokens-metric" })] }))] }));
251
252
  }
252
253
  function countToday(transcripts, now) {
253
254
  const startOfDay = new Date(now);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokens-metric",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "Real-time token usage meter for Claude Code — statusline + Ink TUI.",
5
5
  "type": "module",
6
6
  "bin": {