fix(sessions): stop pinning the w1-myapp placeholder as Claude's /resume title - #457
shenlvkang-collab wants to merge 1 commit into
Conversation
…ume title Local claude spawns passed the tab name as `--name`. That flag is not only the cross-session peer name: it is also the prompt-box label, the `/resume` picker entry and the terminal title, and a pinned title stops Claude generating its own (`customTitle ?? aiTitle`). So every conversation of a case was listed in `/resume` as the same `w1-myapp`, and none of them got a generated title. On one workspace, 34 of 34 conversations spawned with `--name` had no ai-title, while every conversation spawned without it had one. Only a name the user chose is pinned now: `Session.cliPinnedName` is the name when `nameSource === 'manual'`, carried to the builders as a separate `cliName` so the tab/mux name is untouched. Placeholder and auto names let Claude title the conversation again. A rename in Codeman also reaches `/resume`: the new name is appended to the conversation's transcript as the `custom-title` row `/rename` writes (never creating the file, never writing an empty title). For a pane spawned without `--name` this holds immediately; a pane spawned with one re-appends its own title each turn, so there the new name holds from the next spawn. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks for this, and for doing the legwork: the diagnosis is right and I reproduced it here before reading the code. Two things I would like fixed before merge. 1. const previous = session.name;
if (name === previous) return { name: previous };The tab-strip inline rename already guards this way ( 2. Two smaller things, happy to take them here or in a follow-up:
Nits, no action needed unless you want them: On the trade-off for orchestrators: I am fine with it. The skill joins on the Typecheck, lint, format, frontend syntax and the full test gate are all green here (405 files, 7720 tests), same as CI. Push the two fixes and I will merge. |
Problem
Local Claude spawns pass the tab name as
--name(since #243 / 1.16, for cross-session peer names). But--nameis also, perclaude --help, the name "shown in the prompt box, /resume picker, and terminal title", and a pinned title stops Claude generating its own (/resumeshowscustomTitle ?? aiTitle).So with the default placeholder names, every conversation of a case lands in
/resumeas the samew1-myapp/w2-myapp, and none gets Claude's generated title. On one real workspace: 34 of 34 transcripts spawned with--name w<N>-…have acustom-titlerow and zeroai-titlerows; every transcript spawned without it has one. Renaming the tab in Codeman did not help either, because the rename never reached Claude.Fix
Session.cliPinnedNamereturns the name only whennameSource === 'manual'. It travels to the builders as a separatecliNameonCreateSessionOptions/RespawnPaneOptions(and to the direct-PTYbuildInteractiveArgs), so the tab / mux name is untouched. Placeholder (w1-myapp) and auto names (w1-myapp: fix the login…) now leave Claude to title the conversation, which restores the generated/resumeentry and terminal title./resume.PUT /api/sessions/:id/nameappends the new name to the conversation's transcript as the{"type":"custom-title"}row that/renamewrites (src/claude-session-title.ts). Transcript from the hook-reported path, elsefindClaudeTranscript. Gated oncapabilities.transcript === 'claude-jsonl'and not remote; never creates the file; skips a blank name (an emptycustomTitlewould blank the picker entry instead of falling back). Best effort: a failure logs and the rename still succeeds.A pane that was spawned with
--namere-appends its in-memory title after every turn, so for that case the new name holds from the next spawn (which now pins it). Panes spawned without--namenever write acustom-titleback, so the appended row sticks immediately.Trade-off for orchestrators
A worker quick-started with a
w<N>-shapedsessionName(e.g. the docs'w9-msgtest) is a placeholder by the existingisGeneratedSessionNamerule, so its peer name is now derived.messaging.mdandagent-control-plan.mdnow say to use a descriptive name (msgtest-worker), which is pinned as before.Tests
test/claude-resume-title.test.ts:cliPinnedNamefor placeholder / auto / manual / renamed sessions and the respawn options;appendClaudeCustomTitleappends one row, never creates a file, skips a blank title.test/routes/session-name-routes.test.ts: the rename route appends a CJKcustom-titlewith the transcript's conversation id, and writes nothing for a blank name.npm test: 405 files passed (the one failure on the first run wascli-registry-no-id-branchingcatching amode !== 'claude'I then replaced with thetranscriptcapability).tsc --noEmit, eslint and prettier clean on the touched sources.🤖 Generated with Claude Code