codedash-app 4.0.0 → 4.1.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": "codedash-app",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Termius-style browser dashboard for Claude Code sessions. View, search, resume, and delete sessions with a dark-themed UI.",
5
5
  "bin": {
6
6
  "codedash": "./bin/cli.js"
@@ -0,0 +1,161 @@
1
+ 'use strict';
2
+
3
+ const CHANGELOG = [
4
+ {
5
+ version: '4.0.0',
6
+ date: '2026-04-04',
7
+ title: 'Cross-agent session conversion',
8
+ changes: [
9
+ 'Convert sessions between Claude Code and Codex CLI',
10
+ 'CLI: codedash convert <id> claude/codex',
11
+ 'Convert button in session detail panel',
12
+ 'Atomic writes for safety',
13
+ ],
14
+ },
15
+ {
16
+ version: '3.4.0',
17
+ date: '2026-04-04',
18
+ title: 'CLI search, show, docs',
19
+ changes: [
20
+ 'codedash search <query> — full-text search from terminal',
21
+ 'codedash show <id> — session details with cost and messages',
22
+ 'CLAUDE.md and architecture documentation',
23
+ ],
24
+ },
25
+ {
26
+ version: '3.3.0',
27
+ date: '2026-04-04',
28
+ title: 'Install Agents, author credit',
29
+ changes: [
30
+ 'Install Agents section: Claude Code, Codex, Kiro, OpenCode',
31
+ 'One-click copy install commands',
32
+ 'Author credit in sidebar',
33
+ ],
34
+ },
35
+ {
36
+ version: '3.2.0',
37
+ date: '2026-04-04',
38
+ title: 'Real cost calculation',
39
+ changes: [
40
+ 'Real cost from actual token usage (not file size estimates)',
41
+ 'Model-specific pricing: Opus, Sonnet, Haiku, Codex, GPT-5',
42
+ 'Cache pricing: cache_read 90% discount, cache_create 25% premium',
43
+ 'Detail panel shows real cost with model and token breakdown',
44
+ ],
45
+ },
46
+ {
47
+ version: '3.1.0',
48
+ date: '2026-04-04',
49
+ title: 'Running sessions view',
50
+ changes: [
51
+ 'New "Running" sidebar view with grid layout',
52
+ 'CPU, Memory, PID, Uptime for each active session',
53
+ 'Focus, Details, Replay buttons',
54
+ 'Recently inactive sessions shown below',
55
+ ],
56
+ },
57
+ {
58
+ version: '3.0.0',
59
+ date: '2026-04-04',
60
+ title: 'Session Replay, Cost Analytics',
61
+ changes: [
62
+ 'Session Replay: timeline slider, play/pause, progressive messages',
63
+ 'Cost Analytics dashboard: daily chart, project bars, top sessions',
64
+ 'Focus Terminal button for active sessions',
65
+ ],
66
+ },
67
+ {
68
+ version: '2.1.0',
69
+ date: '2026-04-04',
70
+ title: 'Animated border on live cards',
71
+ changes: [
72
+ 'Conic gradient border spins around LIVE cards',
73
+ 'WAITING cards: static border',
74
+ 'Pulsing dot + LIVE/WAITING badges',
75
+ ],
76
+ },
77
+ {
78
+ version: '2.0.0',
79
+ date: '2026-04-04',
80
+ title: 'Live session detection',
81
+ changes: [
82
+ 'Detect running Claude/Codex processes via PID files',
83
+ 'LIVE (green) and WAITING (yellow) badges with pulse animation',
84
+ 'CPU%, Memory, PID shown on hover',
85
+ 'Polling every 5 seconds',
86
+ ],
87
+ },
88
+ {
89
+ version: '1.9.0',
90
+ date: '2026-04-03',
91
+ title: 'Tags fix, search index, Export/Import UI',
92
+ changes: [
93
+ 'Fixed tag dropdown positioning',
94
+ 'In-memory search index (263ms build, 60s cache)',
95
+ 'Export/Import dialog in sidebar',
96
+ 'codedash update/restart/stop commands',
97
+ ],
98
+ },
99
+ {
100
+ version: '1.6.0',
101
+ date: '2026-04-03',
102
+ title: 'Message extraction fix',
103
+ changes: [
104
+ 'Fixed message extraction for both Claude and Codex',
105
+ 'Hover preview and expand cards working',
106
+ 'Version badge in sidebar',
107
+ ],
108
+ },
109
+ {
110
+ version: '1.5.0',
111
+ date: '2026-04-03',
112
+ title: 'Deep search, hover preview, expandable cards',
113
+ changes: [
114
+ 'Full-text search across all session messages',
115
+ 'Hover tooltip with first 6 messages',
116
+ 'Expand cards inline with first 10 messages',
117
+ ],
118
+ },
119
+ {
120
+ version: '1.4.0',
121
+ date: '2026-04-03',
122
+ title: 'Export/Import for PC migration',
123
+ changes: [
124
+ 'codedash export — archive all sessions as tar.gz',
125
+ 'codedash import — restore on new machine',
126
+ ],
127
+ },
128
+ {
129
+ version: '1.3.0',
130
+ date: '2026-04-03',
131
+ title: 'Trigram fuzzy search',
132
+ changes: [
133
+ 'Fuzzy search with trigram scoring',
134
+ 'Results ranked by relevance',
135
+ ],
136
+ },
137
+ {
138
+ version: '1.1.0',
139
+ date: '2026-04-03',
140
+ title: 'Grid/List toggle, Codex support',
141
+ changes: [
142
+ 'Grid/List layout switcher',
143
+ 'Codex session parsing fixed',
144
+ 'Project navigation from Projects view',
145
+ ],
146
+ },
147
+ {
148
+ version: '1.0.0',
149
+ date: '2026-04-03',
150
+ title: 'Initial release',
151
+ changes: [
152
+ 'Session dashboard with dark theme',
153
+ 'Group by project, timeline, activity heatmap',
154
+ 'Star, tag, delete sessions',
155
+ 'Resume in iTerm2/Terminal.app',
156
+ 'Terminal selector, theme switcher',
157
+ ],
158
+ },
159
+ ];
160
+
161
+ module.exports = { CHANGELOG };
@@ -732,6 +732,11 @@ function render() {
732
732
  return;
733
733
  }
734
734
 
735
+ if (currentView === 'changelog') {
736
+ renderChangelog(content);
737
+ return;
738
+ }
739
+
735
740
  if (currentView === 'running') {
736
741
  renderRunning(content, sessions);
737
742
  return;
@@ -1746,6 +1751,40 @@ function focusSession(sessionId) {
1746
1751
  });
1747
1752
  }
