tokmon 0.7.0 → 0.8.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +45 -25
  2. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/cli.tsx
4
4
  import { render } from "ink";
5
+ import { MouseProvider as MouseProvider2 } from "@zenobius/ink-mouse";
5
6
 
6
7
  // src/config.ts
7
8
  import { readFile, writeFile, mkdir } from "fs/promises";
@@ -36,6 +37,7 @@ async function saveConfig(config2) {
36
37
  // src/app.tsx
37
38
  import { useState, useEffect, useCallback, useRef } from "react";
38
39
  import { Box, Text, useInput, useStdout, useApp } from "ink";
40
+ import { useMouse } from "@zenobius/ink-mouse";
39
41
 
40
42
  // src/data.ts
41
43
  import { readdir, stat as fsStat } from "fs/promises";
@@ -267,9 +269,10 @@ async function getAccessToken() {
267
269
  }
268
270
  return null;
269
271
  }
272
+ var EMPTY = { session: null, weekly: null, sonnet: null, extraUsage: null, error: null };
270
273
  async function fetchBilling() {
271
274
  const token = await getAccessToken();
272
- if (!token) return null;
275
+ if (!token) return { ...EMPTY, error: "No OAuth token found (macOS Keychain)" };
273
276
  try {
274
277
  const res = await fetch("https://api.anthropic.com/api/oauth/usage", {
275
278
  headers: {
@@ -279,7 +282,9 @@ async function fetchBilling() {
279
282
  },
280
283
  signal: AbortSignal.timeout(1e4)
281
284
  });
282
- if (!res.ok) return null;
285
+ if (res.status === 429) return { ...EMPTY, error: "Rate limited \u2014 retrying in 2m" };
286
+ if (res.status === 401) return { ...EMPTY, error: "Token expired \u2014 restart Claude Code" };
287
+ if (!res.ok) return { ...EMPTY, error: `API ${res.status}` };
283
288
  const data = await res.json();
284
289
  return {
285
290
  session: data.five_hour ? {
@@ -297,10 +302,11 @@ async function fetchBilling() {
297
302
  extraUsage: data.extra_usage?.is_enabled ? {
298
303
  limit: data.extra_usage.monthly_limit / 100,
299
304
  used: data.extra_usage.used_credits / 100
300
- } : null
305
+ } : null,
306
+ error: null
301
307
  };
302
308
  } catch {
303
- return null;
309
+ return { ...EMPTY, error: "Network error" };
304
310
  }
305
311
  }
306
312
  function formatReset(iso) {
@@ -407,7 +413,7 @@ function App({ interval: cliInterval }) {
407
413
  useEffect(() => {
408
414
  let active = true;
409
415
  const load = () => fetchBilling().then((b) => {
410
- if (active && b) setBilling(b);
416
+ if (active) setBilling(b);
411
417
  }).catch(() => {
412
418
  });
413
419
  load();
@@ -454,6 +460,20 @@ function App({ interval: cliInterval }) {
454
460
  setCursor(0);
455
461
  setExpanded(-1);
456
462
  }, []);
463
+ const mouse = useMouse();
464
+ useEffect(() => {
465
+ if (!IS_TTY) return;
466
+ mouse.enable();
467
+ const onScroll = (_pos, dir) => {
468
+ if (tab === 1) {
469
+ setCursor((c) => dir === "scrollup" ? Math.max(0, c - 3) : c + 3);
470
+ }
471
+ };
472
+ mouse.events.on("scroll", onScroll);
473
+ return () => {
474
+ mouse.events.off("scroll", onScroll);
475
+ };
476
+ }, [tab]);
457
477
  useInput((input, key) => {
458
478
  if (showSettings) {
459
479
  if (key.escape || input === "s") setShowSettings(false);
@@ -709,21 +729,21 @@ function DashboardView({ data, billing }) {
709
729
  ]
710
730
  }
711
731
  ),
712
- billing && /* @__PURE__ */ jsxs(Fragment, { children: [
713
- /* @__PURE__ */ jsx(Box, { height: 1 }),
714
- /* @__PURE__ */ jsxs(
715
- Box,
716
- {
717
- flexDirection: "column",
718
- paddingLeft: 1,
719
- borderStyle: "bold",
720
- borderColor: "yellow",
721
- borderRight: false,
722
- borderTop: false,
723
- borderBottom: false,
724
- children: [
725
- /* @__PURE__ */ jsx(Text, { bold: true, children: "Rate Limits" }),
726
- /* @__PURE__ */ jsx(Box, { height: 1 }),
732
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
733
+ /* @__PURE__ */ jsxs(
734
+ Box,
735
+ {
736
+ flexDirection: "column",
737
+ paddingLeft: 1,
738
+ borderStyle: "bold",
739
+ borderColor: billing?.error ? "red" : "yellow",
740
+ borderRight: false,
741
+ borderTop: false,
742
+ borderBottom: false,
743
+ children: [
744
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Rate Limits" }),
745
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
746
+ billing?.error ? /* @__PURE__ */ jsx(Text, { color: "red", children: billing.error }) : billing?.session || billing?.weekly ? /* @__PURE__ */ jsxs(Fragment, { children: [
727
747
  billing.session && /* @__PURE__ */ jsx(LimitBar, { label: "Session", pct: billing.session.utilization, resets: billing.session.resetsAt }),
728
748
  billing.weekly && /* @__PURE__ */ jsx(LimitBar, { label: "Weekly", pct: billing.weekly.utilization, resets: billing.weekly.resetsAt }),
729
749
  billing.sonnet && /* @__PURE__ */ jsx(LimitBar, { label: "Sonnet", pct: billing.sonnet.utilization, resets: billing.sonnet.resetsAt }),
@@ -739,10 +759,10 @@ function DashboardView({ data, billing }) {
739
759
  " limit"
740
760
  ] })
741
761
  ] })
742
- ]
743
- }
744
- )
745
- ] })
762
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Fetching..." })
763
+ ]
764
+ }
765
+ )
746
766
  ] });
747
767
  }
748
768
  function LimitBar({ label, pct, resets }) {
@@ -929,5 +949,5 @@ var config = await loadConfig();
929
949
  if (config.clearScreen && process.stdout.isTTY) {
930
950
  process.stdout.write("\x1B[2J\x1B[H");
931
951
  }
932
- var { waitUntilExit } = render(/* @__PURE__ */ jsx2(App, { interval }));
952
+ var { waitUntilExit } = render(/* @__PURE__ */ jsx2(MouseProvider2, { children: /* @__PURE__ */ jsx2(App, { interval }) }));
933
953
  await waitUntilExit();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokmon",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Terminal dashboard for Claude Code usage and costs",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,7 @@
14
14
  "dev": "tsx src/cli.tsx"
15
15
  },
16
16
  "dependencies": {
17
+ "@zenobius/ink-mouse": "^1.0.3",
17
18
  "ink": "^5.0.0",
18
19
  "react": "^18.0.0"
19
20
  },