Skip to content

Commit 6da9e9a

Browse files
committed
Support custom-title entries in session summary
Sessions renamed via /rename now display the custom title in the session picker instead of the auto-generated summary.
1 parent b7669be commit 6da9e9a

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/claude_code_transcripts/__init__.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,30 @@ def get_session_summary(filepath, max_length=200):
115115
def _get_jsonl_summary(filepath, max_length=200):
116116
"""Extract summary from JSONL file."""
117117
try:
118+
# First priority: custom title (user renamed session via /rename)
119+
with open(filepath, "r", encoding="utf-8") as f:
120+
for line in f:
121+
line = line.strip()
122+
if not line:
123+
continue
124+
try:
125+
obj = json.loads(line)
126+
if obj.get("type") == "custom-title" and obj.get("customTitle"):
127+
title = obj["customTitle"]
128+
if len(title) > max_length:
129+
return title[: max_length - 3] + "..."
130+
return title
131+
except json.JSONDecodeError:
132+
continue
133+
134+
# Second priority: summary type entries
118135
with open(filepath, "r", encoding="utf-8") as f:
119136
for line in f:
120137
line = line.strip()
121138
if not line:
122139
continue
123140
try:
124141
obj = json.loads(line)
125-
# First priority: summary type entries
126142
if obj.get("type") == "summary" and obj.get("summary"):
127143
summary = obj["summary"]
128144
if len(summary) > max_length:
@@ -131,7 +147,7 @@ def _get_jsonl_summary(filepath, max_length=200):
131147
except json.JSONDecodeError:
132148
continue
133149

134-
# Second pass: find first non-meta user message
150+
# Third pass: find first non-meta user message
135151
with open(filepath, "r", encoding="utf-8") as f:
136152
for line in f:
137153
line = line.strip()

tests/test_generate_html.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,26 @@ def test_truncates_long_summaries(self, tmp_path):
10761076
assert len(summary) <= 100
10771077
assert summary.endswith("...")
10781078

1079+
def test_gets_custom_title_from_jsonl(self, tmp_path):
1080+
"""Test extracting custom title from JSONL file (set via /rename)."""
1081+
jsonl_file = tmp_path / "test.jsonl"
1082+
jsonl_file.write_text(
1083+
'{"type":"custom-title","customTitle":"GIT stuff","sessionId":"abc123"}\n'
1084+
'{"type":"user","message":{"content":"Hello"}}\n'
1085+
)
1086+
summary = get_session_summary(jsonl_file)
1087+
assert summary == "GIT stuff"
1088+
1089+
def test_custom_title_takes_priority_over_summary(self, tmp_path):
1090+
"""Test that custom title takes priority over summary entry."""
1091+
jsonl_file = tmp_path / "test.jsonl"
1092+
jsonl_file.write_text(
1093+
'{"type":"custom-title","customTitle":"My Custom Title","sessionId":"abc123"}\n'
1094+
'{"type":"summary","summary":"Auto-generated summary"}\n'
1095+
)
1096+
summary = get_session_summary(jsonl_file)
1097+
assert summary == "My Custom Title"
1098+
10791099

10801100
class TestFindLocalSessions:
10811101
"""Tests for find_local_sessions which discovers local JSONL files."""

0 commit comments

Comments
 (0)