[BUG] Desktop session list: untitled sessions are titled from the raw first prompt with no disambiguation — automated runs collapse into dozens of identical rows

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 0 comments · opened Aug 10, 2026

Summary

After using Import CLI sessions, the Desktop session list contained large blocks of
visually identical rows. Sessions that have no customTitle are titled from the first
~55 characters of the raw first prompt, truncated, with nothing appended to tell them
apart — no date, cwd, branch, or index.

Any session driven programmatically (agent harness, scheduled task, eval loop) starts
with the same long preamble, so N such sessions render as N indistinguishable rows.
In my list, one preamble produced 49 identical rows and another 35.

This is not the same as #83051. On this build customTitle is imported correctly —
I verified 273 of 274 titled sessions match their CLI transcript exactly, and the
Desktop record does now contain title + titleSource fields (#83051 reports the
record having "no title field of any kind", which appears to be fixed on 2.1.222).
The defect here is purely the fallback path for sessions that never had a title.

Environment

  • Claude Code CLI 2.1.224
  • Desktop-bundled claude-code 2.1.222
  • Claude Desktop 1.26832.0 (macOS 15.5 / Darwin 25.5.0, arm64)
  • Auth: claude.ai subscription

Steps to reproduce

  1. Create several CLI sessions whose first prompt begins with an identical long

preamble and which are never /renamed. Anything programmatic does this naturally:

```bash
for i in 1 2 3 4 5; do
claude -p "You are assisting an operator inside the <repo> repository.

## Your capabilities this turn
You have NO filesystem, shell, git, or search tools. The host supplies file
contents below and applies any edits you return.
...
## Operator message
Task $i" ; done
```

(Scheduled tasks reproduce it too — their prompt opens with a
<scheduled-task name="..." file="..."> wrapper.)

  1. In Desktop, open a session and click Import CLI sessions.
  2. Look at the sidebar.

Expected: the rows are distinguishable — e.g. preamble text is skipped in favour of
the first genuinely user-authored turn, or the row is disambiguated with cwd / branch /
timestamp.

Actual: every one of those sessions renders as the same truncated preamble string.

Evidence

Across ~/Library/Application Support/Claude/claude-code-sessions/**/local_*.json
(1222 records) cross-referenced against ~/.claude/projects/*/<uuid>.jsonl:

titleSource histogram        auto 711 | <none> 510 | user 1
distinct titles              991 across 1222 records

top titles (count × value)
  105 × "Heartbeat"                                            <- scheduled task
   49 × "You are assisting an operator inside the <redacted>"  <- agent preamble
   35 × "You are <redacted>, a calm outreach co-pilot. In ONE"  <- agent preamble
    4 × "Call the wt_list tool now, then call wt_read on READ"
    3 × "Call wt_list now. Then list your exact tool names. B"

Confirming the customTitle path itself is healthy on this build:

transcripts WITH a customTitle
  desktop title == customTitle : 273
  desktop title != customTitle : 1     (benign " (fork)" suffix)
  no customTitle in transcript : 224   <- these are the colliding rows

So ~224 untitled sessions all fall through to prompt-prefix titling, and the ones from
repeated automation collapse onto each other.

Why the current fallback is the wrong source

For a human-typed session the first prompt is a reasonable title. For a machine-driven
session the first prompt is boilerplate, and the distinguishing content (the actual task)
sits hundreds of characters later — past the truncation point. The transcripts contain
no summary record to fall back to (0 of 501 files in my ~/.claude/projects have one),
so the title is the only differentiator the sidebar has, and it carries zero signal.

Suggested fixes (any one would resolve it)

  1. Disambiguate on collision. If a derived title already exists in the list, append

the cwd basename / branch / relative time. Cheap, no heuristics.

  1. Skip boilerplate when deriving. Prefer the first user turn that isn't the

session-opening programmatic prompt — in practice, skip queue-operation content and
<scheduled-task …> wrappers when a later human turn exists.

  1. Derive from the transcript, not the prompt. Generate a short auto-title the way

titleSource: "auto" already does for interactive sessions, and apply it to imported
sessions too rather than leaving titleSource unset (510 records here have no
titleSource at all).

Impact

The list is the only way to find a past session in Desktop. With ~7% of rows sharing one
string and another ~3% sharing a second, "which of these 49 was the one I want?" is only
answerable by opening them one at a time.

---

Adjacent but distinct, for triage:

  • #83051 — customTitle dropped on import → "General coding session". Different fallback

string, and the title/titleSource fields it reports as missing are present on 2.1.222.

  • #32150 — last-prompt text overriding an existing custom-title (VS Code/Linux). Here

there is no custom title to override.

  • #59248 — silent retention cleanup. Related only in that it left 724 of my 1222 rows

pointing at deleted transcripts ("Session not found on disk"); not part of this report.

View original on GitHub ↗