claude-session-dashboard 0.4.3 → 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.
Files changed (38) hide show
  1. package/dist/client/assets/_dashboard-Job6DOd1.js +1 -0
  2. package/dist/client/assets/_sessionId-CIFXqjVa.js +12 -0
  3. package/dist/client/assets/app-CkRVT69z.css +1 -0
  4. package/dist/client/assets/{createServerFn-BYTDoNe-.js → createServerFn-6SJrpRCO.js} +1 -1
  5. package/dist/client/assets/index-DDr2smLW.js +1 -0
  6. package/dist/client/assets/main-B6FohBFQ.js +69 -0
  7. package/dist/client/assets/sessions.queries-ClgzoOt4.js +1 -0
  8. package/dist/client/assets/settings-DQD2EaIq.js +1 -0
  9. package/dist/client/assets/{settings.types-CMYAW0cQ.js → settings.types-LYd9Z8Y1.js} +1 -1
  10. package/dist/client/assets/stats-CrWQ_y2R.js +4 -0
  11. package/dist/client/assets/{useSessionCost-BBu3AmcX.js → useSessionCost-Drt0v6oj.js} +1 -1
  12. package/dist/server/assets/{_dashboard-TUzgwLqB.js → _dashboard-61fpMMMe.js} +59 -33
  13. package/dist/server/assets/{_sessionId-DyFxvcBN.js → _sessionId-B_O50OfN.js} +17 -17
  14. package/dist/server/assets/_tanstack-start-manifest_v-Dva5sIpS.js +4 -0
  15. package/dist/server/assets/app-info.api-CdaWsxHl.js +40 -0
  16. package/dist/server/assets/{index-Bx7vBs4O.js → index-BYcFI9Ho.js} +6 -6
  17. package/dist/server/assets/{project-analytics.server-kTooOGl-.js → project-analytics.api-QnhRRs7T.js} +2 -2
  18. package/dist/server/assets/{router-Cd4jLk4T.js → router-BvYNknMb.js} +80 -12
  19. package/dist/server/assets/{session-detail.server-CO5XwLSv.js → session-detail.api-8plxSeB0.js} +2 -2
  20. package/dist/server/assets/{sessions.server-CTeIkXCV.js → sessions.api-DRmOjipJ.js} +6 -6
  21. package/dist/server/assets/{sessions.queries-B5ZBiVJy.js → sessions.queries-CvAnVbE8.js} +3 -3
  22. package/dist/server/assets/{settings-KKaz1ty7.js → settings-Ct2BZGxb.js} +33 -5
  23. package/dist/server/assets/{settings.server-6B2PvLgf.js → settings.api-C9L2GoIE.js} +4 -4
  24. package/dist/server/assets/{settings.queries-DSQd324O.js → settings.queries-BVEZA-1G.js} +2 -2
  25. package/dist/server/assets/{stats-Bsrkajci.js → stats-CZEpvzmd.js} +51 -37
  26. package/dist/server/assets/{stats.server-iJ_z7eUN.js → stats.api-CH-wTCGE.js} +2 -2
  27. package/dist/server/assets/{useSessionCost-CYs5UOX-.js → useSessionCost-CyWBuljV.js} +1 -1
  28. package/dist/server/server.js +39 -25
  29. package/package.json +4 -1
  30. package/dist/client/assets/_dashboard-t702m22X.js +0 -1
  31. package/dist/client/assets/_sessionId-D4Tpmmb5.js +0 -12
  32. package/dist/client/assets/app-DREGBD44.css +0 -1
  33. package/dist/client/assets/index-DnK_zh3s.js +0 -1
  34. package/dist/client/assets/main-CV28H4XG.js +0 -56
  35. package/dist/client/assets/sessions.queries-tzrs5GhP.js +0 -1
  36. package/dist/client/assets/settings-D8yv1q93.js +0 -1
  37. package/dist/client/assets/stats-C_6E4jyb.js +0 -4
  38. package/dist/server/assets/_tanstack-start-manifest_v-Bzp9kpGN.js +0 -4
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useMatches, Link, Outlet } from "@tanstack/react-router";
3
- import { useQuery } from "@tanstack/react-query";
4
- import { a as activeSessionsQuery } from "./sessions.queries-B5ZBiVJy.js";
5
- import "./createSsrRpc-CVg2UDl0.js";
6
- import "../server.js";
3
+ import { useQuery, queryOptions } from "@tanstack/react-query";
4
+ import { a as activeSessionsQuery } from "./sessions.queries-CvAnVbE8.js";
5
+ import { c as createSsrRpc } from "./createSsrRpc-CVg2UDl0.js";
6
+ import { c as createServerFn } from "../server.js";
7
+ import "zod";
7
8
  import "@tanstack/history";
8
9
  import "@tanstack/router-core/ssr/client";
9
10
  import "@tanstack/router-core";
@@ -13,13 +14,22 @@ import "h3-v2";
13
14
  import "tiny-invariant";
14
15
  import "seroval";
15
16
  import "@tanstack/react-router/ssr/server";