1748
1753
 
1754
+ // ── Changelog view ────────────────────────────────────────────
1755
+
1756
+ async function renderChangelog(container) {
1757
+ container.innerHTML = '<div class="loading">Loading changelog...</div>';
1758
+ try {
1759
+ var resp = await fetch('/api/changelog');
1760
+ var log = await resp.json();
1761
+
1762
+ var html = '<div class="changelog-container">';
1763
+ html += '<h2 class="heatmap-title">Changelog</h2>';
1764
+
1765
+ log.forEach(function(entry, i) {
1766
+ var isNew = i === 0;
1767
+ html += '<div class="changelog-entry' + (isNew ? ' changelog-latest' : '') + '">';
1768
+ html += '<div class="changelog-header">';
1769
+ html += '<span class="changelog-version">v' + escHtml(entry.version) + '</span>';
1770
+ if (isNew) html += '<span class="changelog-new">NEW</span>';
1771
+ html += '<span class="changelog-date">' + escHtml(entry.date) + '</span>';
1772
+ html += '</div>';
1773
+ html += '<div class="changelog-title">' + escHtml(entry.title) + '</div>';
1774
+ html += '<ul class="changelog-list">';
1775
+ entry.changes.forEach(function(c) {
1776
+ html += '<li>' + escHtml(c) + '</li>';
1777
+ });
1778
+ html += '</ul></div>';
1779
+ });
1780
+
1781
+ html += '</div>';
1782
+ container.innerHTML = html;
1783
+ } catch (e) {
1784
+ container.innerHTML = '<div class="empty-state">Failed to load changelog.</div>';
1785
+ }
1786
+ }
1787
+
1749
1788
  // ── Convert session ───────────────────────────────────────────
1750
1789
 
