@viren/claude-code-dashboard 0.0.5 → 0.0.6
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/README.md +10 -0
- package/package.json +1 -1
- package/src/assembler.mjs +8 -4
- package/src/constants.mjs +1 -1
- package/src/helpers.mjs +21 -0
- package/src/sections.mjs +7 -3
- package/template/dashboard.css +73 -4
- package/template/dashboard.js +46 -0
package/README.md
CHANGED
|
@@ -212,6 +212,16 @@ If no directories are listed, the entire home directory is scanned (depth 5).
|
|
|
212
212
|
- Node.js 18+
|
|
213
213
|
- Git (for freshness timestamps and drift detection)
|
|
214
214
|
|
|
215
|
+
## Roadmap
|
|
216
|
+
|
|
217
|
+
Completed: v0.1 (foundation), v0.2 (intelligence layer), v0.3 (recommendations engine), v0.4 (config templates), v0.5 (control center).
|
|
218
|
+
|
|
219
|
+
**Up next:**
|
|
220
|
+
|
|
221
|
+
- [ ] Org-wide dashboard — scan multiple users' configs for team visibility
|
|
222
|
+
|
|
223
|
+
See [issues](https://github.com/VirenMohindra/claude-code-dashboard/issues) for feature requests.
|
|
224
|
+
|
|
215
225
|
## Privacy
|
|
216
226
|
|
|
217
227
|
The generated HTML file contains:
|
package/package.json
CHANGED
package/src/assembler.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync } from "fs";
|
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
|
|
5
|
-
import { esc } from "./helpers.mjs";
|
|
5
|
+
import { esc, insightsToMarkdown } from "./helpers.mjs";
|
|
6
6
|
import { VERSION, REPO_URL } from "./constants.mjs";
|
|
7
7
|
import { renderCmd, renderRule, renderRepoCard } from "./render.mjs";
|
|
8
8
|
import {
|
|
@@ -64,8 +64,11 @@ export function generateDashboardHtml(data) {
|
|
|
64
64
|
// ── Build section HTML fragments ──────────────────────────────────────────
|
|
65
65
|
|
|
66
66
|
const header = `<h1>claude code dashboard</h1>
|
|
67
|
-
<
|
|
68
|
-
<
|
|
67
|
+
<div class="header-actions">
|
|
68
|
+
<button id="refresh-btn" class="header-btn" title="Copy refresh command to clipboard" aria-label="Copy refresh command">↻ refresh</button>
|
|
69
|
+
<button id="theme-toggle" class="theme-toggle" title="Toggle light/dark mode" aria-label="Toggle theme"><span class="theme-icon"></span></button>
|
|
70
|
+
</div>
|
|
71
|
+
<p class="sub">generated ${timestamp} · <a href="${esc(REPO_URL)}" target="_blank" rel="noopener" style="color:var(--accent);text-decoration:none">v${esc(VERSION)}</a></p>`;
|
|
69
72
|
|
|
70
73
|
const statsBar = renderStatsBar(data);
|
|
71
74
|
|
|
@@ -80,7 +83,8 @@ export function generateDashboardHtml(data) {
|
|
|
80
83
|
${globalRules.map((r) => renderRule(r)).join("\n ")}
|
|
81
84
|
</div>
|
|
82
85
|
</div>`;
|
|
83
|
-
const
|
|
86
|
+
const insightsMarkdown = insightsToMarkdown(insights);
|
|
87
|
+
const insightsHtml = renderInsightsCard(insights, insightsMarkdown);
|
|
84
88
|
const chainsHtml = renderChainsCard(chains);
|
|
85
89
|
const consolidationHtml = renderConsolidationCard(consolidationGroups);
|
|
86
90
|
const tabOverview = `${overviewCommands}\n ${insightsHtml}\n ${chainsHtml}\n ${consolidationHtml}`;
|
package/src/constants.mjs
CHANGED
package/src/helpers.mjs
CHANGED
|
@@ -33,6 +33,27 @@ export function gitCmd(repoDir, ...args) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
const INSIGHT_ICONS = {
|
|
37
|
+
warning: "\u26A0\uFE0F",
|
|
38
|
+
tip: "\u2728",
|
|
39
|
+
promote: "\u2B06",
|
|
40
|
+
info: "\u2139\uFE0F",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** Convert an insights array to a markdown string suitable for pasting into Claude Code. */
|
|
44
|
+
export function insightsToMarkdown(insights) {
|
|
45
|
+
if (!insights || !insights.length) return "";
|
|
46
|
+
const lines = ["# Dashboard Insights\n"];
|
|
47
|
+
for (const i of insights) {
|
|
48
|
+
const icon = INSIGHT_ICONS[i.type] || INSIGHT_ICONS.info;
|
|
49
|
+
lines.push(`## ${icon} ${i.title}`);
|
|
50
|
+
if (i.detail) lines.push(i.detail);
|
|
51
|
+
if (i.action) lines.push(`**Action:** ${i.action}`);
|
|
52
|
+
lines.push("");
|
|
53
|
+
}
|
|
54
|
+
return lines.join("\n");
|
|
55
|
+
}
|
|
56
|
+
|
|
36
57
|
export function anonymizePath(p) {
|
|
37
58
|
return p
|
|
38
59
|
.replace(/^\/Users\/[^/]+\//, "~/")
|
package/src/sections.mjs
CHANGED
|
@@ -330,10 +330,14 @@ export function renderReferenceCard() {
|
|
|
330
330
|
</div>`;
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
export function renderInsightsCard(insights) {
|
|
333
|
+
export function renderInsightsCard(insights, markdown) {
|
|
334
334
|
if (!insights || !insights.length) return "";
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
const mdAttr = markdown ? ` data-markdown="${esc(markdown)}"` : "";
|
|
336
|
+
return `<div class="card insight-card"${mdAttr}>
|
|
337
|
+
<div class="card-header">
|
|
338
|
+
<h2>Insights <span class="n">${insights.length}</span></h2>
|
|
339
|
+
${markdown ? `<button class="copy-md-btn" title="Copy as Markdown">📋 copy markdown</button>` : ""}
|
|
340
|
+
</div>
|
|
337
341
|
${insights
|
|
338
342
|
.map(
|
|
339
343
|
(i) =>
|
package/template/dashboard.css
CHANGED
|
@@ -52,6 +52,31 @@ h1 {
|
|
|
52
52
|
color: var(--accent);
|
|
53
53
|
margin-bottom: 0.2rem;
|
|
54
54
|
}
|
|
55
|
+
.header-actions {
|
|
56
|
+
position: fixed;
|
|
57
|
+
top: 1rem;
|
|
58
|
+
right: 1rem;
|
|
59
|
+
z-index: 100;
|
|
60
|
+
display: flex;
|
|
61
|
+
gap: 0.4rem;
|
|
62
|
+
align-items: center;
|
|
63
|
+
}
|
|
64
|
+
.header-btn {
|
|
65
|
+
background: var(--surface);
|
|
66
|
+
border: 1px solid var(--border);
|
|
67
|
+
border-radius: 8px;
|
|
68
|
+
padding: 0.4rem 0.6rem;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
color: var(--text-dim);
|
|
71
|
+
font-size: 0.75rem;
|
|
72
|
+
transition:
|
|
73
|
+
background 0.15s,
|
|
74
|
+
border-color 0.15s;
|
|
75
|
+
}
|
|
76
|
+
.header-btn:hover {
|
|
77
|
+
border-color: var(--accent-dim);
|
|
78
|
+
color: var(--text);
|
|
79
|
+
}
|
|
55
80
|
.sub {
|
|
56
81
|
color: var(--text-dim);
|
|
57
82
|
font-size: 0.78rem;
|
|
@@ -609,6 +634,54 @@ details.cmd-detail > summary::-webkit-details-marker {
|
|
|
609
634
|
color: var(--accent);
|
|
610
635
|
}
|
|
611
636
|
|
|
637
|
+
.card-header {
|
|
638
|
+
display: flex;
|
|
639
|
+
align-items: center;
|
|
640
|
+
justify-content: space-between;
|
|
641
|
+
margin-bottom: 0.5rem;
|
|
642
|
+
}
|
|
643
|
+
.card-header h2 {
|
|
644
|
+
margin-bottom: 0;
|
|
645
|
+
}
|
|
646
|
+
.copy-md-btn {
|
|
647
|
+
background: var(--surface2);
|
|
648
|
+
border: 1px solid var(--border);
|
|
649
|
+
border-radius: 5px;
|
|
650
|
+
padding: 0.25rem 0.5rem;
|
|
651
|
+
font-size: 0.65rem;
|
|
652
|
+
color: var(--text-dim);
|
|
653
|
+
cursor: pointer;
|
|
654
|
+
transition:
|
|
655
|
+
border-color 0.15s,
|
|
656
|
+
color 0.15s;
|
|
657
|
+
white-space: nowrap;
|
|
658
|
+
}
|
|
659
|
+
.copy-md-btn:hover {
|
|
660
|
+
border-color: var(--accent-dim);
|
|
661
|
+
color: var(--text);
|
|
662
|
+
}
|
|
663
|
+
.copy-toast {
|
|
664
|
+
position: fixed;
|
|
665
|
+
bottom: 1.5rem;
|
|
666
|
+
left: 50%;
|
|
667
|
+
transform: translateX(-50%) translateY(20px);
|
|
668
|
+
background: var(--surface);
|
|
669
|
+
border: 1px solid var(--accent-dim);
|
|
670
|
+
color: var(--text);
|
|
671
|
+
padding: 0.5rem 1rem;
|
|
672
|
+
border-radius: 8px;
|
|
673
|
+
font-size: 0.75rem;
|
|
674
|
+
opacity: 0;
|
|
675
|
+
pointer-events: none;
|
|
676
|
+
transition:
|
|
677
|
+
opacity 0.2s,
|
|
678
|
+
transform 0.2s;
|
|
679
|
+
z-index: 200;
|
|
680
|
+
}
|
|
681
|
+
.copy-toast.visible {
|
|
682
|
+
opacity: 1;
|
|
683
|
+
transform: translateX(-50%) translateY(0);
|
|
684
|
+
}
|
|
612
685
|
.insight-card {
|
|
613
686
|
margin-bottom: 1.25rem;
|
|
614
687
|
}
|
|
@@ -1133,10 +1206,6 @@ details.cmd-detail > summary::-webkit-details-marker {
|
|
|
1133
1206
|
}
|
|
1134
1207
|
|
|
1135
1208
|
.theme-toggle {
|
|
1136
|
-
position: fixed;
|
|
1137
|
-
top: 1rem;
|
|
1138
|
-
right: 1rem;
|
|
1139
|
-
z-index: 100;
|
|
1140
1209
|
background: var(--surface);
|
|
1141
1210
|
border: 1px solid var(--border);
|
|
1142
1211
|
border-radius: 8px;
|
package/template/dashboard.js
CHANGED
|
@@ -119,6 +119,52 @@ groupSelect.addEventListener("change", function () {
|
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
// ── Toast helper ────────────────────────────────────────────
|
|
123
|
+
var toast = document.createElement("div");
|
|
124
|
+
toast.className = "copy-toast";
|
|
125
|
+
document.body.appendChild(toast);
|
|
126
|
+
var toastTimer;
|
|
127
|
+
function showToast(msg) {
|
|
128
|
+
toast.textContent = msg;
|
|
129
|
+
toast.classList.add("visible");
|
|
130
|
+
clearTimeout(toastTimer);
|
|
131
|
+
toastTimer = setTimeout(function () {
|
|
132
|
+
toast.classList.remove("visible");
|
|
133
|
+
}, 2000);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ── Copy Markdown button ────────────────────────────────────
|
|
137
|
+
document.querySelectorAll(".copy-md-btn").forEach(function (btn) {
|
|
138
|
+
btn.addEventListener("click", function () {
|
|
139
|
+
var card = btn.closest("[data-markdown]");
|
|
140
|
+
if (!card) return;
|
|
141
|
+
var md = card.dataset.markdown;
|
|
142
|
+
navigator.clipboard
|
|
143
|
+
.writeText(md)
|
|
144
|
+
.then(function () {
|
|
145
|
+
showToast("Markdown copied to clipboard");
|
|
146
|
+
})
|
|
147
|
+
.catch(function () {
|
|
148
|
+
showToast("Copy failed \u2014 use browser copy from the insights card");
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// ── Refresh button ──────────────────────────────────────────
|
|
154
|
+
var refreshBtn = document.getElementById("refresh-btn");
|
|
155
|
+
if (refreshBtn) {
|
|
156
|
+
refreshBtn.addEventListener("click", function () {
|
|
157
|
+
navigator.clipboard
|
|
158
|
+
.writeText("claude-code-dashboard --open")
|
|
159
|
+
.then(function () {
|
|
160
|
+
showToast("Copied \u2014 paste in terminal to refresh");
|
|
161
|
+
})
|
|
162
|
+
.catch(function () {
|
|
163
|
+
showToast("Run: claude-code-dashboard --open");
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
122
168
|
// Custom tooltip for heatmap cells and peak bars
|
|
123
169
|
var tip = document.getElementById("chart-tooltip");
|
|
124
170
|
document.addEventListener("mouseover", function (e) {
|