16
- import "zod";
17
17
  function ActiveSessionsBadge() {
18
18
  const { data: activeSessions } = useQuery(activeSessionsQuery);
19
19
  const count = activeSessions?.length ?? 0;
20
20
  if (count === 0) return null;
21
21
  return /* @__PURE__ */ jsx("span", { className: "ml-auto rounded-full bg-emerald-500/20 px-1.5 py-0.5 text-[10px] font-medium text-emerald-400", children: count });
22
22
  }
23
+ const getAppInfo = createServerFn({
24
+ method: "GET"
25
+ }).handler(createSsrRpc("04ac41a7e3e644815167d098c2d6c3375d00a72a11e5af0d37033ba771081ba9"));
26
+ const appInfoQuery = queryOptions({
27
+ queryKey: ["app-info"],
28
+ queryFn: () => getAppInfo(),
29
+ staleTime: Infinity,
30
+ // Version and path never change at runtime
31
+ refetchOnWindowFocus: false
32
+ });
23
33
  const NAV_ITEMS = [
24
34
  {
25
35
  to: "/sessions",
@@ -51,9 +61,10 @@ const NAV_ITEMS = [
51
61
  function AppShell({ children }) {
52
62
  const matches = useMatches();
53
63
  const currentPath = matches[matches.length - 1]?.pathname ?? "";
64
+ const { data: appInfo } = useQuery(appInfoQuery);
54
65
  return /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen", children: [
55
66
  /* @__PURE__ */ jsxs("aside", { className: "flex w-56 shrink-0 flex-col border-r border-gray-800 bg-gray-950", children: [
56
- /* @__PURE__ */ jsx("div", { className: "flex h-14 items-center border-b border-gray-800 px-4", children: /* @__PURE__ */ jsxs(Link, { to: "/sessions", className: "text-sm font-bold text-white", children: [
67
+ /* @__PURE__ */ jsx("div", { className: "flex h-14 items-center border-b border-gray-800 px-4", children: /* @__PURE__ */ jsxs(Link, { to: "/sessions", className: "text-sm font-bold text-gray-100", children: [
57
68
  /* @__PURE__ */ jsx("span", { className: "text-brand-500", children: "Claude" }),
58
69
  " Dashboard"
59
70
  ] }) }),
@@ -63,7 +74,7 @@ function AppShell({ children }) {
63
74
  Link,
64
75
  {
65
76
  to: item.to,
66
- className: `flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors ${isActive ? "bg-gray-800 text-white" : "text-gray-400 hover:bg-gray-800/50 hover:text-gray-200"}`,
77
+ className: `flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors ${isActive ? "bg-gray-800 text-gray-100" : "text-gray-400 hover:bg-gray-900 hover:text-gray-200"}`,
67
78
  children: [
68
79
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: item.icon }),
69
80
  item.label,
@@ -73,33 +84,48 @@ function AppShell({ children }) {
73
84
  item.to
74
85
  );
75
86
  }) }),
76
- /* @__PURE__ */ jsx("div", { className: "border-t border-gray-800 p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
77
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
78
- /* @__PURE__ */ jsx(
79
- "a",
80
- {
81
- href: "https://github.com/dlupiak/claude-session-dashboard",
82
- target: "_blank",
83
- rel: "noopener noreferrer",
84
- className: "text-gray-500 hover:text-gray-300 transition-colors",
85
- title: "GitHub Repository",
86
- children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" }) })
87
- }
88
- ),
89
- /* @__PURE__ */ jsx(
90
- "a",
91
- {
92
- href: "https://www.npmjs.com/package/claude-session-dashboard",
93
- target: "_blank",
94
- rel: "noopener noreferrer",
95
- className: "text-gray-500 hover:text-gray-300 transition-colors",
96
- title: "npm Package",
97
- children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M0 0v16h16V0H0zm13 13H8V5H5v8H3V3h10v10z" }) })
98
- }
99
- )
87
+ /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-800 p-3 space-y-3", children: [
88
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
89
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
90
+ /* @__PURE__ */ jsx(
91
+ "a",
92
+ {
93
+ href: "https://github.com/dlupiak/claude-session-dashboard",
94
+ target: "_blank",
95
+ rel: "noopener noreferrer",
96
+ className: "text-gray-500 hover:text-gray-300 transition-colors",
97
+ title: "GitHub Repository",
98
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" }) })
99
+ }
100
+ ),
101
+ /* @__PURE__ */ jsx(
102
+ "a",
103
+ {
104
+ href: "https://www.npmjs.com/package/claude-session-dashboard",
105
+ target: "_blank",
106
+ rel: "noopener noreferrer",
107
+ className: "text-gray-500 hover:text-gray-300 transition-colors",
108
+ title: "npm Package",
109
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M0 0v16h16V0H0zm13 13H8V5H5v8H3V3h10v10z" }) })
110
+ }
111
+ )
112
+ ] }),
113
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: "Read-only" })
100
114
  ] }),
101
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600", children: "Read-only" })
102
- ] }) })
115
+ appInfo && /* @__PURE__ */ jsxs(
116
+ "p",
117
+ {
118
+ className: "mt-1.5 truncate text-[10px] text-gray-500",
119
+ title: `v${appInfo.version} · ${appInfo.appPath}`,
120
+ children: [
121
+ "v",
122
+ appInfo.version,
123
+ " · ",
124
+ appInfo.appPath
125
+ ]
126
+ }
127
+ )
128
+ ] })
103
129
  ] }),