1751
1790
  async function convertTo(sessionId, project, targetFormat) {
@@ -1860,6 +1899,13 @@ async function checkForUpdates() {
1860
1899
  badge.textContent = 'v' + data.current;
1861
1900
  }
1862
1901
 
1902
+ // Show "what's new" if version changed since last visit
1903
+ var lastSeenVersion = localStorage.getItem('codedash-last-version');
1904
+ if (lastSeenVersion && lastSeenVersion !== data.current) {
1905
+ showToast('Updated to v' + data.current + ' — check Changelog!');
1906
+ }
1907
+ localStorage.setItem('codedash-last-version', data.current);
1908
+
1863
1909
  if (data.updateAvailable) {
1864
1910
  if (badge) {
1865
1911
  badge.textContent = 'v' + data.current + ' → v' + data.latest;
@@ -75,6 +75,10 @@
75
75
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
76
76
  Export / Import
77
77
  </div>
78
+ <div class="sidebar-item small" data-view="changelog">
79
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
80
+ Changelog
81
+ </div>
78
82
  <div class="sidebar-author">
79
83
  Made by <a href="https://t.me/neuraldeep" target="_blank">Valerii Kovalskii</a>
80
84
  </div>
@@ -1596,6 +1596,93 @@ body {
1596
1596
  box-shadow: 0 8px 32px rgba(0,0,0,0.12);
1597
1597
  }
1598
1598
 
1599
+ /* ── Changelog ──────────────────────────────────────────────── */
1600
+
1601
+ .changelog-container { padding: 20px; max-width: 700px; }
1602
+
1603
+ .changelog-entry {
1604
+ border-left: 2px solid var(--border);
1605
+ padding: 0 0 24px 20px;
1606
+ margin-left: 8px;
1607
+ position: relative;
1608
+ }
1609
+
1610
+ .changelog-entry::before {
1611
+ content: '';
1612
+ position: absolute;
1613
+ left: -5px;
1614
+ top: 4px;
1615
+ width: 8px;
1616
+ height: 8px;
1617
+ border-radius: 50%;
1618
+ background: var(--text-muted);
1619
+ }
1620
+
1621
+ .changelog-latest {
1622
+ border-left-color: var(--accent-green);
1623
+ }
1624
+
1625
+ .changelog-latest::before {
1626
+ background: var(--accent-green);
1627
+ box-shadow: 0 0 6px var(--accent-green);
1628
+ }
1629
+
1630
+ .changelog-header {
1631
+ display: flex;
1632
+ align-items: center;
1633
+ gap: 8px;
1634
+ margin-bottom: 4px;
1635
+ }
1636
+
1637
+ .changelog-version {
1638
+ font-size: 15px;
1639
+ font-weight: 700;
1640
+ color: var(--text-primary);
1641
+ }
1642
+
1643
+ .changelog-new {
1644
+ font-size: 9px;
1645
+ font-weight: 700;
1646
+ letter-spacing: 0.5px;
1647
+ padding: 2px 6px;
1648
+ border-radius: 4px;
1649
+ background: rgba(74, 222, 128, 0.2);
1650
+ color: var(--accent-green);
1651
+ }
1652
+
1653
+ .changelog-date {
1654
+ font-size: 12px;
1655
+ color: var(--text-muted);
1656
+ margin-left: auto;
1657
+ }
1658
+
1659
+ .changelog-title {
1660
+ font-size: 14px;
1661
+ font-weight: 600;
1662
+ color: var(--text-secondary);
1663
+ margin-bottom: 6px;
1664
+ }
1665
+
1666
+ .changelog-list {
1667
+ list-style: none;
1668
+ padding: 0;
1669
+ margin: 0;
1670
+ }
1671
+
1672
+ .changelog-list li {
1673
+ font-size: 13px;
1674
+ color: var(--text-secondary);
1675
+ padding: 2px 0;
1676
+ line-height: 1.5;
1677
+ }
1678
+
1679
+ .changelog-list li::before {
1680
+ content: '+';
1681
+ color: var(--accent-green);
1682
+ font-weight: 700;
1683
+ margin-right: 8px;
1684
+ }
1685
+
1599
1686
  /* ── Running Sessions View ──────────────────────────────────── */
1600
1687
 
1601
1688
  .running-container { padding: 20px; }
package/src/server.js CHANGED
@@ -6,6 +6,7 @@ const { exec } = require('child_process');
6
6
  const { loadSessions, loadSessionDetail, deleteSession, getGitCommits, exportSessionMarkdown, getSessionPreview, searchFullText, getActiveSessions, getSessionReplay, getCostAnalytics, computeSessionCost } = require('./data');
7
7
  const { detectTerminals, openInTerminal, focusTerminalByPid } = require('./terminals');
8
8
  const { convertSession } = require('./convert');
9
+ const { CHANGELOG } = require('./changelog');
9
10
  const { getHTML } = require('./html');
10
11
 
11
12
  function startServer(port, openBrowser = true) {
@@ -177,6 +178,11 @@ function startServer(port, openBrowser = true) {
177
178
  json(res, data);
178
179
  }
179
180
 
181
+ // ── Changelog ─────────────────────────────
182
+ else if (req.method === 'GET' && pathname === '/api/changelog') {
183
+ json(res, CHANGELOG);
184
+ }
185
+
180
186
  // ── Version check ────────────────────────
181
187
  else if (req.method === 'GET' && pathname === '/api/version') {
182
188
  const pkg = require('../package.json');