claude-code-kanban 4.31.0 → 5.0.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/cli.js +16 -5
- package/hub-app.json +25 -0
- package/lib/net-guard.js +6 -1
- package/lib/parsers.js +21 -12
- package/lib/terminal.js +73 -8
- package/package.json +2 -1
- package/plugin/plugins/claude-code-kanban/.claude-plugin/plugin.json +1 -1
- package/plugin/plugins/claude-code-kanban/hooks/hooks.json +12 -0
- package/plugin/plugins/claude-code-kanban/scripts/agent-spy.sh +10 -3
- package/plugin/plugins/claude-code-kanban/scripts/postman.js +13 -2
- package/public/app.js +683 -373
- package/public/index.html +31 -4
- package/public/style.css +149 -9
- package/public/vendor/claude-hub-sdk.js +50 -0
- package/server.js +89 -28
package/public/index.html
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
<script defer src="/app.js"></script>
|
|
33
33
|
</head>
|
|
34
34
|
<body class="booting">
|
|
35
|
+
<script src="/vendor/claude-hub-sdk.js"></script>
|
|
35
36
|
<div id="offline-overlay" class="offline-overlay">
|
|
36
37
|
<div class="offline-card">
|
|
37
38
|
<div class="clawd-sleep" aria-hidden="true">
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
|
|
75
76
|
<!-- Tasks -->
|
|
76
77
|
<div class="sidebar-section flex-1">
|
|
77
|
-
<div class="section-header"
|
|
78
|
+
<div class="section-header">
|
|
78
79
|
<span class="section-header-label">Sessions</span>
|
|
79
80
|
<span id="filter-summary" class="filter-summary" title=""></span>
|
|
80
81
|
<span class="section-header-actions">
|
|
@@ -116,9 +117,16 @@
|
|
|
116
117
|
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L3 8"/>
|
|
117
118
|
</svg>
|
|
118
119
|
</button>
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
<button
|
|
121
|
+
class="icon-btn section-btn"
|
|
122
|
+
onclick="toggleSection('sessions-filters', 'sessions-chevron')"
|
|
123
|
+
title="Show or hide search and filters"
|
|
124
|
+
aria-label="Show or hide search and filters"
|
|
125
|
+
>
|
|
126
|
+
<svg id="sessions-chevron" class="collapse-chevron" viewBox="0 0 24 24">
|
|
127
|
+
<path d="M6 9l6 6 6-6"/>
|
|
128
|
+
</svg>
|
|
129
|
+
</button>
|
|
122
130
|
</span>
|
|
123
131
|
<div id="filter-menu" class="filter-menu" onclick="event.stopPropagation()">
|
|
124
132
|
<div class="pf-field">
|
|
@@ -325,6 +333,7 @@
|
|
|
325
333
|
<div id="terminal-boot" class="terminal-boot" aria-hidden="true">
|
|
326
334
|
<svg class="clawd clawd-jump" viewBox="1 0 16 10" shape-rendering="crispEdges"><use href="#clawd-shape"/></svg>
|
|
327
335
|
<p id="terminal-boot-verb"></p>
|
|
336
|
+
<p class="terminal-boot-slow">Slow to connect. Press <kbd>R</kbd> to reconnect.</p>
|
|
328
337
|
</div>
|
|
329
338
|
<div id="terminal-host" class="terminal-host"></div>
|
|
330
339
|
</div>
|
|
@@ -450,12 +459,17 @@
|
|
|
450
459
|
<div class="modal modal-help" onclick="event.stopPropagation()">
|
|
451
460
|
<div class="modal-header">
|
|
452
461
|
<h3 class="modal-title">Keyboard Shortcuts</h3>
|
|
462
|
+
<a class="help-docs" id="help-docs" href="https://nikiforovall.blog/claude-code-kanban/" target="_blank" rel="noopener">Docs ↗</a>
|
|
453
463
|
<button class="modal-close" aria-label="Close dialog" onclick="closeHelpModal()">
|
|
454
464
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
455
465
|
<path d="M18 6L6 18M6 6l12 12"/>
|
|
456
466
|
</svg>
|
|
457
467
|
</button>
|
|
458
468
|
</div>
|
|
469
|
+
<div class="help-bar">
|
|
470
|
+
<div class="help-tabs" id="help-tabs" role="tablist" aria-label="Shortcut groups"></div>
|
|
471
|
+
<input type="search" id="help-filter" class="form-input help-filter" placeholder="Filter shortcuts" aria-label="Filter shortcuts" autocomplete="off" spellcheck="false">
|
|
472
|
+
</div>
|
|
459
473
|
<div class="modal-body">
|
|
460
474
|
<dl class="shortcuts" id="help-shortcuts"></dl>
|
|
461
475
|
</div>
|
|
@@ -801,6 +815,19 @@
|
|
|
801
815
|
</div>
|
|
802
816
|
</div>
|
|
803
817
|
|
|
818
|
+
<div id="project-picker-modal" class="modal-overlay top-aligned" onclick="closeProjectPicker()">
|
|
819
|
+
<div class="modal session-picker" onclick="event.stopPropagation()">
|
|
820
|
+
<input type="text" id="project-picker-input" class="form-input sp-input" placeholder="Filter by project..." autocomplete="off" spellcheck="false">
|
|
821
|
+
<div class="pp-chips">
|
|
822
|
+
<button type="button" class="pf-recent" id="pp-recent-chip" aria-pressed="false" title="List only projects active in the last 24h" onclick="ppToggleRecentOnly()">Recent</button>
|
|
823
|
+
</div>
|
|
824
|
+
<div class="sp-body">
|
|
825
|
+
<div id="project-picker-list" class="sp-list"></div>
|
|
826
|
+
</div>
|
|
827
|
+
<div class="sp-hint"><kbd>↑</kbd><kbd>↓</kbd> move · <kbd>Enter</kbd> filter · <kbd>Alt</kbd><kbd>R</kbd> recent · <kbd>Alt</kbd><kbd>C</kbd> reset filter · <kbd>Esc</kbd> close</div>
|
|
828
|
+
</div>
|
|
829
|
+
</div>
|
|
830
|
+
|
|
804
831
|
<div id="toast" class="toast"></div>
|
|
805
832
|
</body>
|
|
806
833
|
</html>
|
package/public/style.css
CHANGED
|
@@ -232,6 +232,25 @@ body::before {
|
|
|
232
232
|
animation: pulse 2.5s ease-in-out infinite;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
.activity-icon {
|
|
236
|
+
display: inline-flex;
|
|
237
|
+
margin: 0 -2px;
|
|
238
|
+
color: var(--chip-color, var(--accent));
|
|
239
|
+
}
|
|
240
|
+
.activity-icon svg {
|
|
241
|
+
width: 11px;
|
|
242
|
+
height: 11px;
|
|
243
|
+
}
|
|
244
|
+
.activity-chip.activity-zero .activity-icon {
|
|
245
|
+
color: var(--text-muted);
|
|
246
|
+
}
|
|
247
|
+
.activity-chip.activity-warn {
|
|
248
|
+
--chip-color: var(--warning);
|
|
249
|
+
background: var(--warning-dim);
|
|
250
|
+
border-color: color-mix(in srgb, var(--chip-color) 60%, var(--border));
|
|
251
|
+
color: var(--chip-color);
|
|
252
|
+
}
|
|
253
|
+
|
|
235
254
|
.sidebar.collapsed .activity-chips {
|
|
236
255
|
display: none;
|
|
237
256
|
}
|
|
@@ -942,6 +961,22 @@ body.booting .boot-splash {
|
|
|
942
961
|
background: var(--success);
|
|
943
962
|
}
|
|
944
963
|
|
|
964
|
+
.session-item.warm.idle .session-time {
|
|
965
|
+
color: var(--text-tertiary);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.session-item.warm.idle .session-time::before {
|
|
969
|
+
background: var(--text-tertiary);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
.session-item.warm.permission-pending .session-time {
|
|
973
|
+
color: var(--warning);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.session-item.warm.permission-pending .session-time::before {
|
|
977
|
+
background: var(--warning);
|
|
978
|
+
}
|
|
979
|
+
|
|
945
980
|
.session-item.stale .session-time {
|
|
946
981
|
color: var(--text-muted);
|
|
947
982
|
}
|
|
@@ -962,6 +997,27 @@ body.booting .boot-splash {
|
|
|
962
997
|
padding-right: 22px;
|
|
963
998
|
}
|
|
964
999
|
|
|
1000
|
+
.session-item.unread::before,
|
|
1001
|
+
.session-item.permission-pending::before {
|
|
1002
|
+
content: '';
|
|
1003
|
+
position: absolute;
|
|
1004
|
+
inset: -1px;
|
|
1005
|
+
border-left: 3px solid var(--accent);
|
|
1006
|
+
border-radius: inherit;
|
|
1007
|
+
pointer-events: none;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.session-item.permission-pending::before {
|
|
1011
|
+
border-left-color: var(--warning);
|
|
1012
|
+
animation: agent-badge-pulse 1.6s ease-in-out infinite;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1016
|
+
.session-item.permission-pending::before {
|
|
1017
|
+
animation: none;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
965
1021
|
.session-indicators .pulse,
|
|
966
1022
|
.wf-live-name .pulse,
|
|
967
1023
|
.session-waiting .pulse {
|
|
@@ -3132,6 +3188,14 @@ body.booting .boot-splash {
|
|
|
3132
3188
|
animation: boot-fade 0.3s ease-out 0.2s both;
|
|
3133
3189
|
}
|
|
3134
3190
|
|
|
3191
|
+
.terminal-boot-slow {
|
|
3192
|
+
display: none;
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
.terminal-boot.slow .terminal-boot-slow {
|
|
3196
|
+
display: block;
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3135
3199
|
/* Opacity, not visibility: a hidden textarea drops focus, and the terminal must keep it. */
|
|
3136
3200
|
.terminal-pane:has(.terminal-boot.visible) .xterm {
|
|
3137
3201
|
opacity: 0;
|
|
@@ -5587,6 +5651,7 @@ body.light .msg-assistant .msg-text {
|
|
|
5587
5651
|
the viewport cap. */
|
|
5588
5652
|
.modal-help {
|
|
5589
5653
|
max-width: 900px;
|
|
5654
|
+
height: min(700px, 90vh);
|
|
5590
5655
|
padding: 16px 20px 20px;
|
|
5591
5656
|
display: flex;
|
|
5592
5657
|
flex-direction: column;
|
|
@@ -5599,11 +5664,30 @@ body.light .msg-assistant .msg-text {
|
|
|
5599
5664
|
font-size: 14px;
|
|
5600
5665
|
}
|
|
5601
5666
|
|
|
5667
|
+
.help-docs {
|
|
5668
|
+
margin: 0 12px 0 auto;
|
|
5669
|
+
padding: 4px 10px;
|
|
5670
|
+
border: 1px solid var(--border);
|
|
5671
|
+
border-radius: 6px;
|
|
5672
|
+
color: var(--text-secondary);
|
|
5673
|
+
font-size: 12px;
|
|
5674
|
+
text-decoration: none;
|
|
5675
|
+
white-space: nowrap;
|
|
5676
|
+
transition:
|
|
5677
|
+
color 0.15s ease,
|
|
5678
|
+
border-color 0.15s ease;
|
|
5679
|
+
}
|
|
5680
|
+
|
|
5681
|
+
.help-docs:hover {
|
|
5682
|
+
color: var(--accent);
|
|
5683
|
+
border-color: var(--accent);
|
|
5684
|
+
}
|
|
5685
|
+
|
|
5602
5686
|
/* One shared grid for both halves (key | label | spacer | key | label): each key
|
|
5603
5687
|
gutter is sized by its column's widest combo, and left/right rows share row
|
|
5604
5688
|
tracks, so paired groups line up — a shorter group just leaves empty rows.
|
|
5605
5689
|
Cells opt into a half via sc-l / sc-r; the markup is generated from
|
|
5606
|
-
|
|
5690
|
+
SHORTCUT_TABS in app.js. */
|
|
5607
5691
|
.shortcuts {
|
|
5608
5692
|
margin: 0;
|
|
5609
5693
|
display: grid;
|
|
@@ -5666,7 +5750,8 @@ body.light .msg-assistant .msg-text {
|
|
|
5666
5750
|
|
|
5667
5751
|
/* keycap chips: elevated fill + thicker bottom border reads as a key */
|
|
5668
5752
|
.sp-hint kbd,
|
|
5669
|
-
.shortcuts kbd
|
|
5753
|
+
.shortcuts kbd,
|
|
5754
|
+
.terminal-boot-slow kbd {
|
|
5670
5755
|
display: inline-flex;
|
|
5671
5756
|
align-items: center;
|
|
5672
5757
|
justify-content: center;
|
|
@@ -5689,10 +5774,31 @@ body.light .msg-assistant .msg-text {
|
|
|
5689
5774
|
font-size: 11px;
|
|
5690
5775
|
}
|
|
5691
5776
|
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5777
|
+
.shortcuts .sc-empty {
|
|
5778
|
+
grid-column: 1 / -1;
|
|
5779
|
+
padding: 24px 0;
|
|
5780
|
+
color: var(--text-muted);
|
|
5781
|
+
text-align: center;
|
|
5782
|
+
}
|
|
5783
|
+
|
|
5784
|
+
.help-bar {
|
|
5785
|
+
display: flex;
|
|
5786
|
+
align-items: flex-end;
|
|
5787
|
+
gap: 12px;
|
|
5788
|
+
margin-bottom: 12px;
|
|
5789
|
+
border-bottom: 1px solid var(--border);
|
|
5790
|
+
flex-shrink: 0;
|
|
5791
|
+
}
|
|
5792
|
+
|
|
5793
|
+
.help-tabs {
|
|
5794
|
+
display: flex;
|
|
5795
|
+
}
|
|
5796
|
+
|
|
5797
|
+
.help-bar .help-filter {
|
|
5798
|
+
margin: 0 0 6px auto;
|
|
5799
|
+
width: 220px;
|
|
5800
|
+
padding: 4px 10px;
|
|
5801
|
+
font-size: 12px;
|
|
5696
5802
|
}
|
|
5697
5803
|
|
|
5698
5804
|
@keyframes live-border-pulse {
|
|
@@ -6024,6 +6130,21 @@ select.form-input option:checked {
|
|
|
6024
6130
|
color: var(--text-primary);
|
|
6025
6131
|
}
|
|
6026
6132
|
|
|
6133
|
+
.sp-pin {
|
|
6134
|
+
flex: none;
|
|
6135
|
+
line-height: 0;
|
|
6136
|
+
}
|
|
6137
|
+
|
|
6138
|
+
.sp-pin.pinned svg {
|
|
6139
|
+
fill: var(--accent);
|
|
6140
|
+
stroke: var(--accent);
|
|
6141
|
+
}
|
|
6142
|
+
|
|
6143
|
+
.sp-pin.sticky svg {
|
|
6144
|
+
fill: var(--warning);
|
|
6145
|
+
stroke: var(--warning);
|
|
6146
|
+
}
|
|
6147
|
+
|
|
6027
6148
|
.sp-row:not(.outside) + .sp-row.outside {
|
|
6028
6149
|
margin-top: 8px;
|
|
6029
6150
|
}
|
|
@@ -6076,6 +6197,17 @@ select.form-input option:checked {
|
|
|
6076
6197
|
font-size: 11px;
|
|
6077
6198
|
}
|
|
6078
6199
|
|
|
6200
|
+
.pp-chips {
|
|
6201
|
+
display: flex;
|
|
6202
|
+
gap: 6px;
|
|
6203
|
+
}
|
|
6204
|
+
|
|
6205
|
+
.sp-row.recent .sp-name::before {
|
|
6206
|
+
content: '•';
|
|
6207
|
+
margin-right: 5px;
|
|
6208
|
+
color: var(--accent-text);
|
|
6209
|
+
}
|
|
6210
|
+
|
|
6079
6211
|
/* #endregion */
|
|
6080
6212
|
|
|
6081
6213
|
/* #region NEW_SESSION */
|
|
@@ -6556,7 +6688,8 @@ select.form-input option:checked {
|
|
|
6556
6688
|
flex-shrink: 0;
|
|
6557
6689
|
}
|
|
6558
6690
|
|
|
6559
|
-
.storage-tab
|
|
6691
|
+
.storage-tab,
|
|
6692
|
+
.help-tab {
|
|
6560
6693
|
background: none;
|
|
6561
6694
|
border: none;
|
|
6562
6695
|
color: var(--text-secondary);
|
|
@@ -6570,11 +6703,13 @@ select.form-input option:checked {
|
|
|
6570
6703
|
border-color 0.15s;
|
|
6571
6704
|
}
|
|
6572
6705
|
|
|
6573
|
-
.storage-tab:hover
|
|
6706
|
+
.storage-tab:hover,
|
|
6707
|
+
.help-tab:hover {
|
|
6574
6708
|
color: var(--text-primary);
|
|
6575
6709
|
}
|
|
6576
6710
|
|
|
6577
|
-
.storage-tab.active
|
|
6711
|
+
.storage-tab.active,
|
|
6712
|
+
.help-tab.active {
|
|
6578
6713
|
color: var(--accent);
|
|
6579
6714
|
border-bottom-color: var(--accent);
|
|
6580
6715
|
}
|
|
@@ -7258,6 +7393,11 @@ pre.mermaid svg {
|
|
|
7258
7393
|
background: var(--accent-dim);
|
|
7259
7394
|
}
|
|
7260
7395
|
|
|
7396
|
+
/* An empty section shows only while a drag needs its ungroup drop zone. */
|
|
7397
|
+
.sessions-list:not(.sg-dragging-active) .sg-section-empty {
|
|
7398
|
+
display: none;
|
|
7399
|
+
}
|
|
7400
|
+
|
|
7261
7401
|
.sessions-list.sg-dragging-active .sg-ungroup-zone {
|
|
7262
7402
|
border: 1px dashed var(--accent);
|
|
7263
7403
|
border-radius: 4px;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// claude-hub-sdk 1.1.0 (sha256 0fed14faa670). Copied by npm run sdk:sync in claude-code-hub. Do not edit.
|
|
2
|
+
// Claude Code Hub SDK stub: what an app serves when no hub runs it. Under a hub, the hub hands the
|
|
3
|
+
// app its real SDK (client.js) in place of this file. The API must match client.js; a test checks it.
|
|
4
|
+
((root) => {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
function createClaudeHub(win) {
|
|
8
|
+
let hub = null;
|
|
9
|
+
const off = () => {};
|
|
10
|
+
|
|
11
|
+
function connect({ standalone = {} } = {}) {
|
|
12
|
+
if (hub) return hub;
|
|
13
|
+
const standaloneFn = (action) => {
|
|
14
|
+
const fn = (typeof standalone === 'function' ? standalone() : standalone)[action];
|
|
15
|
+
return typeof fn === 'function' ? fn : null;
|
|
16
|
+
};
|
|
17
|
+
hub = {
|
|
18
|
+
status: 'standalone',
|
|
19
|
+
themes: [],
|
|
20
|
+
inHub: false,
|
|
21
|
+
onStatus: () => off,
|
|
22
|
+
onActive: () => off,
|
|
23
|
+
onThemes: () => off,
|
|
24
|
+
subscribe: () => off,
|
|
25
|
+
bindTheme: () => off,
|
|
26
|
+
handle() {},
|
|
27
|
+
publish() {},
|
|
28
|
+
invoke(action, params = {}) {
|
|
29
|
+
const target = standaloneFn(action)?.(params);
|
|
30
|
+
if (!target) return Promise.resolve({ ok: false, reason: 'unhandled' });
|
|
31
|
+
win.open(target, '_blank', 'noopener');
|
|
32
|
+
return Promise.resolve({ ok: true, handledBy: 'standalone' });
|
|
33
|
+
},
|
|
34
|
+
can: (action) => !!standaloneFn(action),
|
|
35
|
+
forwards: () => false,
|
|
36
|
+
closeGuard() {},
|
|
37
|
+
openExternal(url) {
|
|
38
|
+
win.open(url, '_blank', 'noopener');
|
|
39
|
+
},
|
|
40
|
+
terminalToken: () => Promise.resolve(null),
|
|
41
|
+
};
|
|
42
|
+
return hub;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { connect };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (typeof module === 'object' && module.exports) module.exports = { createClaudeHub };
|
|
49
|
+
else root.ClaudeHub = createClaudeHub(root);
|
|
50
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|