104
130
  /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-5xl px-6 py-6", children }) })
105
131
  ] });
@@ -7,10 +7,10 @@ import { useRef, useCallback, useState, useEffect, useMemo } from "react";
7
7
  import { format } from "date-fns";
8
8
  import { a as formatDuration, f as formatTokenCount, e as formatDateTime, c as formatUSD } from "./format-DIZHV7IJ.js";
9
9
  import { ResponsiveContainer, AreaChart, YAxis, Tooltip, ReferenceLine, Area } from "recharts";
10
- import { s as settingsQuery } from "./settings.queries-DSQd324O.js";
11
- import { g as getMergedPricing, c as calculateSessionCost, u as useSessionCost, E as ExportDropdown, d as downloadFile, e as sessionToJSON } from "./useSessionCost-CYs5UOX-.js";
12
- import { a as activeSessionsQuery } from "./sessions.queries-B5ZBiVJy.js";
13
- import { b as Route, u as usePrivacy } from "./router-Cd4jLk4T.js";
10
+ import { s as settingsQuery } from "./settings.queries-BVEZA-1G.js";
11
+ import { g as getMergedPricing, c as calculateSessionCost, u as useSessionCost, E as ExportDropdown, d as downloadFile, e as sessionToJSON } from "./useSessionCost-CyWBuljV.js";
12
+ import { a as activeSessionsQuery } from "./sessions.queries-CvAnVbE8.js";
13
+ import { c as Route, u as usePrivacy } from "./router-BvYNknMb.js";
14
14
  import "@tanstack/history";
15
15
  import "@tanstack/router-core/ssr/client";
16
16
  import "@tanstack/router-core";
@@ -24,7 +24,7 @@ import "./settings.types-DntadCHo.js";
24
24
  import "zod";
25
25
  const getSessionDetail = createServerFn({
26
26
  method: "GET"
27
- }).inputValidator((input) => input).handler(createSsrRpc("ff8a3161afdfa175e9c519e4146a56ab5bce6e80745e99cfc2191ebbb7a859bb"));
27
+ }).inputValidator((input) => input).handler(createSsrRpc("71794080473579a94431392ab409ebd02772f6a9f6a08386cadbb8c0d3cf804a"));
28
28
  function sessionDetailQuery(sessionId, projectPath, isActive) {
29
29
  return queryOptions({
30
30
  queryKey: ["session", "detail", sessionId],
@@ -305,7 +305,7 @@ function TimelineChart({ data, width, onHover }) {
305
305
  y1: TOP_MARGIN - 4,
306
306
  x2: chartWidth - RIGHT_MARGIN,
307
307
  y2: TOP_MARGIN - 4,
308
- stroke: "#374151",
308
+ stroke: "var(--color-gray-700)",
309
309
  strokeWidth: 1
310
310
  }
311
311
  ),
@@ -317,7 +317,7 @@ function TimelineChart({ data, width, onHover }) {
317
317
  y1: TOP_MARGIN - 8,
318
318
  x2: tick.x,
319
319
  y2: TOP_MARGIN - 4,
320
- stroke: "#4b5563",
320
+ stroke: "var(--color-gray-600)",
321
321
  strokeWidth: 1
322
322
  }
323
323
  ),
@@ -348,7 +348,7 @@ function TimelineChart({ data, width, onHover }) {
348
348
  y1: mainLaneY + LANE_HEIGHT / 2,
349
349
  x2: chartWidth - RIGHT_MARGIN,
350
350
  y2: mainLaneY + LANE_HEIGHT / 2,
351
- stroke: "#1f2937",
351
+ stroke: "var(--color-gray-800)",
352
352
  strokeWidth: 1,
353
353
  strokeDasharray: "2,4"
354
354
  }
@@ -405,7 +405,7 @@ function TimelineChart({ data, width, onHover }) {
405
405
  y1: skillRowY + LANE_HEIGHT / 2,
406
406
  x2: chartWidth - RIGHT_MARGIN,
407
407
  y2: skillRowY + LANE_HEIGHT / 2,
408
- stroke: "#1f2937",
408
+ stroke: "var(--color-gray-800)",
409
409
  strokeWidth: 1,
410
410
  strokeDasharray: "2,4"
411
411
  }
@@ -457,7 +457,7 @@ function TimelineChart({ data, width, onHover }) {
457
457
  y1: errorRowY + LANE_HEIGHT / 2,
458
458
  x2: chartWidth - RIGHT_MARGIN,
459
459
  y2: errorRowY + LANE_HEIGHT / 2,
460
- stroke: "#1f2937",
460
+ stroke: "var(--color-gray-800)",
461
461
  strokeWidth: 1,
462
462
  strokeDasharray: "2,4"
463
463
  }
@@ -908,7 +908,7 @@ function ContextWindowPanel({ contextWindow, tokens }) {
908
908
  /* @__PURE__ */ jsx("span", { className: "rounded bg-gray-800 px-1.5 py-0.5 text-[10px] font-mono text-gray-400", children: shortModel })
909
909
  ] }),
