claude-starter 1.3.1 → 1.3.3

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.
Files changed (2) hide show
  1. package/index.js +37 -5
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -393,7 +393,9 @@ function formatTimestamp(ts) {
393
393
  if (!ts) return 'unknown';
394
394
  const d = new Date(ts);
395
395
  const now = new Date();
396
- const diffDays = Math.floor((now.getTime() - d.getTime()) / 86400000);
396
+ const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
397
+ const targetStart = new Date(d.getFullYear(), d.getMonth(), d.getDate());
398
+ const diffDays = Math.round((todayStart.getTime() - targetStart.getTime()) / 86400000);
397
399
  const time = d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
398
400
  if (diffDays === 0) return `Today ${time}`;
399
401
  if (diffDays === 1) return `Yesterday ${time}`;
@@ -445,6 +447,16 @@ function runListMode(limit) {
445
447
  function createApp() {
446
448
  const allSessions = loadAllSessions();
447
449
  const meta = loadMeta();
450
+
451
+ // Apply meta customTitles — these take priority over JSONL titles
452
+ // so renames persist even after continuing a conversation
453
+ for (const session of allSessions) {
454
+ const sm = meta.sessions[session.sessionId];
455
+ if (sm && sm.customTitle) {
456
+ session.customTitle = sm.customTitle;
457
+ }
458
+ }
459
+
448
460
  let filteredSessions = [...allSessions];
449
461
  let selectedIndex = -1; // -1 = "New Session", 0+ = session index
450
462
  let filterText = '';
@@ -530,6 +542,16 @@ function createApp() {
530
542
  });
531
543
 
532
544
  function updateFooter() {
545
+ if (isSearchMode) {
546
+ const keys = [
547
+ '{#e0af68-fg}{bold}↵{/} {#e0af68-fg}Confirm{/}',
548
+ '{#7aa2f7-fg}{bold}↑↓{/} {#7aa2f7-fg}Navigate{/}',
549
+ '{#565f89-fg}{bold}⌫{/} {#565f89-fg}Delete char{/}',
550
+ '{#565f89-fg}{bold}Esc{/} {#565f89-fg}Clear{/}',
551
+ ];
552
+ footer.setContent(`\n ${keys.join(' {#414868-fg}│{/} ')}`);
553
+ return;
554
+ }
533
555
  const keys = [
534
556
  '{#9ece6a-fg}{bold}n{/} {#9ece6a-fg}New{/}',
535
557
  '{#7aa2f7-fg}{bold}↵{/} {#7aa2f7-fg}Resume{/}',
@@ -652,6 +674,10 @@ function createApp() {
652
674
  const session = filteredSessions[selectedIndex];
653
675
  loadSessionDetail(session);
654
676
 
677
+ // Meta customTitle takes priority over JSONL
678
+ const sm = meta.sessions[session.sessionId];
679
+ if (sm && sm.customTitle) session.customTitle = sm.customTitle;
680
+
655
681
  const color = getProjectColor(session.project, projectColorMap);
656
682
  let c = '';
657
683
  const sep = ` {#414868-fg}${'─'.repeat(44)}{/}`;
@@ -841,11 +867,13 @@ function createApp() {
841
867
  }
842
868
 
843
869
  screen.key(['down'], () => {
844
- if (renameMode || popupOpen || isSearchMode) return;
870
+ if (renameMode || popupOpen) return;
871
+ if (isSearchMode) { isSearchMode = false; updateHeader(); updateFooter(); screen.render(); }
845
872
  moveSelection(1);
846
873
  });
847
874
  screen.key(['up'], () => {
848
- if (renameMode || popupOpen || isSearchMode) return;
875
+ if (renameMode || popupOpen) return;
876
+ if (isSearchMode) { isSearchMode = false; updateHeader(); updateFooter(); screen.render(); }
849
877
  moveSelection(-1);
850
878
  });
851
879
  screen.key(['home'], () => {
@@ -878,7 +906,9 @@ function createApp() {
878
906
  // Search
879
907
  screen.key(['/'], () => {
880
908
  if (renameMode || isSearchMode) return;
881
- isSearchMode = true; filterText = ''; applyFilter();
909
+ isSearchMode = true;
910
+ if (!filterText) filterText = ''; // keep existing filterText if any
911
+ updateHeader(); updateFooter(); screen.render();
882
912
  });
883
913
 
884
914
  screen.on('keypress', (ch, key) => {
@@ -946,7 +976,7 @@ function createApp() {
946
976
  }
947
977
 
948
978
  if (!isSearchMode) return;
949
- if (key.name === 'return' || key.name === 'enter') { isSearchMode = false; renderAll(); return; }
979
+ if (key.name === 'return' || key.name === 'enter') { isSearchMode = false; searchJustConfirmed = true; renderAll(); return; }
950
980
  if (key.name === 'escape') { isSearchMode = false; filterText = ''; applyFilter(); return; }
951
981
  // Only accept printable characters (exclude control chars like \r \n \t)
952
982
  if (ch && ch.length === 1 && ch.charCodeAt(0) >= 32 && !key.ctrl && !key.meta) { filterText += ch; selectedIndex = -1; applyFilter(); }
@@ -1005,10 +1035,12 @@ function createApp() {
1005
1035
  // Track the rename confirm popup and its session for Enter handling
1006
1036
  let renameConfirmPopup = null;
1007
1037
  let renameConfirmSession = null;
1038
+ let searchJustConfirmed = false;
1008
1039
 
1009
1040
  screen.key(['enter'], () => {
1010
1041
  if (renameMode) return;
1011
1042
  if (renameJustFinished) return;
1043
+ if (searchJustConfirmed) { searchJustConfirmed = false; return; }
1012
1044
  // Handle rename confirm popup Enter
1013
1045
  if (renameConfirmPopup && popupOpen) {
1014
1046
  const session = renameConfirmSession;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-starter",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "A beautiful terminal UI for managing Claude Code sessions — start new or resume past conversations",
5
5
  "main": "index.js",
6
6
  "bin": {