claude-code-log 0.2.7__tar.gz → 0.2.8__tar.gz
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.
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/.claude/settings.local.json +6 -1
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/CHANGELOG.md +7 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/PKG-INFO +1 -1
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/templates/transcript.html +298 -2
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/pyproject.toml +1 -1
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/uv.lock +1 -1
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/.github/workflows/ci.yml +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/.github/workflows/docs.yml +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/.gitignore +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/CLAUDE.md +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/LICENSE +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/README.md +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/__init__.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/cli.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/converter.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/models.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/parser.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/py.typed +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/renderer.py +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/claude_code_log/templates/index.html +0 -0
- {claude_code_log-0.2.7 → claude_code_log-0.2.8}/justfile +0 -0
|
@@ -30,7 +30,12 @@
|
|
|
30
30
|
"Bash(open /tmp/test_preview.html)",
|
|
31
31
|
"Bash(open /tmp/test_improved_preview.html)",
|
|
32
32
|
"Bash(open /tmp/test_fixed_preview.html)",
|
|
33
|
-
"Bash(git tag:*)"
|
|
33
|
+
"Bash(git tag:*)",
|
|
34
|
+
"Bash(open /tmp/test_filter.html)",
|
|
35
|
+
"Bash(open /tmp/test_toolbar.html)",
|
|
36
|
+
"Bash(open /tmp/test_sticky.html)",
|
|
37
|
+
"Bash(open /tmp/test_counts.html)",
|
|
38
|
+
"Bash(open /tmp/test_grid.html)"
|
|
34
39
|
],
|
|
35
40
|
"deny": []
|
|
36
41
|
}
|
|
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
## [0.2.8] - 2025-06-23
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Implement filtering by message type in transcripts**
|
|
14
|
+
|
|
15
|
+
|
|
9
16
|
## [0.2.7] - 2025-06-21
|
|
10
17
|
|
|
11
18
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-log
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Convert Claude Code transcript JSONL files to HTML
|
|
5
5
|
Project-URL: Homepage, https://github.com/daaain/claude-code-log
|
|
6
6
|
Project-URL: Issues, https://github.com/daaain/claude-code-log/issues
|
|
@@ -312,6 +312,143 @@
|
|
|
312
312
|
transform: translateY(-2px);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
.filter-toolbar {
|
|
316
|
+
background-color: #f8f9fa66;
|
|
317
|
+
border-radius: 8px;
|
|
318
|
+
padding: 12px 16px;
|
|
319
|
+
margin-bottom: 16px;
|
|
320
|
+
box-shadow: -7px -7px 10px #eeeeee44, 7px 7px 10px #00000011;
|
|
321
|
+
border-left: #ffffff66 1px solid;
|
|
322
|
+
border-top: #ffffff66 1px solid;
|
|
323
|
+
border-bottom: #00000017 1px solid;
|
|
324
|
+
border-right: #00000017 1px solid;
|
|
325
|
+
display: none;
|
|
326
|
+
position: sticky;
|
|
327
|
+
top: 0;
|
|
328
|
+
z-index: 100;
|
|
329
|
+
backdrop-filter: blur(8px);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.filter-toolbar.visible {
|
|
333
|
+
display: grid;
|
|
334
|
+
grid-template-columns: auto 1fr auto;
|
|
335
|
+
align-items: center;
|
|
336
|
+
gap: 16px;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.filter-label {
|
|
340
|
+
white-space: nowrap;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.filter-toggles {
|
|
344
|
+
display: flex;
|
|
345
|
+
flex-wrap: wrap;
|
|
346
|
+
align-items: center;
|
|
347
|
+
gap: 8px;
|
|
348
|
+
justify-content: center;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.filter-messages {
|
|
352
|
+
position: fixed;
|
|
353
|
+
bottom: 140px;
|
|
354
|
+
right: 20px;
|
|
355
|
+
background-color: #e8f4fd66;
|
|
356
|
+
color: #666;
|
|
357
|
+
border: none;
|
|
358
|
+
border-radius: 50%;
|
|
359
|
+
width: 50px;
|
|
360
|
+
height: 50px;
|
|
361
|
+
font-size: 1.2em;
|
|
362
|
+
line-height: 1;
|
|
363
|
+
cursor: pointer;
|
|
364
|
+
display: flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
justify-content: center;
|
|
367
|
+
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
|
|
368
|
+
transition: background-color 0.3s, transform 0.2s;
|
|
369
|
+
z-index: 1000;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.filter-messages:hover {
|
|
373
|
+
background-color: #e8f4fdcc;
|
|
374
|
+
transform: translateY(-2px);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.filter-messages.active {
|
|
378
|
+
background-color: #fff3cd66;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.filter-toolbar h3 {
|
|
382
|
+
margin: 0;
|
|
383
|
+
font-size: 1em;
|
|
384
|
+
color: #495057;
|
|
385
|
+
font-weight: 600;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.filter-toggle {
|
|
389
|
+
padding: 6px 12px;
|
|
390
|
+
border: 1px solid #dee2e6;
|
|
391
|
+
border-radius: 20px;
|
|
392
|
+
background-color: transparent;
|
|
393
|
+
color: #495057;
|
|
394
|
+
font-size: 0.85em;
|
|
395
|
+
font-weight: 500;
|
|
396
|
+
cursor: pointer;
|
|
397
|
+
transition: all 0.2s;
|
|
398
|
+
display: flex;
|
|
399
|
+
align-items: center;
|
|
400
|
+
gap: 4px;
|
|
401
|
+
white-space: nowrap;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.filter-toggle:hover {
|
|
405
|
+
background-color: #ffffff99;
|
|
406
|
+
transform: translateY(-1px);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.filter-toggle.active {
|
|
410
|
+
background-color: #ffffffaa;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.filter-toggle.active:hover {
|
|
414
|
+
background-color: #ffffff66;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.filter-actions {
|
|
418
|
+
display: flex;
|
|
419
|
+
gap: 6px;
|
|
420
|
+
white-space: nowrap;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.filter-action-btn {
|
|
424
|
+
padding: 4px 8px;
|
|
425
|
+
border: 1px solid #dee2e6;
|
|
426
|
+
border-radius: 4px;
|
|
427
|
+
background-color: #ffffff66;
|
|
428
|
+
color: #6c757d;
|
|
429
|
+
font-size: 0.75em;
|
|
430
|
+
cursor: pointer;
|
|
431
|
+
transition: background-color 0.2s;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.filter-action-btn:hover {
|
|
435
|
+
background-color: #ffffff99;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.filter-toggle .count {
|
|
439
|
+
opacity: 0.7;
|
|
440
|
+
font-size: 0.9em;
|
|
441
|
+
margin-left: 2px;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.filter-toggle.active .count {
|
|
445
|
+
opacity: 1;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.message.filtered-hidden {
|
|
449
|
+
display: none;
|
|
450
|
+
}
|
|
451
|
+
|
|
315
452
|
.session-summary {
|
|
316
453
|
background-color: #ffffff66;
|
|
317
454
|
border-left: #4caf5088 4px solid;
|
|
@@ -442,6 +579,31 @@
|
|
|
442
579
|
<body>
|
|
443
580
|
<h1 id="title">{{ title }}</h1>
|
|
444
581
|
|
|
582
|
+
<!-- Filter Toolbar -->
|
|
583
|
+
<div class="filter-toolbar">
|
|
584
|
+
<div class="filter-label">
|
|
585
|
+
<h3>Filter:</h3>
|
|
586
|
+
</div>
|
|
587
|
+
<div class="filter-toggles">
|
|
588
|
+
<button class="filter-toggle active" data-type="user">🤷 User <span class="count">(0)</span></button>
|
|
589
|
+
<button class="filter-toggle active" data-type="assistant">🤖 Assistant <span
|
|
590
|
+
class="count">(0)</span></button>
|
|
591
|
+
<button class="filter-toggle active" data-type="system">⚙️ System <span class="count">(0)</span></button>
|
|
592
|
+
<button class="filter-toggle active" data-type="tool_use">🛠️ Tool Use <span
|
|
593
|
+
class="count">(0)</span></button>
|
|
594
|
+
<button class="filter-toggle active" data-type="tool_result">🧰 Tool Results <span
|
|
595
|
+
class="count">(0)</span></button>
|
|
596
|
+
<button class="filter-toggle active" data-type="thinking">💭 Thinking <span
|
|
597
|
+
class="count">(0)</span></button>
|
|
598
|
+
<button class="filter-toggle active" data-type="image">🖼️ Images <span class="count">(0)</span></button>
|
|
599
|
+
</div>
|
|
600
|
+
<div class="filter-actions">
|
|
601
|
+
<button class="filter-action-btn" id="selectAll">All</button>
|
|
602
|
+
<button class="filter-action-btn" id="selectNone">None</button>
|
|
603
|
+
<button class="filter-action-btn" id="closeFilters" title="Close filters">✕</button>
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
|
|
445
607
|
{% if sessions and sessions|length > 1 %}
|
|
446
608
|
<div class='navigation'>
|
|
447
609
|
<h2>Sessions</h2>
|
|
@@ -503,13 +665,21 @@
|
|
|
503
665
|
{% endif %}
|
|
504
666
|
{% endfor %}
|
|
505
667
|
|
|
668
|
+
<button class="filter-messages" id="filterMessages" title="Toggle filters">🔍</button>
|
|
506
669
|
<button class="toggle-details" id="toggleDetails" title="Toggle all details">📋</button>
|
|
507
670
|
<a class="scroll-top" title="Scroll to top" href="#title">🔝</a>
|
|
508
671
|
|
|
509
672
|
<script>
|
|
510
673
|
document.addEventListener('DOMContentLoaded', function () {
|
|
511
674
|
const toggleButton = document.getElementById('toggleDetails');
|
|
512
|
-
|
|
675
|
+
const filterButton = document.getElementById('filterMessages');
|
|
676
|
+
const filterToolbar = document.querySelector('.filter-toolbar');
|
|
677
|
+
const selectAllButton = document.getElementById('selectAll');
|
|
678
|
+
const selectNoneButton = document.getElementById('selectNone');
|
|
679
|
+
const closeFiltersButton = document.getElementById('closeFilters');
|
|
680
|
+
const filterToggles = document.querySelectorAll('.filter-toggle');
|
|
681
|
+
|
|
682
|
+
// Toggle details functionality
|
|
513
683
|
function updateToggleButton() {
|
|
514
684
|
const allDetails = document.querySelectorAll('details.collapsible-details');
|
|
515
685
|
const openCount = document.querySelectorAll('details[open].collapsible-details').length;
|
|
@@ -544,8 +714,134 @@
|
|
|
544
714
|
|
|
545
715
|
toggleButton.addEventListener('click', toggleAllDetails);
|
|
546
716
|
|
|
547
|
-
//
|
|
717
|
+
// Filter toolbar toggle functionality
|
|
718
|
+
function toggleFilterToolbar() {
|
|
719
|
+
const isVisible = filterToolbar.classList.contains('visible');
|
|
720
|
+
if (isVisible) {
|
|
721
|
+
filterToolbar.classList.remove('visible');
|
|
722
|
+
filterButton.classList.remove('active');
|
|
723
|
+
filterButton.title = 'Show filters';
|
|
724
|
+
} else {
|
|
725
|
+
filterToolbar.classList.add('visible');
|
|
726
|
+
filterButton.classList.add('active');
|
|
727
|
+
filterButton.title = 'Hide filters';
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
filterButton.addEventListener('click', toggleFilterToolbar);
|
|
732
|
+
closeFiltersButton.addEventListener('click', toggleFilterToolbar);
|
|
733
|
+
|
|
734
|
+
// Count messages by type and update button labels
|
|
735
|
+
function updateMessageCounts() {
|
|
736
|
+
const messageTypes = ['user', 'assistant', 'system', 'tool_use', 'tool_result', 'thinking', 'image'];
|
|
737
|
+
|
|
738
|
+
messageTypes.forEach(type => {
|
|
739
|
+
const messages = document.querySelectorAll(`.message.${type}:not(.session-header)`);
|
|
740
|
+
const count = messages.length;
|
|
741
|
+
const toggle = document.querySelector(`[data-type="${type}"]`);
|
|
742
|
+
const countSpan = toggle.querySelector('.count');
|
|
743
|
+
|
|
744
|
+
if (countSpan) {
|
|
745
|
+
countSpan.textContent = `(${count})`;
|
|
746
|
+
|
|
747
|
+
// Hide toggles for message types with 0 count
|
|
748
|
+
if (count === 0) {
|
|
749
|
+
toggle.style.display = 'none';
|
|
750
|
+
} else {
|
|
751
|
+
toggle.style.display = 'flex';
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Filter functionality
|
|
758
|
+
function applyFilter() {
|
|
759
|
+
const activeTypes = Array.from(filterToggles)
|
|
760
|
+
.filter(toggle => toggle.classList.contains('active'))
|
|
761
|
+
.map(toggle => toggle.dataset.type);
|
|
762
|
+
|
|
763
|
+
// Show/hide messages based on active toggle buttons
|
|
764
|
+
const allMessages = document.querySelectorAll('.message:not(.session-header)');
|
|
765
|
+
allMessages.forEach(message => {
|
|
766
|
+
const shouldShow = activeTypes.some(type => message.classList.contains(type));
|
|
767
|
+
if (shouldShow) {
|
|
768
|
+
message.classList.remove('filtered-hidden');
|
|
769
|
+
} else {
|
|
770
|
+
message.classList.add('filtered-hidden');
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// Update visible counts in real-time
|
|
775
|
+
updateVisibleCounts();
|
|
776
|
+
|
|
777
|
+
// Update filter button appearance based on whether all types are selected
|
|
778
|
+
const allTypesSelected = activeTypes.length === filterToggles.length;
|
|
779
|
+
if (!allTypesSelected && filterToolbar.classList.contains('visible')) {
|
|
780
|
+
filterButton.classList.add('active');
|
|
781
|
+
} else if (allTypesSelected && filterToolbar.classList.contains('visible')) {
|
|
782
|
+
filterButton.classList.add('active');
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
function updateVisibleCounts() {
|
|
787
|
+
const messageTypes = ['user', 'assistant', 'system', 'tool_use', 'tool_result', 'thinking', 'image'];
|
|
788
|
+
|
|
789
|
+
messageTypes.forEach(type => {
|
|
790
|
+
const visibleMessages = document.querySelectorAll(`.message.${type}:not(.session-header):not(.filtered-hidden)`);
|
|
791
|
+
const totalMessages = document.querySelectorAll(`.message.${type}:not(.session-header)`);
|
|
792
|
+
const visibleCount = visibleMessages.length;
|
|
793
|
+
const totalCount = totalMessages.length;
|
|
794
|
+
|
|
795
|
+
const toggle = document.querySelector(`[data-type="${type}"]`);
|
|
796
|
+
const countSpan = toggle.querySelector('.count');
|
|
797
|
+
|
|
798
|
+
if (countSpan && totalCount > 0) {
|
|
799
|
+
// Show "visible/total" format when filtering is active
|
|
800
|
+
const activeTypes = Array.from(filterToggles)
|
|
801
|
+
.filter(toggle => toggle.classList.contains('active'))
|
|
802
|
+
.map(toggle => toggle.dataset.type);
|
|
803
|
+
|
|
804
|
+
const isFiltering = activeTypes.length < filterToggles.length;
|
|
805
|
+
|
|
806
|
+
if (isFiltering && visibleCount !== totalCount) {
|
|
807
|
+
countSpan.textContent = `(${visibleCount}/${totalCount})`;
|
|
808
|
+
} else {
|
|
809
|
+
countSpan.textContent = `(${totalCount})`;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
function toggleFilter(button) {
|
|
816
|
+
button.classList.toggle('active');
|
|
817
|
+
applyFilter();
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function selectAllTypes() {
|
|
821
|
+
filterToggles.forEach(toggle => {
|
|
822
|
+
toggle.classList.add('active');
|
|
823
|
+
});
|
|
824
|
+
applyFilter();
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function selectNoTypes() {
|
|
828
|
+
filterToggles.forEach(toggle => {
|
|
829
|
+
toggle.classList.remove('active');
|
|
830
|
+
});
|
|
831
|
+
applyFilter();
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// Event listeners for filter toggles
|
|
835
|
+
filterToggles.forEach(toggle => {
|
|
836
|
+
toggle.addEventListener('click', () => toggleFilter(toggle));
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
selectAllButton.addEventListener('click', selectAllTypes);
|
|
840
|
+
selectNoneButton.addEventListener('click', selectNoTypes);
|
|
841
|
+
|
|
842
|
+
// Initialize button state and message counts
|
|
548
843
|
updateToggleButton();
|
|
844
|
+
updateMessageCounts();
|
|
549
845
|
});
|
|
550
846
|
</script>
|
|
551
847
|
</body>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|