claude-code-kanban 4.18.0 → 4.19.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-kanban",
3
- "version": "4.18.0",
3
+ "version": "4.19.0",
4
4
  "description": "A web-based Kanban board for viewing Claude Code tasks with agent teams support",
5
5
  "main": "server.js",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -6453,6 +6453,14 @@ function updateStickyBtnState() {
6453
6453
  if (svg) svg.setAttribute('fill', isSticky ? 'currentColor' : 'none');
6454
6454
  }
6455
6455
 
6456
+ // Purely cosmetic: the tmp root is identical for every session and the encoded
6457
+ // project segment is already shown in the Path row, so only the last two segments
6458
+ // carry information. The full path stays in the tooltip and the copy button.
6459
+ function abbreviateScratchpadDir(dir) {
6460
+ const sep = dir.includes('\\') ? '\\' : '/';
6461
+ return ['$tmp', '…', ...dir.split(/[/\\]/).slice(-2)].join(sep);
6462
+ }
6463
+
6456
6464
  function showInfoModal(session, teamConfig, tasks, planContent, parentInfo) {
6457
6465
  const modal = document.getElementById('team-modal');
6458
6466
  const titleEl = document.getElementById('team-modal-title');
@@ -6470,7 +6478,8 @@ function showInfoModal(session, teamConfig, tasks, planContent, parentInfo) {
6470
6478
  let html = '';
6471
6479
 
6472
6480
  // Session & project details as compact key-value rows
6473
- // Each row: [label, displayValue, { openPath?, copyValue? }]
6481
+ // Each row: [label, value, { openPath?, abbrev? }] — `value` is authoritative
6482
+ // (tooltip + copy); `abbrev` only replaces the rendered text.
6474
6483
  const infoRows = [];
6475
6484
  infoRows.push(['Session', session.id, { openClaudeDir: true, openFile: session.jsonlPath }]);
6476
6485
  if (parentInfo?.parentSessionId) {
@@ -6500,6 +6509,13 @@ function showInfoModal(session, teamConfig, tasks, planContent, parentInfo) {
6500
6509
  if (session.tasksDir) {
6501
6510
  infoRows.push(['Tasks Dir', session.tasksDir, { openPath: session.tasksDir }]);
6502
6511
  }
6512
+ if (session.scratchpadDir) {
6513
+ infoRows.push([
6514
+ 'Scratchpad',
6515
+ session.scratchpadDir,
6516
+ { openPath: session.scratchpadDir, abbrev: abbreviateScratchpadDir(session.scratchpadDir) },
6517
+ ]);
6518
+ }
6503
6519
  if (session.sharedTaskList) {
6504
6520
  infoRows.push(['Shared Tasks', session.sharedTaskList]);
6505
6521
  }
@@ -6517,7 +6533,7 @@ function showInfoModal(session, teamConfig, tasks, planContent, parentInfo) {
6517
6533
  if (opts?.openSession) {
6518
6534
  html += `<span onclick="openSessionFromInfo('${escAttrJs(opts.openSession)}')" style="${clickableStyle}" title="Open session in app">${escapeHtml(value)}</span>`;
6519
6535
  } else {
6520
- html += `<span style="${plainStyle}" title="${escapeHtml(value)}">${escapeHtml(value)}</span>`;
6536
+ html += `<span style="${plainStyle}" title="${escapeHtml(value)}">${escapeHtml(opts?.abbrev || value)}</span>`;
6521
6537
  }
6522
6538
  const copyBtn = `<button onclick="copyWithFeedback('${escAttrJs(value)}', this)" title="Copy">${ICON_COPY}</button>`;
6523
6539
  let openBtn = '';
package/public/style.css CHANGED
@@ -2805,6 +2805,9 @@ body::before {
2805
2805
  }
2806
2806
  .rendered-md blockquote {
2807
2807
  margin: 0.6em 0;
2808
+ padding-left: 10px;
2809
+ border-left: 2px solid var(--border);
2810
+ color: var(--text-secondary);
2808
2811
  }
2809
2812
  .rendered-md table {
2810
2813
  margin: 0.6em 0;
package/server.js CHANGED
@@ -94,6 +94,8 @@ const CCK_DIR = path.join(CLAUDE_DIR, '.cck');
94
94
  const AGENT_ACTIVITY_DIR = path.join(CCK_DIR, 'agent-activity');
95
95
  const CONTEXT_STATUS_DIR = path.join(CCK_DIR, 'context-status');
96
96
  const PINS_FILE = path.join(CCK_DIR, 'pins.json');
97
+ // Harness-owned scratchpad root; the per-session dir under it is created lazily.
98
+ const SCRATCHPAD_ROOT = path.join(os.tmpdir(), 'claude');
97
99
 
98
100
  // Server-side pin mirror (UI authoritative, server stores latest pushed state for CLI queries).
99
101
  function readPins() {
@@ -961,6 +963,14 @@ function getSessionDisplayName(sessionId, meta) {
961
963
  return null;
962
964
  }
963
965
 
966
+ // Derived by convention, not looked up: the harness creates the dir lazily, so a
967
+ // stat here would report "missing" for every session that has not written a temp
968
+ // file yet — and it would put IO on the session-list hot path. Pure string join.
969
+ function getScratchpadDir(id, meta) {
970
+ if (!meta.jsonlPath) return null;
971
+ return path.join(SCRATCHPAD_ROOT, path.basename(path.dirname(meta.jsonlPath)), id, 'scratchpad');
972
+ }
973
+
964
974
  function buildSessionObject(id, meta, overrides = {}) {
965
975
  const logStat = overrides._logStat || getSessionLogStat(meta);
966
976
  const logMtime = logStat.mtime;
@@ -992,6 +1002,7 @@ function buildSessionObject(id, meta, overrides = {}) {
992
1002
  jsonlPath: meta.jsonlPath || null,
993
1003
  tasksDir: null,
994
1004
  projectDir: meta.jsonlPath ? path.dirname(meta.jsonlPath) : null,
1005
+ scratchpadDir: getScratchpadDir(id, meta),
995
1006
  contextStatus: getContextStatus(id, meta),
996
1007
  ...getPlanInfo(meta.slug),
997
1008
  ...getWorkflowInfoSummary(id),