tokmon 0.3.1 → 0.3.3
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.
- package/dist/cli.js +62 -53
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,16 +3,49 @@
|
|
|
3
3
|
// src/cli.tsx
|
|
4
4
|
import { render } from "ink";
|
|
5
5
|
|
|
6
|
+
// src/config.ts
|
|
7
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
var DEFAULTS = { interval: 2, clearScreen: true };
|
|
11
|
+
function configDir() {
|
|
12
|
+
if (process.platform === "win32") {
|
|
13
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "tokmon");
|
|
14
|
+
}
|
|
15
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
16
|
+
return join(xdg, "tokmon");
|
|
17
|
+
}
|
|
18
|
+
function configPath() {
|
|
19
|
+
return join(configDir(), "config.json");
|
|
20
|
+
}
|
|
21
|
+
async function loadConfig() {
|
|
22
|
+
try {
|
|
23
|
+
const raw = await readFile(configPath(), "utf-8");
|
|
24
|
+
const parsed = JSON.parse(raw);
|
|
25
|
+
return { ...DEFAULTS, ...parsed };
|
|
26
|
+
} catch {
|
|
27
|
+
return { ...DEFAULTS };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function saveConfig(config2) {
|
|
31
|
+
const dir = configDir();
|
|
32
|
+
await mkdir(dir, { recursive: true });
|
|
33
|
+
await writeFile(configPath(), JSON.stringify(config2, null, 2) + "\n");
|
|
34
|
+
}
|
|
35
|
+
function configLocation() {
|
|
36
|
+
return configPath();
|
|
37
|
+
}
|
|
38
|
+
|
|
6
39
|
// src/app.tsx
|
|
7
40
|
import { useState, useEffect, useRef } from "react";
|
|
8
|
-
import { Box, Text, useInput, useStdout } from "ink";
|
|
41
|
+
import { Box, Text, useInput, useStdout, useApp } from "ink";
|
|
9
42
|
|
|
10
43
|
// src/data.ts
|
|
11
44
|
import { readdir, stat as fsStat } from "fs/promises";
|
|
12
45
|
import { createReadStream } from "fs";
|
|
13
46
|
import { createInterface } from "readline";
|
|
14
|
-
import { join } from "path";
|
|
15
|
-
import { homedir } from "os";
|
|
47
|
+
import { join as join2 } from "path";
|
|
48
|
+
import { homedir as homedir2 } from "os";
|
|
16
49
|
|
|
17
50
|
// src/format.ts
|
|
18
51
|
function currency(value) {
|
|
@@ -56,19 +89,19 @@ var PRICING = {
|
|
|
56
89
|
var FALLBACK = PRICING["claude-opus-4"];
|
|
57
90
|
var fileCache = /* @__PURE__ */ new Map();
|
|
58
91
|
function getClaudeDirs() {
|
|
59
|
-
const home =
|
|
60
|
-
const dirs = [
|
|
92
|
+
const home = homedir2();
|
|
93
|
+
const dirs = [join2(home, ".claude", "projects")];
|
|
61
94
|
if (process.env.XDG_CONFIG_HOME) {
|
|
62
|
-
dirs.push(
|
|
95
|
+
dirs.push(join2(process.env.XDG_CONFIG_HOME, "claude", "projects"));
|
|
63
96
|
} else if (process.platform !== "win32") {
|
|
64
|
-
dirs.push(
|
|
97
|
+
dirs.push(join2(home, ".config", "claude", "projects"));
|
|
65
98
|
}
|
|
66
99
|
if (process.env.APPDATA) {
|
|
67
|
-
dirs.push(
|
|
100
|
+
dirs.push(join2(process.env.APPDATA, "claude", "projects"));
|
|
68
101
|
}
|
|
69
102
|
if (process.env.CLAUDE_CONFIG_DIR) {
|
|
70
103
|
for (const p of process.env.CLAUDE_CONFIG_DIR.split(process.platform === "win32" ? ";" : ",")) {
|
|
71
|
-
dirs.push(
|
|
104
|
+
dirs.push(join2(p.trim(), "projects"));
|
|
72
105
|
}
|
|
73
106
|
}
|
|
74
107
|
return dirs;
|
|
@@ -123,7 +156,7 @@ async function loadEntries(since) {
|
|
|
123
156
|
}
|
|
124
157
|
const files = listing.filter((f) => f.endsWith(".jsonl"));
|
|
125
158
|
await Promise.all(files.map(async (f) => {
|
|
126
|
-
const path =
|
|
159
|
+
const path = join2(dir, f);
|
|
127
160
|
if (seen.has(path)) return;
|
|
128
161
|
seen.add(path);
|
|
129
162
|
try {
|
|
@@ -232,39 +265,6 @@ async function fetchTable() {
|
|
|
232
265
|
};
|
|
233
266
|
}
|
|
234
267
|
|
|
235
|
-
// src/config.ts
|
|
236
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
237
|
-
import { join as join2 } from "path";
|
|
238
|
-
import { homedir as homedir2 } from "os";
|
|
239
|
-
var DEFAULTS = { interval: 2, clearScreen: true };
|
|
240
|
-
function configDir() {
|
|
241
|
-
if (process.platform === "win32") {
|
|
242
|
-
return join2(process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"), "tokmon");
|
|
243
|
-
}
|
|
244
|
-
const xdg = process.env.XDG_CONFIG_HOME ?? join2(homedir2(), ".config");
|
|
245
|
-
return join2(xdg, "tokmon");
|
|
246
|
-
}
|
|
247
|
-
function configPath() {
|
|
248
|
-
return join2(configDir(), "config.json");
|
|
249
|
-
}
|
|
250
|
-
async function loadConfig() {
|
|
251
|
-
try {
|
|
252
|
-
const raw = await readFile(configPath(), "utf-8");
|
|
253
|
-
const parsed = JSON.parse(raw);
|
|
254
|
-
return { ...DEFAULTS, ...parsed };
|
|
255
|
-
} catch {
|
|
256
|
-
return { ...DEFAULTS };
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
async function saveConfig(config) {
|
|
260
|
-
const dir = configDir();
|
|
261
|
-
await mkdir(dir, { recursive: true });
|
|
262
|
-
await writeFile(configPath(), JSON.stringify(config, null, 2) + "\n");
|
|
263
|
-
}
|
|
264
|
-
function configLocation() {
|
|
265
|
-
return configPath();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
268
|
// src/app.tsx
|
|
269
269
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
270
270
|
var TABS = ["Dashboard", "Table"];
|
|
@@ -279,18 +279,17 @@ function App({ interval: cliInterval }) {
|
|
|
279
279
|
const [view, setView] = useState(0);
|
|
280
280
|
const [scroll, setScroll] = useState(0);
|
|
281
281
|
const [showSettings, setShowSettings] = useState(false);
|
|
282
|
-
const [
|
|
282
|
+
const [config2, setConfig] = useState(null);
|
|
283
283
|
const [settingsCursor, setSettingsCursor] = useState(0);
|
|
284
284
|
const tableLoadedOnce = useRef(false);
|
|
285
285
|
const { stdout } = useStdout();
|
|
286
286
|
const rows = stdout?.rows ?? 24;
|
|
287
287
|
const cols = stdout?.columns ?? 80;
|
|
288
|
-
const interval2 = cliInterval ?? (
|
|
288
|
+
const interval2 = cliInterval ?? (config2?.interval ?? 2) * 1e3;
|
|
289
289
|
useEffect(() => {
|
|
290
290
|
loadConfig().then((c) => {
|
|
291
291
|
if (cliInterval) c = { ...c, interval: cliInterval / 1e3 };
|
|
292
292
|
setConfig(c);
|
|
293
|
-
if (c.clearScreen && stdout) stdout.write("\x1B[2J\x1B[H");
|
|
294
293
|
});
|
|
295
294
|
}, []);
|
|
296
295
|
useEffect(() => {
|
|
@@ -347,9 +346,10 @@ function App({ interval: cliInterval }) {
|
|
|
347
346
|
clearInterval(id);
|
|
348
347
|
};
|
|
349
348
|
}, [tab, interval2]);
|
|
349
|
+
const { exit } = useApp();
|
|
350
350
|
const isTTY = process.stdin.isTTY === true;
|
|
351
351
|
const settingsItems = 2;
|
|
352
|
-
const cfg =
|
|
352
|
+
const cfg = config2 ?? { interval: 2, clearScreen: true };
|
|
353
353
|
useInput((input, key) => {
|
|
354
354
|
if (showSettings) {
|
|
355
355
|
if (key.escape || input === "s") setShowSettings(false);
|
|
@@ -380,6 +380,10 @@ function App({ interval: cliInterval }) {
|
|
|
380
380
|
}
|
|
381
381
|
return;
|
|
382
382
|
}
|
|
383
|
+
if (input === "q") {
|
|
384
|
+
exit();
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
383
387
|
if (input === "s") {
|
|
384
388
|
setShowSettings(true);
|
|
385
389
|
return;
|
|
@@ -458,7 +462,7 @@ function App({ interval: cliInterval }) {
|
|
|
458
462
|
showSettings ? /* @__PURE__ */ jsx(SettingsView, { config: cfg, cursor: settingsCursor }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
459
463
|
/* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
|
|
460
464
|
/* @__PURE__ */ jsx(TabBar, { tabs: TABS, active: tab }),
|
|
461
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " Tab
|
|
465
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " Tab/\u2190\u2192" })
|
|
462
466
|
] }),
|
|
463
467
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
464
468
|
tab === 0 && /* @__PURE__ */ jsx(DashboardView, { data: dashboard }),
|
|
@@ -473,7 +477,8 @@ function App({ interval: cliInterval }) {
|
|
|
473
477
|
/* @__PURE__ */ jsx(Text, { children: "David Ilie" }),
|
|
474
478
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " (" }),
|
|
475
479
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "davidilie.com" }),
|
|
476
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ")" })
|
|
480
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: ") \xB7 " }),
|
|
481
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "s=settings q=quit" })
|
|
477
482
|
] })
|
|
478
483
|
] });
|
|
479
484
|
}
|
|
@@ -498,7 +503,7 @@ function ViewBar({ views, active }) {
|
|
|
498
503
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " d/w/m or \u2190\u2192" })
|
|
499
504
|
] });
|
|
500
505
|
}
|
|
501
|
-
function SettingsView({ config, cursor }) {
|
|
506
|
+
function SettingsView({ config: config2, cursor }) {
|
|
502
507
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
503
508
|
/* @__PURE__ */ jsx(Text, { bold: true, children: "Settings" }),
|
|
504
509
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: configLocation() }),
|
|
@@ -514,7 +519,7 @@ function SettingsView({ config, cursor }) {
|
|
|
514
519
|
" "
|
|
515
520
|
] }),
|
|
516
521
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", children: [
|
|
517
|
-
|
|
522
|
+
config2.interval,
|
|
518
523
|
"s"
|
|
519
524
|
] }),
|
|
520
525
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -528,7 +533,7 @@ function SettingsView({ config, cursor }) {
|
|
|
528
533
|
" "
|
|
529
534
|
] }),
|
|
530
535
|
/* @__PURE__ */ jsx(Text, { children: "Clear screen " }),
|
|
531
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color:
|
|
536
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: config2.clearScreen ? "green" : "red", children: config2.clearScreen ? "on" : "off" })
|
|
532
537
|
] }),
|
|
533
538
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
534
539
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 select \u2190\u2192 adjust s/Esc close" })
|
|
@@ -717,9 +722,13 @@ for (let i = 0; i < args.length; i++) {
|
|
|
717
722
|
console.log(" \u2191\u2193 Scroll table");
|
|
718
723
|
console.log(" 1-2 Jump to view");
|
|
719
724
|
console.log(" s Settings");
|
|
720
|
-
console.log("
|
|
725
|
+
console.log(" q Quit");
|
|
721
726
|
process.exit(0);
|
|
722
727
|
}
|
|
723
728
|
}
|
|
729
|
+
var config = await loadConfig();
|
|
730
|
+
if (config.clearScreen && process.stdout.isTTY) {
|
|
731
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
732
|
+
}
|
|
724
733
|
var { waitUntilExit } = render(/* @__PURE__ */ jsx2(App, { interval }));
|
|
725
734
|
await waitUntilExit();
|