[VSCode] No way to disable AI session titles, and one engine path overwrites a user-set title for non-active sessions

Status Open
Reported on v2.1.283
Maintainer reply None cached
Activity 0 comments · opened Sep 27, 2026

Environment

| | |
|---|---|
| VS Code extension | 2.1.283 (also reproduced on 2.1.280) |
| Engine | bundled resources/native-binary/claude.exe, same version as the extension |
| OS | Windows 11 Home 26200 |
| Usage pattern | many parallel session tabs in VS Code, terminal CLI almost never used |

Summary

I rename session tabs so I can tell parallel sessions apart. The AI-generated title keeps replacing my name. Two separate problems make this unfixable from the user side:

  1. There is no setting to turn AI session titles off. claude-code-settings.schema.json in 2.1.283 contains only "title" and "terminalTitleFromRename" — no autoTitle / aiTitle / generateTitle / sessionTitle key. The extension's package.json contributes exactly four config keys (acceptProposedDiff, insertAtMentioned, rejectProposedDiff, viewingProposedDiff), none title-related. DISABLE_TERMINAL_TITLE only affects the terminal window title.
  2. One engine write path appends ai-title without checking whether a user title exists. Details below.

There is also no way to name a session before it exists: Claude Code: Rename Session Tab needs a live session, and by then the AI titler has already been triggered by the first message. So "just rename it first" is not available to the user.

Evidence: 26 renamed sessions from one project

For every session that has a custom-title.json sidecar, I recorded the line number of the first custom-title record and of the first ai-title record in the transcript, plus the record counts. Titles replaced with placeholders.

| Session (prefix) | 1st user | 1st custom-title | 1st ai-title | #custom-title | #ai-title | Last title record |
|---|---|---|---|---|---|---|
| 70dd8913 | 4 | 1 | none | 36 | 0 | custom |
| fe53cf87 | 4 | 1 | none | 41 | 0 | custom |
| b8bd1cd1 | 4 | 1 | none | 15 | 0 | custom |
| c790de67 | 4 | 1 | none | 30 | 0 | custom |
| 492562b3 | 3 | 144 | none | 25 | 0 | custom |
| 6eb3639b | 3 | 885 | 23 | 2 | 44 | custom |
| 6cd5b342 | 3 | 898 | 70 | 4 | 41 | custom |
| 5e178f02 | 3 | 836 | 134 | 2 | 32 | custom |
| b5fd1476 | 3 | 499 | 152 | 2 | 26 | custom |
| f7cf0079 | 3 | 612 | 162 | 4 | 25 | custom |
| c5427f2d | 2 | 664 | 205 | 2 | 23 | custom |
| 136c768e | 3 | 403 | 92 | 8 | 23 | ai |
| 58eb856e | 3 | 482 | 191 | 9 | 22 | ai |
| 2425ca55 | 3 | 442 | 86 | 2 | 17 | custom |
| e17f069f | 3 | 361 | 24 | 2 | 17 | custom |
| d88bcded | 3 | 548 | 215 | 2 | 16 | custom |
| b769efb3 | 3 | 215 | 49 | 8 | 16 | ai |
| 7786b100 | 3 | 519 | 210 | 2 | 13 | custom |
| 2216c1c3 | 3 | 547 | 251 | 2 | 13 | custom |
| 1b736323 | 3 | 392 | 114 | 2 | 13 | ai |
| 31bc7408 | 3 | 295 | 130 | 2 | 9 | custom |
| 7a200378 | 3 | 236 | 113 | 3 | 9 | ai |
| b3f9cd32 | 3 | 384 | 242 | 3 | 8 | custom |
| d9257fa3 | 3 | 197 | 87 | 2 | 7 | custom |
| 91232a7e | 3 | 174 | 119 | 2 | 4 | custom |
| 8f44ac35 | 3 | 183 | 108 | 2 | 4 | custom |

No counter-examples in the set:

  • The five sessions with zero ai-title records are exactly the ones where a custom-title record already existed when the titler ran.
  • In the four sessions where custom-title is line 1, the first user record (line 4) is /clear. These sessions were started by /clear in a tab I had already renamed, so the tab's name was written as line 1 and the titler found a title already present.
  • Every affected session has 1st ai-title < 1st custom-title.
  • Once ai-title exists, the engine keeps re-appending it (8–44 records), and in five sessions it ends up as the last title record.

Root cause

The ai-title writer lives in the engine, not in the extension — grep -c 'ai-title' extension.js returns 1, in the reader only. The writer:

function CZ(e,n,r){if(ov(_f(e),{type:"ai-title",aiTitle:n,sessionId:e},r).catch((s)=>{t(`saveAiGeneratedTitle: transcript append failed: ${l(s)}`)}),e===Y())xs().currentSessionAiTitle=n,ta().sessionTitleChanged.emit()}

Guarded path (the once-per-session "haiku title" after the first message) correctly drops its result when a title already exists:

if(!this._haikuTitleAttempted){…this._haikuTitleAttempted=!0;let $r=ft.id;this._engine.generateSessionTitle(Un,{credentials:Io}).then((Wn)=>{if($r!==ft.id)return;let pr=Pt.getSnapshot();if(pr.sessionTitle||pr.aiSessionTitle)return;if(Wn)jt(Wn),CZ($r,Wn,Mt),Vl()?.adoptLocalAiTitle?.();else this._haikuTitleAttempted=!1},()=>{this._haikuTitleAttempted=!1})}

Unguarded path — when the session stopped being the active one while the title was being generated, E() appends ai-title with no bp(r) check at all, i.e. without asking whether the user has set a title:

let E=()=>{try{CZ(r,v,o.storageV5)}catch(L){…}};if(r!==Y()){if(u)E();return v}if(!bp(r)){if(_c())E();else GSr(v)}

bp(e) returns the user-set title (currentSessionTitle); it is consulted only on the r===Y() branch. This matches the symptom being worst with many parallel tabs, where sessions routinely stop being active mid-turn.

A third call site also persists without consulting bp:

generateSessionTitle:async(k,A)=>{if(A?.persist)at=!0;…if(L&&A?.persist)try{CZ(Y(),L,K?.toolUseContext.storageV5)}catch(W){…}return L}

Read precedence itself is fine — the extension prefers the custom title on every path:

let B=f1(W,"customTitle")||X||f1(Y,"customTitle")||f1(W,"aiTitle")||f1(Y,"aiTitle")||void 0

So nothing is lost on disk; the problem is that ai-title records keep being written for sessions that already carry a user-set title.

Workarounds that do not work

  • Developer: Reload Window does not help. It re-reads from disk but does not stop or remove the ai-title records appended after the rename.
  • "Rename while the session is idle" does not help either. What matters is whether the titler has already written its record, not whether a turn is running.
  • "Rename before the first prompt" is impossible — the rename command needs an existing session.

The only reliable workaround I found: rename a tab once, then /clear. The new session inherits the name as line 1 and the titler never writes. That costs a wiped context per tab.

Ask

  1. Make every ai-title write path check for a user-set title, including the r!==Y() branch and the persist API call — a user-set title should never be followed by an AI title for the same session.
  2. Add a setting to disable AI-generated session titles entirely, for people who name their tabs by hand.

Related

Same symptom, different angles: #95168, #94017, #94817, #94470, and the closed #40781, #40787, #46587, #47832, #52352.

View original on GitHub ↗