claude-home 1.2.2 → 1.4.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/bin/cli.js +2 -4
- package/package.json +1 -1
- package/public/index.html +57 -16
- package/server.js +18 -4
package/bin/cli.js
CHANGED
|
@@ -66,10 +66,8 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
66
66
|
if (subcommand === 'stop') {
|
|
67
67
|
const { execSync } = require('child_process');
|
|
68
68
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
execSync(`kill ${pid}`);
|
|
72
|
-
console.log(`✓ claude-home stopped (pid ${pid})`);
|
|
69
|
+
execSync(`lsof -ti:${port} | xargs kill -9`, { stdio: 'ignore' });
|
|
70
|
+
console.log(`✓ claude-home stopped`);
|
|
73
71
|
} catch { console.log(`No claude-home process found on port ${port}`); }
|
|
74
72
|
process.exit(0);
|
|
75
73
|
}
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -397,6 +397,10 @@
|
|
|
397
397
|
|
|
398
398
|
.message { display: flex; flex-direction: column; margin-bottom: 24px; }
|
|
399
399
|
|
|
400
|
+
.message.assistant { flex-direction: row; align-items: flex-start; gap: 10px; }
|
|
401
|
+
.message.assistant .message-role { margin-bottom: 0; flex-shrink: 0; padding-top: 3px; }
|
|
402
|
+
.message.assistant .message-bubble .md-content > *:first-child { margin-top: 0; }
|
|
403
|
+
|
|
400
404
|
.message-role {
|
|
401
405
|
font-size: 10px;
|
|
402
406
|
font-weight: 700;
|
|
@@ -431,7 +435,10 @@
|
|
|
431
435
|
align-items: center;
|
|
432
436
|
gap: 8px;
|
|
433
437
|
margin-top: 6px;
|
|
438
|
+
opacity: 0;
|
|
439
|
+
transition: opacity 0.15s;
|
|
434
440
|
}
|
|
441
|
+
.message:hover .message-footer { opacity: 1; }
|
|
435
442
|
|
|
436
443
|
.msg-meta { font-size: 10.5px; color: var(--ink-3); }
|
|
437
444
|
|
|
@@ -443,13 +450,16 @@
|
|
|
443
450
|
.md-content p { margin: 6px 0; }
|
|
444
451
|
.md-content ul, .md-content ol { padding-left: 20px; margin: 6px 0; }
|
|
445
452
|
.md-content li { margin: 3px 0; }
|
|
446
|
-
.md-content code {
|
|
453
|
+
.md-content code, .inline-code {
|
|
447
454
|
background: var(--canvas);
|
|
448
455
|
border: 1px solid var(--rule);
|
|
449
456
|
padding: 1px 5px;
|
|
457
|
+
border-radius: 3px;
|
|
450
458
|
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
451
459
|
font-size: 12px;
|
|
452
460
|
}
|
|
461
|
+
/* keep inline hljs within the bubble background, don't override with theme's white */
|
|
462
|
+
code.inline-code.hljs { background: var(--canvas); }
|
|
453
463
|
.md-content pre {
|
|
454
464
|
background: var(--white);
|
|
455
465
|
border: 1px solid var(--rule);
|
|
@@ -1959,7 +1969,7 @@
|
|
|
1959
1969
|
</div>
|
|
1960
1970
|
</div>
|
|
1961
1971
|
<div style="display:flex;gap:6px;align-items:center;flex-shrink:0">
|
|
1962
|
-
<button class="btn btn-sm" :class="cleanMode ? 'btn-primary' : ''" style="background:var(--canvas-2);color:var(--ink)" :style="cleanMode ? 'background:var(--blue);color:#fff' : ''" @click="cleanMode=!cleanMode" title="Toggle
|
|
1972
|
+
<button class="btn btn-sm" :class="cleanMode ? 'btn-primary' : ''" style="background:var(--canvas-2);color:var(--ink)" :style="cleanMode ? 'background:var(--blue);color:#fff' : ''" @click="cleanMode=!cleanMode" title="Toggle focus view">Focus</button>
|
|
1963
1973
|
<div style="position:relative">
|
|
1964
1974
|
<button class="btn btn-sm" style="background:var(--canvas-2);color:var(--ink);display:flex;align-items:center;gap:4px" @click="exportDropOpen=!exportDropOpen" @click.outside="exportDropOpen=false">
|
|
1965
1975
|
Export <svg width="10" height="10" viewBox="0 0 10 10" fill="currentColor"><path d="M2 3.5L5 6.5L8 3.5"/></svg>
|
|
@@ -1992,8 +2002,11 @@
|
|
|
1992
2002
|
<div class="message-bubble">
|
|
1993
2003
|
<template x-for="(block, bi) in getUserBlocks(msg)" :key="bi">
|
|
1994
2004
|
<div>
|
|
2005
|
+
<template x-if="block.type === 'slash-command'">
|
|
2006
|
+
<span style="display:inline-flex;align-items:center;gap:4px;font-size:11px;padding:2px 8px;border-radius:4px;background:var(--canvas-2);border:1px solid var(--rule-2);color:var(--ink-2);font-family:monospace" x-text="block.command"></span>
|
|
2007
|
+
</template>
|
|
1995
2008
|
<template x-if="block.type === 'text'">
|
|
1996
|
-
<div x-
|
|
2009
|
+
<div x-html="renderInlineCode(block.text)" style="white-space:pre-wrap"></div>
|
|
1997
2010
|
</template>
|
|
1998
2011
|
<template x-if="block.type === 'tool_result' && !cleanMode">
|
|
1999
2012
|
<div class="collapsible" style="margin-top:6px">
|
|
@@ -2022,7 +2035,9 @@
|
|
|
2022
2035
|
<!-- Assistant message -->
|
|
2023
2036
|
<template x-if="msg.type === 'assistant'">
|
|
2024
2037
|
<div class="message assistant" x-show="!cleanMode || msgHasText(msg)">
|
|
2025
|
-
<div class="message-role">
|
|
2038
|
+
<div class="message-role">
|
|
2039
|
+
<svg fill="currentColor" fill-rule="evenodd" width="16" height="16" viewBox="0 0 24 24" style="color:var(--ink-3)" xmlns="http://www.w3.org/2000/svg"><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"></path></svg>
|
|
2040
|
+
</div>
|
|
2026
2041
|
<div class="message-bubble">
|
|
2027
2042
|
<template x-for="(block, bi) in getAssistantBlocks(msg)" :key="bi">
|
|
2028
2043
|
<div>
|
|
@@ -3811,14 +3826,26 @@
|
|
|
3811
3826
|
|
|
3812
3827
|
<script>
|
|
3813
3828
|
marked.setOptions({ gfm: true, breaks: true });
|
|
3814
|
-
marked.use({ renderer: {
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3829
|
+
marked.use({ renderer: {
|
|
3830
|
+
code(token) {
|
|
3831
|
+
const lang = token.lang || '';
|
|
3832
|
+
const valid = hljs.getLanguage(lang) ? lang : 'plaintext';
|
|
3833
|
+
try {
|
|
3834
|
+
const highlighted = hljs.highlight(token.text, { language: valid }).value;
|
|
3835
|
+
return `<pre><code class="hljs language-${valid}">${highlighted}</code></pre>`;
|
|
3836
|
+
} catch { return `<pre><code>${token.text}</code></pre>`; }
|
|
3837
|
+
},
|
|
3838
|
+
codespan(token) {
|
|
3839
|
+
try {
|
|
3840
|
+
const highlighted = hljs.highlightAuto(token.text).value;
|
|
3841
|
+
return `<code class="inline-code hljs">${highlighted}</code>`;
|
|
3842
|
+
} catch { return `<code class="inline-code">${token.text}</code>`; }
|
|
3843
|
+
}
|
|
3844
|
+
}});
|
|
3845
|
+
|
|
3846
|
+
function hljsInline(text) {
|
|
3847
|
+
try { return hljs.highlightAuto(text).value; } catch { return text; }
|
|
3848
|
+
}
|
|
3822
3849
|
|
|
3823
3850
|
function app() {
|
|
3824
3851
|
return {
|
|
@@ -3854,7 +3881,7 @@
|
|
|
3854
3881
|
deletingSession: false,
|
|
3855
3882
|
exportDropOpen: false,
|
|
3856
3883
|
exportMsg: '',
|
|
3857
|
-
cleanMode:
|
|
3884
|
+
cleanMode: true,
|
|
3858
3885
|
planExportMsg: '',
|
|
3859
3886
|
planExportOpen: false,
|
|
3860
3887
|
sidebarW: parseInt(localStorage.getItem('cm:sidebarW') || '260'),
|
|
@@ -4253,9 +4280,13 @@
|
|
|
4253
4280
|
|
|
4254
4281
|
getUserBlocks(msg) {
|
|
4255
4282
|
const content = msg.message?.content;
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4283
|
+
const blocks = typeof content === 'string' ? [{ type: 'text', text: content }] : Array.isArray(content) ? content : [];
|
|
4284
|
+
return blocks.map(b => {
|
|
4285
|
+
if (b.type !== 'text') return b;
|
|
4286
|
+
const m = b.text?.match(/<command-name>([^<]+)<\/command-name>/);
|
|
4287
|
+
if (m) return { type: 'slash-command', command: m[1].startsWith('/') ? m[1] : '/' + m[1] };
|
|
4288
|
+
return b;
|
|
4289
|
+
});
|
|
4259
4290
|
},
|
|
4260
4291
|
|
|
4261
4292
|
getAssistantBlocks(msg) {
|
|
@@ -4295,6 +4326,16 @@
|
|
|
4295
4326
|
|
|
4296
4327
|
renderMd(text) { try { return marked.parse(text); } catch { return text; } },
|
|
4297
4328
|
|
|
4329
|
+
renderInlineCode(text) {
|
|
4330
|
+
const esc = text
|
|
4331
|
+
.replace(/&/g, '&').replace(/</g, '<')
|
|
4332
|
+
.replace(/>/g, '>').replace(/"/g, '"');
|
|
4333
|
+
return esc.replace(/`([^`\n]+)`/g, (_, code) => {
|
|
4334
|
+
const decoded = code.replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&').replace(/"/g,'"');
|
|
4335
|
+
return `<code class="inline-code hljs">${hljsInline(decoded)}</code>`;
|
|
4336
|
+
});
|
|
4337
|
+
},
|
|
4338
|
+
|
|
4298
4339
|
shortProjectName(p) {
|
|
4299
4340
|
if (!p) return 'unknown';
|
|
4300
4341
|
const parts = p.replace(/\\/g, '/').split('/');
|
package/server.js
CHANGED
|
@@ -200,10 +200,15 @@ async function readFirstMessage(filePath) {
|
|
|
200
200
|
if (!timestamp && obj.timestamp) timestamp = obj.timestamp;
|
|
201
201
|
if (!firstPrompt && obj.type === 'user') {
|
|
202
202
|
const content = obj.message?.content;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
const isHook = typeof content === 'string'
|
|
204
|
+
? content.includes('<local-command-caveat>')
|
|
205
|
+
: Array.isArray(content) && content.every(c => c.type === 'text' && c.text?.includes('<local-command-caveat>'));
|
|
206
|
+
if (!isHook) {
|
|
207
|
+
if (typeof content === 'string' && !content.includes('<command-name>')) firstPrompt = content.slice(0, 300);
|
|
208
|
+
else if (Array.isArray(content)) {
|
|
209
|
+
const txt = content.find(c => c.type === 'text' && !c.text?.includes('<command-name>') && !c.text?.includes('<local-command-caveat>'));
|
|
210
|
+
if (txt) firstPrompt = txt.text.slice(0, 300);
|
|
211
|
+
}
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
214
|
if (firstPrompt && gitBranch && count > 5) break;
|
|
@@ -291,6 +296,15 @@ async function parseJsonl(filePath, { includeNoise = false, searchText = null }
|
|
|
291
296
|
try { obj = JSON.parse(line); } catch { continue; }
|
|
292
297
|
if (!includeNoise && NOISE_TYPES.has(obj.type)) continue;
|
|
293
298
|
|
|
299
|
+
// Filter out hook output messages (local-command-caveat)
|
|
300
|
+
if (obj.type === 'user') {
|
|
301
|
+
const c = obj.message?.content;
|
|
302
|
+
const isHookMsg = typeof c === 'string'
|
|
303
|
+
? c.includes('<local-command-caveat>')
|
|
304
|
+
: Array.isArray(c) && c.every(b => b.type === 'text' && b.text?.includes('<local-command-caveat>'));
|
|
305
|
+
if (isHookMsg) continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
294
308
|
if (searchText) {
|
|
295
309
|
const text = extractText(obj);
|
|
296
310
|
if (!text.toLowerCase().includes(searchText.toLowerCase())) continue;
|