claude-code-kanban 4.24.0 → 4.25.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/README.md +3 -1
- package/cli.js +1 -1
- package/install.js +14 -9
- package/lib/claude-dir.js +53 -0
- package/lib/open-editor.js +4 -1
- package/lib/parsers.js +54 -4
- package/package.json +1 -1
- package/plugin/plugins/claude-code-kanban/.claude-plugin/plugin.json +1 -1
- package/plugin/plugins/claude-code-kanban/scripts/agent-spy.sh +2 -2
- package/plugin/plugins/claude-code-kanban/scripts/approval-gate.sh +6 -6
- package/plugin/plugins/claude-code-kanban/scripts/context-status.sh +2 -2
- package/plugin/plugins/claude-code-kanban/scripts/postman.js +2 -1
- package/public/app.js +235 -108
- package/public/index.html +7 -3
- package/public/style.css +62 -3
- package/server.js +14 -23
package/public/index.html
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github.min.css" id="hljs-theme-light" disabled>
|
|
23
23
|
<script defer src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
|
|
24
24
|
<script defer src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
25
|
+
<script>window.__STORAGE_NS__ = null;</script>
|
|
25
26
|
<script defer src="/app.js"></script>
|
|
26
27
|
</head>
|
|
27
28
|
<body>
|
|
@@ -355,7 +356,7 @@
|
|
|
355
356
|
</svg>
|
|
356
357
|
</button>
|
|
357
358
|
</div>
|
|
358
|
-
<div class="modal-body
|
|
359
|
+
<div class="modal-body">
|
|
359
360
|
<dl class="shortcuts" id="help-shortcuts"></dl>
|
|
360
361
|
</div>
|
|
361
362
|
</div>
|
|
@@ -611,8 +612,11 @@
|
|
|
611
612
|
<div id="session-picker-modal" class="modal-overlay top-aligned" onclick="closeSessionPicker()">
|
|
612
613
|
<div class="modal session-picker" onclick="event.stopPropagation()">
|
|
613
614
|
<input type="text" id="session-picker-input" class="form-input sp-input" placeholder="Jump to session..." autocomplete="off" spellcheck="false">
|
|
614
|
-
<div
|
|
615
|
-
|
|
615
|
+
<div class="sp-body">
|
|
616
|
+
<div id="session-picker-list" class="sp-list"></div>
|
|
617
|
+
<div id="session-picker-peek" class="sp-peek"></div>
|
|
618
|
+
</div>
|
|
619
|
+
<div class="sp-hint"><kbd>↑</kbd><kbd>↓</kbd> move · <kbd>Enter</kbd> open · <kbd>Ctrl</kbd><kbd>Space</kbd> peek · <kbd>Esc</kbd> close</div>
|
|
616
620
|
</div>
|
|
617
621
|
</div>
|
|
618
622
|
|
package/public/style.css
CHANGED
|
@@ -2264,7 +2264,8 @@ body::before {
|
|
|
2264
2264
|
flex-direction: column;
|
|
2265
2265
|
}
|
|
2266
2266
|
#team-modal .modal-body,
|
|
2267
|
-
#agent-modal .modal-body
|
|
2267
|
+
#agent-modal .modal-body,
|
|
2268
|
+
.modal-help .modal-body {
|
|
2268
2269
|
flex: 1 1 auto;
|
|
2269
2270
|
overflow-y: auto;
|
|
2270
2271
|
min-height: 0;
|
|
@@ -2349,7 +2350,6 @@ body::before {
|
|
|
2349
2350
|
padding: 10px 14px;
|
|
2350
2351
|
background: var(--bg-elevated);
|
|
2351
2352
|
border: 1px solid var(--border);
|
|
2352
|
-
border-left: 3px solid var(--warning);
|
|
2353
2353
|
border-radius: 8px;
|
|
2354
2354
|
}
|
|
2355
2355
|
.info-goal-head {
|
|
@@ -4519,8 +4519,21 @@ body.light .msg-assistant .msg-text {
|
|
|
4519
4519
|
max-width: 440px;
|
|
4520
4520
|
}
|
|
4521
4521
|
|
|
4522
|
+
/* Reference card, not reading material: it stays out of the modal zoom, uses the app's
|
|
4523
|
+
small type, and scrolls its body (rule shared with #team-modal) instead of growing past
|
|
4524
|
+
the viewport cap. */
|
|
4522
4525
|
.modal-help {
|
|
4523
|
-
max-width:
|
|
4526
|
+
max-width: 900px;
|
|
4527
|
+
padding: 16px 20px 20px;
|
|
4528
|
+
display: flex;
|
|
4529
|
+
flex-direction: column;
|
|
4530
|
+
font-size: 13px;
|
|
4531
|
+
}
|
|
4532
|
+
.modal-help .modal-header {
|
|
4533
|
+
margin-bottom: 8px;
|
|
4534
|
+
}
|
|
4535
|
+
.modal-help .modal-title {
|
|
4536
|
+
font-size: 14px;
|
|
4524
4537
|
}
|
|
4525
4538
|
|
|
4526
4539
|
/* One shared grid for both halves (key | label | spacer | key | label): each key
|
|
@@ -4844,13 +4857,59 @@ select.form-input option:checked {
|
|
|
4844
4857
|
font-size: 13px;
|
|
4845
4858
|
}
|
|
4846
4859
|
|
|
4860
|
+
.modal.session-picker.peeking {
|
|
4861
|
+
max-width: 1240px;
|
|
4862
|
+
}
|
|
4863
|
+
|
|
4864
|
+
.sp-body {
|
|
4865
|
+
display: flex;
|
|
4866
|
+
gap: 10px;
|
|
4867
|
+
min-height: 0;
|
|
4868
|
+
}
|
|
4869
|
+
|
|
4870
|
+
.sp-body > * {
|
|
4871
|
+
min-width: 0;
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4847
4874
|
.sp-list {
|
|
4875
|
+
flex: 1;
|
|
4848
4876
|
overflow-y: auto;
|
|
4849
4877
|
display: flex;
|
|
4850
4878
|
flex-direction: column;
|
|
4851
4879
|
gap: 2px;
|
|
4852
4880
|
}
|
|
4853
4881
|
|
|
4882
|
+
.sp-peek {
|
|
4883
|
+
flex: 0 0 42%;
|
|
4884
|
+
overflow-y: auto;
|
|
4885
|
+
border-left: 1px solid var(--border);
|
|
4886
|
+
padding-left: 10px;
|
|
4887
|
+
}
|
|
4888
|
+
|
|
4889
|
+
.modal.session-picker:not(.peeking) .sp-peek {
|
|
4890
|
+
display: none;
|
|
4891
|
+
}
|
|
4892
|
+
|
|
4893
|
+
.sp-peek-title {
|
|
4894
|
+
display: flex;
|
|
4895
|
+
align-items: center;
|
|
4896
|
+
justify-content: space-between;
|
|
4897
|
+
gap: 8px;
|
|
4898
|
+
margin-bottom: 6px;
|
|
4899
|
+
font-family: var(--mono);
|
|
4900
|
+
font-size: 11px;
|
|
4901
|
+
color: var(--text-muted);
|
|
4902
|
+
white-space: nowrap;
|
|
4903
|
+
overflow: hidden;
|
|
4904
|
+
text-overflow: ellipsis;
|
|
4905
|
+
}
|
|
4906
|
+
|
|
4907
|
+
/* Row clicks open the live panel's detail modal by index, which means nothing
|
|
4908
|
+
for a peeked session. The renderer's readOnly mode already drops the buttons. */
|
|
4909
|
+
.sp-peek-items {
|
|
4910
|
+
pointer-events: none;
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4854
4913
|
.sp-row {
|
|
4855
4914
|
display: flex;
|
|
4856
4915
|
align-items: center;
|
package/server.js
CHANGED
|
@@ -34,6 +34,7 @@ const {
|
|
|
34
34
|
} = require('./lib/parsers');
|
|
35
35
|
const { inlineHtmlAssets } = require('./lib/inline-assets');
|
|
36
36
|
const { buildDecision, decisionFileName, isDecisionFile, waitSecondsFrom, isLapsed } = require('./lib/approvals');
|
|
37
|
+
const { getClaudeDir, getArgValue, storageNamespace } = require('./lib/claude-dir');
|
|
37
38
|
|
|
38
39
|
if (process.argv.includes("--install") || process.argv.includes("--uninstall")) {
|
|
39
40
|
const { runInstall, runUninstall } = require("./install");
|
|
@@ -56,30 +57,8 @@ app.use(net.hostGuard);
|
|
|
56
57
|
app.use(net.frameGuard);
|
|
57
58
|
app.use(net.originGuard);
|
|
58
59
|
|
|
59
|
-
// Parse --dir flag for custom Claude directory
|
|
60
|
-
function getClaudeDir() {
|
|
61
|
-
const dirIndex = process.argv.findIndex(arg => arg.startsWith('--dir'));
|
|
62
|
-
if (dirIndex !== -1) {
|
|
63
|
-
const arg = process.argv[dirIndex];
|
|
64
|
-
if (arg.includes('=')) {
|
|
65
|
-
const dir = arg.split('=')[1];
|
|
66
|
-
return dir.startsWith('~') ? dir.replace('~', os.homedir()) : dir;
|
|
67
|
-
} else if (process.argv[dirIndex + 1]) {
|
|
68
|
-
const dir = process.argv[dirIndex + 1];
|
|
69
|
-
return dir.startsWith('~') ? dir.replace('~', os.homedir()) : dir;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return process.env.CLAUDE_CONFIG_DIR || process.env.CLAUDE_DIR || path.join(os.homedir(), '.claude');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
60
|
function getArgUrl(argName, envName) {
|
|
76
|
-
|
|
77
|
-
if (idx !== -1) {
|
|
78
|
-
const arg = process.argv[idx];
|
|
79
|
-
if (arg.includes('=')) return arg.split('=').slice(1).join('=');
|
|
80
|
-
if (process.argv[idx + 1]) return process.argv[idx + 1];
|
|
81
|
-
}
|
|
82
|
-
return process.env[envName] || null;
|
|
61
|
+
return getArgValue(argName) || process.env[envName] || null;
|
|
83
62
|
}
|
|
84
63
|
|
|
85
64
|
const MARKETPLACE_URL = getArgUrl('marketplace-url', 'MARKETPLACE_URL');
|
|
@@ -516,6 +495,18 @@ app.get('/hub-config', (_req, res) => {
|
|
|
516
495
|
res.json({ enabled: !!process.env.CLAUDE_HUB, url: process.env.HUB_URL || null });
|
|
517
496
|
});
|
|
518
497
|
|
|
498
|
+
// app.js reads localStorage synchronously at startup, before any fetch could deliver the
|
|
499
|
+
// namespace, so it is injected into the page instead of served from /hub-config.
|
|
500
|
+
const STORAGE_NS = storageNamespace(CLAUDE_DIR);
|
|
501
|
+
const NS_DECL = 'window.__STORAGE_NS__ = null;';
|
|
502
|
+
const RAW_INDEX = readFileSync(path.join(__dirname, 'public', 'index.html'), 'utf8');
|
|
503
|
+
if (!RAW_INDEX.includes(NS_DECL)) throw new Error(`public/index.html is missing "${NS_DECL}"`);
|
|
504
|
+
const INDEX_HTML = RAW_INDEX.replace(NS_DECL, `window.__STORAGE_NS__ = ${JSON.stringify(STORAGE_NS)};`);
|
|
505
|
+
app.get(['/', '/index.html'], (_req, res) => {
|
|
506
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
507
|
+
res.type('html').send(INDEX_HTML);
|
|
508
|
+
});
|
|
509
|
+
|
|
519
510
|
// Serve static files
|
|
520
511
|
app.get('/sw.js', (_req, res) => {
|
|
521
512
|
res.setHeader('Cache-Control', 'no-cache');
|