Browse Source

feat(skills): Add copy-session-id button to summon picker widget

Per-row clipboard button copies the short session id (what summon
recover/rebind/--peek take). navigator.clipboard first, hidden-textarea
execCommand fallback for sandboxed iframes; inline tick/cross feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0xDarkMatter 3 weeks ago
parent
commit
a32422d3e8
1 changed files with 16 additions and 1 deletions
  1. 16 1
      skills/summon/assets/picker-widget.html

+ 16 - 1
skills/summon/assets/picker-widget.html

@@ -81,6 +81,7 @@ ordered.forEach((proj, gi) => {
       ${arch ? `<span class="badge b-arch">archived</span>` : ""}
       ${REBOUND.has(id) ? `<span class="badge b-reb">✓ rebound</span>` : ""}
       <button class="peek" data-i="${i}" title="peek last messages">👁</button>
+      <button class="peek cpy" data-id="${id}" title="copy session id ${id}">📋</button>
       <span class="age">${age(ts)}</span>
     </label>`; }).join("");
   gEl.appendChild(det);
@@ -124,11 +125,25 @@ function applyFilters(){
 }
 flt.addEventListener("input", applyFilters);
 win.addEventListener("change", applyFilters);
-document.querySelectorAll(".peek").forEach(p => p.addEventListener("click", e => {
+document.querySelectorAll(".peek:not(.cpy)").forEach(p => p.addEventListener("click", e => {
   e.preventDefault(); e.stopPropagation();
   const [id, t] = S[+p.dataset.i];
   sendPrompt(`Peek session ${id} ("${t}") — show me its last few messages via summon --peek so I can decide whether to recover it.`);
 }));
+document.querySelectorAll(".cpy").forEach(b => b.addEventListener("click", async e => {
+  e.preventDefault(); e.stopPropagation();
+  let ok = false;
+  try { await navigator.clipboard.writeText(b.dataset.id); ok = true; } catch (_) {}
+  if (!ok) {
+    const ta = document.createElement("textarea");
+    ta.value = b.dataset.id; ta.style.position = "absolute"; ta.style.left = "-9999px";
+    document.body.appendChild(ta); ta.select();
+    try { ok = document.execCommand("copy"); } catch (_) {}
+    ta.remove();
+  }
+  b.textContent = ok ? "✅" : "❌";
+  setTimeout(() => { b.textContent = "📋"; }, 900);
+}));
 function fmt(list){ return list.map(([id,t,cwd,,,,wt]) => `- ${id} "${t}" @ ${cwd}${wt ? "\\.claude\\worktrees\\" + wt : ""}`).join("\n"); }
 document.getElementById("recover").addEventListener("click", () => {
   sendPrompt(`Recover these sessions I ticked in the picker (summon recover each — distilled handover brief + fresh-start prompt):\n${fmt(sel())}`);