910
910
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-baseline gap-1", children: [
911
- /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-white", children: formatTokenCount(currentContextSize) }),
911
+ /* @__PURE__ */ jsx("span", { className: "text-2xl font-bold text-gray-100", children: formatTokenCount(currentContextSize) }),
912
912
  /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-500", children: [
913
913
  "/ ",
914
914
  formatTokenCount(contextLimit)
@@ -1032,8 +1032,8 @@ function ContextWindowPanel({ contextWindow, tokens }) {
1032
1032
  Tooltip,
1033
1033
  {
1034
1034
  contentStyle: {
1035
- background: "#1c1c1a",
1036
- border: "1px solid #3d3b36",
1035
+ background: "var(--color-gray-900)",
1036
+ border: "1px solid var(--color-gray-700)",
1037
1037
  borderRadius: "8px",
1038
1038
  fontSize: "11px"
1039
1039
  },
@@ -1155,7 +1155,7 @@ function TokenFallback({ tokens }) {
1155
1155
  ];
1156
1156
  return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-gray-800 bg-gray-900/50 p-4", children: [
1157
1157
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-300", children: "Token Usage" }),
1158
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-2xl font-bold text-white", children: formatTokenCount(activeTotal) }),
1158
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-2xl font-bold text-gray-100", children: formatTokenCount(activeTotal) }),
1159
1159
  /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-gray-500", children: [
1160
1160
  "input + output (",
1161
1161
  formatTokenCount(allTotal),
@@ -1336,7 +1336,7 @@ function SkillInvocationsPanel({
1336
1336
  ] }),
1337
1337
  /* @__PURE__ */ jsx("div", { className: "mt-3 space-y-1", children: groups.map((group) => /* @__PURE__ */ jsxs("div", { className: "rounded bg-gray-950/40 px-2 py-1.5", children: [
1338
1338
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1339
- /* @__PURE__ */ jsxs("span", { className: "shrink-0 rounded bg-amber-500/20 px-1.5 py-0.5 text-[10px] font-semibold text-amber-300", children: [
1339
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0 rounded bg-brand-500/20 px-1.5 py-0.5 text-[10px] font-semibold text-brand-400", children: [
1340
1340
  "/",
1341
1341
  group.skill
1342
1342
  ] }),
@@ -1425,7 +1425,7 @@ function CostEstimationPanel({ tokensByModel }) {
1425
1425
  return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-gray-800 bg-gray-900/50 p-4", children: [
1426
1426
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1427
1427
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-300", children: "Cost Estimation" }),
1428
- /* @__PURE__ */ jsxs("span", { className: "font-mono text-lg font-bold text-white", children: [
1428
+ /* @__PURE__ */ jsxs("span", { className: "font-mono text-lg font-bold text-gray-100", children: [
1429
1429
  "~",
1430
1430
  formatUSD(cost.totalUSD)
1431
1431
  ] })
@@ -1581,7 +1581,7 @@ function SessionDetailPage() {
1581
1581
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
1582
1582
  /* @__PURE__ */ jsxs("div", { children: [
1583
1583
  /* @__PURE__ */ jsx(Link, { to: "/sessions", className: "text-xs text-gray-500 hover:text-gray-300", children: "← Sessions" }),
1584
- /* @__PURE__ */ jsx("h1", { className: "mt-1 text-xl font-bold text-white", children: privacyMode ? anonymizeProjectName(detail.projectName) : detail.projectName }),
1584
+ /* @__PURE__ */ jsx("h1", { className: "mt-1 text-xl font-bold text-gray-100", children: privacyMode ? anonymizeProjectName(detail.projectName) : detail.projectName }),
1585
1585
  /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-3 text-xs text-gray-400", children: [
1586
1586
  detail.branch && /* @__PURE__ */ jsx("span", { className: "font-mono", children: anonymizeBranch(detail.branch) }),
1587
1587
  startedAt && /* @__PURE__ */ jsx("span", { children: formatDateTime(startedAt) }),
@@ -0,0 +1,4 @@
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/__root.tsx", "children": ["/", "/_dashboard"], "preloads": ["/assets/main-B6FohBFQ.js"], "assets": [] }, "/": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/index.tsx" }, "/_dashboard": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/_dashboard.tsx", "children": ["/_dashboard/settings", "/_dashboard/stats", "/_dashboard/sessions/$sessionId", "/_dashboard/sessions/"], "assets": [], "preloads": ["/assets/_dashboard-Job6DOd1.js", "/assets/createServerFn-6SJrpRCO.js", "/assets/sessions.queries-ClgzoOt4.js"] }, "/_dashboard/settings": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/_dashboard/settings.tsx", "assets": [], "preloads": ["/assets/settings-DQD2EaIq.js", "/assets/settings.types-LYd9Z8Y1.js"] }, "/_dashboard/stats": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/_dashboard/stats.tsx", "assets": [], "preloads": ["/assets/stats-CrWQ_y2R.js", "/assets/format-Bsprb3az.js", "/assets/useSessionCost-Drt0v6oj.js", "/assets/settings.types-LYd9Z8Y1.js"] }, "/_dashboard/sessions/$sessionId": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/_dashboard/sessions/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-CIFXqjVa.js", "/assets/format-Bsprb3az.js", "/assets/useSessionCost-Drt0v6oj.js", "/assets/settings.types-LYd9Z8Y1.js"] }, "/_dashboard/sessions/": { "filePath": "/home/runner/work/claude-session-dashboard/claude-session-dashboard/apps/web/src/routes/_dashboard/sessions/index.tsx", "assets": [], "preloads": ["/assets/index-DDr2smLW.js", "/assets/format-Bsprb3az.js"] } }, "clientEntry": "/assets/main-B6FohBFQ.js" });
2
+ export {
3
+ tsrStartManifest
4
+ };
@@ -0,0 +1,40 @@
1
+ import { c as createServerRpc } from "./createServerRpc-Bd3B-Ah9.js";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { c as createServerFn } from "../server.js";
5
+ import "@tanstack/history";
6
+ import "@tanstack/router-core/ssr/client";
7
+ import "@tanstack/router-core";
8
+ import "node:async_hooks";
9
+ import "@tanstack/router-core/ssr/server";
10
+ import "h3-v2";
11
+ import "tiny-invariant";
12
+ import "seroval";
13
+ import "react/jsx-runtime";
14
+ import "@tanstack/react-router/ssr/server";
15
+ import "@tanstack/react-router";
16
+ const getAppInfo_createServerFn_handler = createServerRpc({
17
+ id: "04ac41a7e3e644815167d098c2d6c3375d00a72a11e5af0d37033ba771081ba9",
18
+ name: "getAppInfo",
19
+ filename: "src/features/settings/app-info.api.ts"
20
+ }, (opts) => getAppInfo.__executeServer(opts));
21
+ const getAppInfo = createServerFn({
22
+ method: "GET"
23
+ }).handler(getAppInfo_createServerFn_handler, async () => {
24
+ let version = "unknown";
25
+ try {
26
+ const pkgPath = path.resolve(process.cwd(), "package.json");
27
+ const raw = fs.readFileSync(pkgPath, "utf-8");
28
+ const pkg = JSON.parse(raw);
29
+ version = pkg.version ?? "unknown";
30
+ } catch {
31
+ }
32
+ return {
33
+ version,
34
+ appPath: process.cwd(),
35
+ nodeEnv: "production"
36
+ };
37
+ });
38
+ export {
39
+ getAppInfo_createServerFn_handler
40
+ };
@@ -2,9 +2,9 @@ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useState, useEffect, useRef, useCallback, useMemo } from "react";
3
3
  import { useQuery } from "@tanstack/react-query";
4
4
  import { Link, useNavigate } from "@tanstack/react-router";
5
- import { p as paginatedSessionListQuery, a as activeSessionsQuery } from "./sessions.queries-B5ZBiVJy.js";
5
+ import { p as paginatedSessionListQuery, a as activeSessionsQuery } from "./sessions.queries-CvAnVbE8.js";
6
6
  import { a as formatDuration, b as formatRelativeTime, d as formatBytes } from "./format-DIZHV7IJ.js";
7
- import { u as usePrivacy, a as Route } from "./router-Cd4jLk4T.js";
7
+ import { u as usePrivacy, b as Route } from "./router-BvYNknMb.js";
8
8
  import "./createSsrRpc-CVg2UDl0.js";
9
9
  import "../server.js";
10
10
  import "@tanstack/history";
@@ -61,7 +61,7 @@ function SessionCard({ session }) {
61
61
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
62
62
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
63
63
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
64
- /* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-semibold text-white", children: displayName }),
64
+ /* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-semibold text-gray-100", children: displayName }),
65
65
  /* @__PURE__ */ jsx(StatusBadge, { isActive: session.isActive })
66
66
  ] }),
67
67
  displayBranch && /* @__PURE__ */ jsx("p", { className: "mt-1 truncate text-xs text-gray-500", children: /* @__PURE__ */ jsx("span", { className: "font-mono", children: displayBranch }) })
@@ -137,7 +137,7 @@ function SessionFilters({ projects, activeCount }) {
137
137
  "button",
138
138
  {
139
139
  onClick: () => handleStatusChange(s),
140
- className: `px-3 py-1.5 capitalize transition-colors ${status === s ? "bg-gray-700 text-white" : "text-gray-400 hover:text-gray-200"} ${s === "all" ? "rounded-l-lg" : ""} ${s === "completed" ? "rounded-r-lg" : ""}`,
140
+ className: `px-3 py-1.5 capitalize transition-colors ${status === s ? "bg-gray-700 text-gray-100" : "text-gray-400 hover:text-gray-200"} ${s === "all" ? "rounded-l-lg" : ""} ${s === "completed" ? "rounded-r-lg" : ""}`,
141
141
  children: [
142
142
  s,
143
143
  s === "active" && activeCount > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-1 text-emerald-400", children: [
@@ -256,7 +256,7 @@ function PaginationControls({
256
256
  "button",
257
257
  {
258
258
  onClick: () => onPageChange(item),
259
- className: `min-w-[2rem] rounded-lg px-2 py-1.5 text-xs font-mono transition-colors ${item === page ? "bg-brand-600 text-white" : "border border-gray-700 bg-gray-800 text-gray-400 hover:bg-gray-700 hover:text-gray-200"}`,
259
+ className: `min-w-[2rem] rounded-lg px-2 py-1.5 text-xs font-mono transition-colors ${item === page ? "bg-brand-600 text-gray-100" : "border border-gray-700 bg-gray-800 text-gray-400 hover:bg-gray-700 hover:text-gray-200"}`,
260
260
  children: item
261
261
  },
262
262
  item
@@ -367,7 +367,7 @@ function SessionList() {
367
367
  }
368
368
  function SessionsPage() {
369
369
  return /* @__PURE__ */ jsxs("div", { children: [
370
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-white", children: "Sessions" }),
370
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-gray-100", children: "Sessions" }),
371
371
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-400", children: "All Claude Code sessions from ~/.claude" }),
372
372
  /* @__PURE__ */ jsx("div", { className: "mt-6", children: /* @__PURE__ */ jsx(SessionList, {}) })
373
373
  ] });
@@ -45,9 +45,9 @@ function aggregateProjectAnalytics(allSessions) {
45
45
  };
46
46
  }
47
47
  const getProjectAnalytics_createServerFn_handler = createServerRpc({
48
- id: "64052f224a1d6696436e5d3deeee2b798f0742e1292ffabd038c3a7bf75e6fcb",
48
+ id: "39e65590d2bc41f653f54a9b6a9e0a72f185da275304c0a4a595d811cf185572",
49
49
  name: "getProjectAnalytics",
50
- filename: "src/features/project-analytics/project-analytics.server.ts"
50
+ filename: "src/features/project-analytics/project-analytics.api.ts"
51
51
  }, (opts) => getProjectAnalytics.__executeServer(opts));
52
52
  const getProjectAnalytics = createServerFn({
53
53
  method: "GET"
@@ -1,7 +1,7 @@
1
1
  import { createRootRoute, Outlet, HeadContent, Scripts, createFileRoute, lazyRouteComponent, redirect, createRouter } from "@tanstack/react-router";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
4
- import { useState, useRef, useCallback, createContext, useContext } from "react";
4
+ import { useState, useRef, useCallback, createContext, useContext, useEffect, useMemo } from "react";
5
5
  import { z } from "zod";
6
6
  const OS_USERNAME_PATTERN = /^(\/(?:Users|home))\/[^/]+/;
7
7
  function anonymizePath(path, anonymizedProjectName) {
@@ -96,7 +96,57 @@ function usePrivacy() {
96
96
  }
97
97
  return ctx;
98
98
  }
99
- const appCss = "/assets/app-DREGBD44.css";
99
+ const THEME_STORAGE_KEY = "csd-theme";
100
+ const ThemeContext = createContext(null);
101
+ function getInitialTheme() {
102
+ if (typeof window === "undefined") return "dark";
103
+ const stored = window.localStorage.getItem(THEME_STORAGE_KEY);
104
+ if (stored === "light" || stored === "dark") {
105
+ return stored;
106
+ }
107
+ const prefersDark = window.matchMedia?.("(prefers-color-scheme: dark)").matches;
108
+ return prefersDark ? "dark" : "light";
109
+ }
110
+ function ThemeProvider({ children }) {
111
+ const [theme, setTheme] = useState(getInitialTheme);
112
+ useEffect(() => {
113
+ const root = document.documentElement;
114
+ root.setAttribute("data-theme", theme);
115
+ window.localStorage.setItem(THEME_STORAGE_KEY, theme);
116
+ const metaTheme = document.querySelector('meta[name="theme-color"]');
117
+ if (metaTheme) {
118
+ metaTheme.setAttribute("content", theme === "dark" ? "#141413" : "#f5f3ec");
119
+ }
120
+ }, [theme]);
121
+ useEffect(() => {
122
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
123
+ const listener = (event) => {
124
+ const stored = window.localStorage.getItem(THEME_STORAGE_KEY);
125
+ if (stored !== "light" && stored !== "dark") {
126
+ setTheme(event.matches ? "dark" : "light");
127
+ }
128
+ };
129
+ media.addEventListener("change", listener);
130
+ return () => media.removeEventListener("change", listener);
131
+ }, []);
132
+ const value = useMemo(
133
+ () => ({
134
+ theme,
135
+ toggleTheme: () => setTheme((prev) => prev === "dark" ? "light" : "dark"),
136
+ setTheme
137
+ }),
138
+ [theme]
139
+ );
140
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
141
+ }
142
+ function useTheme() {
143
+ const ctx = useContext(ThemeContext);
144
+ if (!ctx) {
145
+ throw new Error("useTheme must be used within a ThemeProvider");
146
+ }
147
+ return ctx;
148
+ }
149
+ const appCss = "/assets/app-CkRVT69z.css";
100
150
  const queryClient = new QueryClient({
101
151
  defaultOptions: {
102
152
  queries: {
@@ -125,18 +175,35 @@ const Route$6 = createRootRoute({
125
175
  component: RootComponent
126
176
  });
127
177
  function RootComponent() {
128
- return /* @__PURE__ */ jsx(RootDocument, { children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(PrivacyProvider, { children: /* @__PURE__ */ jsx(Outlet, {}) }) }) });
178
+ return /* @__PURE__ */ jsx(RootDocument, { children: /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(PrivacyProvider, { children: /* @__PURE__ */ jsx(Outlet, {}) }) }) }) });
129
179
  }
180
+ const themeInitScript = `
181
+ (() => {
182
+ try {
183
+ const stored = localStorage.getItem('csd-theme');
184
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
185
+ const theme = stored === 'light' || stored === 'dark' ? stored : (prefersDark ? 'dark' : 'light');
186
+ document.documentElement.setAttribute('data-theme', theme);
187
+ const meta = document.querySelector('meta[name="theme-color"]');
188
+ if (meta) meta.setAttribute('content', theme === 'dark' ? '#141413' : '#f5f3ec');
189
+ } catch (e) {
190
+ document.documentElement.setAttribute('data-theme', 'dark');
191
+ }
192
+ })();
193
+ `;
130
194
  function RootDocument({ children }) {
131
195
  return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
132
- /* @__PURE__ */ jsx("head", { children: /* @__PURE__ */ jsx(HeadContent, {}) }),
133
- /* @__PURE__ */ jsxs("body", { className: "bg-gray-950 text-gray-100 antialiased", children: [
196
+ /* @__PURE__ */ jsxs("head", { children: [
197
+ /* @__PURE__ */ jsx(HeadContent, {}),
198
+ /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: themeInitScript } })
199
+ ] }),
200
+ /* @__PURE__ */ jsxs("body", { className: "antialiased", children: [
134
201
  children,
135
202
  /* @__PURE__ */ jsx(Scripts, {})
136
203
  ] })
137
204
  ] });
138
205
  }
139
- const $$splitComponentImporter$4 = () => import("./_dashboard-TUzgwLqB.js");
206
+ const $$splitComponentImporter$4 = () => import("./_dashboard-61fpMMMe.js");
140
207
  const Route$5 = createFileRoute("/_dashboard")({
141
208
  component: lazyRouteComponent($$splitComponentImporter$4, "component")
142
209
  });
@@ -145,7 +212,7 @@ const Route$4 = createFileRoute("/")({
145
212
  throw redirect({ to: "/sessions" });
146
213
  }
147
214
  });
148
- const $$splitComponentImporter$3 = () => import("./stats-Bsrkajci.js");
215
+ const $$splitComponentImporter$3 = () => import("./stats-CZEpvzmd.js");
149
216
  const statsSearchSchema = z.object({
150
217
  tab: z.enum(["overview", "projects"]).default("overview").catch("overview")
151
218
  });
@@ -153,11 +220,11 @@ const Route$3 = createFileRoute("/_dashboard/stats")({
153
220
  validateSearch: statsSearchSchema,
154
221
  component: lazyRouteComponent($$splitComponentImporter$3, "component")
155
222
  });
156
- const $$splitComponentImporter$2 = () => import("./settings-KKaz1ty7.js");
223
+ const $$splitComponentImporter$2 = () => import("./settings-Ct2BZGxb.js");
157
224
  const Route$2 = createFileRoute("/_dashboard/settings")({
158
225
  component: lazyRouteComponent($$splitComponentImporter$2, "component")
159
226
  });
160
- const $$splitComponentImporter$1 = () => import("./index-Bx7vBs4O.js");
227
+ const $$splitComponentImporter$1 = () => import("./index-BYcFI9Ho.js");
161
228
  const sessionsSearchSchema = z.object({
162
229
  page: z.number().int().min(1).default(1).catch(1),
163
230
  pageSize: z.number().int().min(5).max(100).default(5).catch(5),
@@ -169,7 +236,7 @@ const Route$1 = createFileRoute("/_dashboard/sessions/")({
169
236
  validateSearch: sessionsSearchSchema,
170
237
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
171
238
  });
172
- const $$splitComponentImporter = () => import("./_sessionId-DyFxvcBN.js");
239
+ const $$splitComponentImporter = () => import("./_sessionId-B_O50OfN.js");
173
240
  const searchSchema = z.object({
174
241
  project: z.string().optional()
175
242
  });
@@ -233,8 +300,9 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
233
300
  }, Symbol.toStringTag, { value: "Module" }));
234
301
  export {
235
302
  Route$3 as R,
236
- Route$1 as a,
237
- Route as b,
303
+ useTheme as a,
304
+ Route$1 as b,
305
+ Route as c,
238
306
  router as r,
239
307
  usePrivacy as u
240
308
  };
@@ -17,9 +17,9 @@ import "react/jsx-runtime";
17
17
  import "@tanstack/react-router/ssr/server";
18
18
  import "@tanstack/react-router";
19
19
  const getSessionDetail_createServerFn_handler = createServerRpc({
20
- id: "ff8a3161afdfa175e9c519e4146a56ab5bce6e80745e99cfc2191ebbb7a859bb",
20
+ id: "71794080473579a94431392ab409ebd02772f6a9f6a08386cadbb8c0d3cf804a",
21
21
  name: "getSessionDetail",
22
- filename: "src/features/session-detail/session-detail.server.ts"
22
+ filename: "src/features/session-detail/session-detail.api.ts"
23
23
  }, (opts) => getSessionDetail.__executeServer(opts));
24
24
  const getSessionDetail = createServerFn({
25
25
  method: "GET"
@@ -19,9 +19,9 @@ import "react/jsx-runtime";
19
19
  import "@tanstack/react-router/ssr/server";
20
20
  import "@tanstack/react-router";
21
21
  const getSessionList_createServerFn_handler = createServerRpc({
22
- id: "bf8e4a7901f1843bdc9c46be1ad5ad59c615b8bbe611b73eb3ff28f20e43ee0d",
22
+ id: "8fd6c4e5b4d5590acf1ec73da75f249978e8aced6dd2be23de06ade8431033be",
23
23
  name: "getSessionList",
24
- filename: "src/features/sessions/sessions.server.ts"
24
+ filename: "src/features/sessions/sessions.api.ts"
25
25
  }, (opts) => getSessionList.__executeServer(opts));
26
26
  const getSessionList = createServerFn({
27
27
  method: "GET"
@@ -29,9 +29,9 @@ const getSessionList = createServerFn({
29
29
  return scanAllSessions();
30
30
  });
31
31
  const getActiveSessionList_createServerFn_handler = createServerRpc({
32
- id: "839d29fe93dfa2a6d506af7b48ca25197190a5ff4c796e970ddfdc6e8c98827f",
32
+ id: "946cc550946f64ee7985dc35913a690eb13183d7ba83cffe398e424e697b4265",
33
33
  name: "getActiveSessionList",
34
- filename: "src/features/sessions/sessions.server.ts"
34
+ filename: "src/features/sessions/sessions.api.ts"
35
35
  }, (opts) => getActiveSessionList.__executeServer(opts));
36
36
  const getActiveSessionList = createServerFn({
37
37
  method: "GET"
@@ -83,9 +83,9 @@ async function paginateAndFilterSessions(allSessions, input) {
83
83
  };
84
84
  }
85
85
  const getPaginatedSessions_createServerFn_handler = createServerRpc({
86
- id: "a3f42f9012fd83586787da8f7cb90649da739dd947d867eb67572f68735ff495",
86
+ id: "e574977967ea9b3387e72d70704b6ca87230e72becaf69f0b98cbc91c9cd1339",
87
87
  name: "getPaginatedSessions",
88
- filename: "src/features/sessions/sessions.server.ts"
88
+ filename: "src/features/sessions/sessions.api.ts"
89
89
  }, (opts) => getPaginatedSessions.__executeServer(opts));
90
90
  const getPaginatedSessions = createServerFn({
91
91
  method: "GET"
@@ -4,10 +4,10 @@ import { z } from "zod";
4
4
  import { c as createServerFn } from "../server.js";
5
5
  const getSessionList = createServerFn({
6
6
  method: "GET"
7
- }).handler(createSsrRpc("bf8e4a7901f1843bdc9c46be1ad5ad59c615b8bbe611b73eb3ff28f20e43ee0d"));
7
+ }).handler(createSsrRpc("8fd6c4e5b4d5590acf1ec73da75f249978e8aced6dd2be23de06ade8431033be"));
8
8
  const getActiveSessionList = createServerFn({
9
9
  method: "GET"
10
- }).handler(createSsrRpc("839d29fe93dfa2a6d506af7b48ca25197190a5ff4c796e970ddfdc6e8c98827f"));
10
+ }).handler(createSsrRpc("946cc550946f64ee7985dc35913a690eb13183d7ba83cffe398e424e697b4265"));
11
11
  const paginatedSessionsInputSchema = z.object({
12
12
  page: z.number().int().min(1),
13
13
  pageSize: z.number().int().min(5).max(100),
@@ -17,7 +17,7 @@ const paginatedSessionsInputSchema = z.object({
17
17
  });
18
18
  const getPaginatedSessions = createServerFn({
19
19
  method: "GET"
20
- }).inputValidator((input) => paginatedSessionsInputSchema.parse(input)).handler(createSsrRpc("a3f42f9012fd83586787da8f7cb90649da739dd947d867eb67572f68735ff495"));
20
+ }).inputValidator((input) => paginatedSessionsInputSchema.parse(input)).handler(createSsrRpc("e574977967ea9b3387e72d70704b6ca87230e72becaf69f0b98cbc91c9cd1339"));
21
21
  queryOptions({
22
22
  queryKey: ["sessions", "list"],
23
23
  queryFn: () => getSessionList(),