Skip to content

feat(sessions): launch every Claude session with --name set to its tab name - #646

Merged
Ark0N merged 2 commits into
Ark0N:masterfrom
opticon454:feat/cli-session-name
Oct 18, 2026
Merged

Ark0N merged 2 commits into
Ark0N:masterfrom
opticon454:feat/cli-session-name

Conversation

@opticon454

Copy link
Copy Markdown
Contributor

What

A Claude session is launched with --name <tab name> for every tab, not only for ones the user renamed.

Why

Claude Code's prompt-box label, /resume entry and its remote session list showed Claude's own generated title for a tab Codeman called w4-Codeman (for example "Git indicator guard test and teardown flake"), so the two lists could not be matched up. cliPinnedName withheld the flag for placeholder and auto-named tabs on purpose, so that every conversation in a case would not share one /resume entry; the tab number already keeps those apart per tab.

How

Session.cliPinnedName returns the tab's name whatever its source. The flag stays version-gated and sanitised as before (buildNameCliArgs). A rename or an auto-name reaches the CLI at its next spawn, because a process started with --name re-appends its in-memory title (see claude-session-title.ts); the transcript row for a manual rename is still written.

Tests

test/claude-resume-title.test.ts pins placeholder and auto names as pinned; the existing --name injection, spawn-golden and registry tests pass unchanged. Changeset included.

@Ark0N

Ark0N commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Thanks for this, @opticon454. The PR launches every Claude session with --name set to its tab name, so Claude's prompt-box label, /resume entry and remote session list read the same as the Codeman tab instead of Claude's generated title.

Matching the two lists by eye is painful today, so I see the point. Before you spend more time on it, I need to settle a design question on my side, because this reverses #457, which I merged on purpose three weeks ago.

Why placeholder and auto names are unpinned today. --name is also the /resume title, and a pinned title stops Claude generating its own. #457 measured 34 of 34 --name-spawned conversations with no generated title, and I reproduced it here. The tab number does not keep /resume entries apart over time: _nextCaseSessionStartNumber() (src/web/public/session-ui.js:1870) numbers from the highest open tab, so once a case's tabs are closed the next one is w1-myapp again, and /resume fills up with identical w1-myapp entries. The rule is written down in CLAUDE.md:257 and docs/architecture-invariants.md:206.

Renames stop reaching Claude. A Codeman rename reaches /resume by appending a custom-title row (src/web/routes/session-routes.ts:1307). As src/claude-session-title.ts:9-13 explains, that only sticks for a pane spawned without --name, because a pane spawned with it re-appends its in-memory title after every turn. With this PR every pane has --name, so renaming w1-myapp holds until the next turn and then reverts, until the pane is respawned (a server restart re-attaches the live pane without respawning it). With auto-naming on, every tab diverges after its first prompt.

If we go ahead, this is what I would ask for:

  1. Put the behaviour behind an opt-in synced setting (default OFF) that switches Session.cliPinnedName (src/session.ts:1733) to always pin, so fix(sessions): stop pinning the w1-myapp placeholder as Claude's /resume title #457's behaviour stays the default. That needs a SettingsUpdateSchema entry and a control in App Settings. I will confirm this direction here first.
  2. Update the docs that state the old rule: CLAUDE.md:257, docs/architecture-invariants.md:206, docs/agent-control-plan.md:761-770, skills/codeman/reference/messaging.md:108-113 and :205, skills/codeman/reference/verbs.md:699-700, then run node scripts/sync-plugin.mjs to refresh the plugin mirror. Include the rename limitation above.
  3. Update the JSDoc that still says only a user-chosen name is pinned: src/mux-interface.ts:97 and :141, src/tmux-manager.ts:901, src/claude-session-title.ts:9-13.
  4. Reword the changeset (.changeset/cli-session-name-matches-tab.md:5): "they now read the same as the tab" holds only until a rename or an auto-name.

Typecheck, lint, format and the full test suite pass, and the sanitizing and version gate on --name are untouched, so the code itself is in good shape. I will post the decision on the setting here; please hold off on changes until then.

@Ark0N

Ark0N commented Oct 18, 2026

Copy link
Copy Markdown
Owner

@opticon454 decision on the design question: an opt-in setting. #457's behaviour stays the default, and always pinning --name goes behind a synced setting that is off by default, so the users who want the CLI labels to match their tabs can have it and nobody loses Claude's generated titles without choosing to.

So items 1 to 4 from my comment above stand as written. A few details for the setting itself:

  • Add it to SettingsUpdateSchema (src/web/schemas.ts) and a control in App Settings, with a description that says what it costs: Claude stops generating its own titles for those sessions, and a rename in Codeman holds only until the next turn.
  • Read it fresh at spawn time, the way readPlanUsageTelemetryEnabled() (src/hooks-config.ts) is read at every claude create and respawn, so Session.cliPinnedName decides per launch and a toggle takes effect on the next spawn or respawn without a server restart. Say that in the description too.
  • In PUT /api/settings, anything that acts on it must resolve from the merged settings, never the raw body (test/routes/system-routes-settings-partial-put.test.ts pins why).
  • A test that pins both sides: with the setting off, a placeholder or auto name still launches without --name (the fix(sessions): stop pinning the w1-myapp placeholder as Claude's /resume title #457 behaviour, byte-identical), and with it on, every local claude spawn gets the sanitized tab name.

Thanks for waiting on this.

@opticon454
opticon454 force-pushed the feat/cli-session-name branch from 791f0ea to 1fefeda Compare October 18, 2026 05:58
Add pinCliSessionName (synced, default OFF), re-read at each spawn and respawn.
Off keeps the Ark0N#457 behaviour; on pins every non-blank tab name as --name.
Update the docs, JSDoc and changeset that stated the old rule.
@opticon454

Copy link
Copy Markdown
Contributor Author

Pushed 76479fdc (rebased onto current master first). Summary of the change:

  • New synced setting pinCliSessionName (default OFF) in SettingsUpdateSchema, with an App Settings toggle under Claude ("Pin tab names on the CLI"). Its description states the cost (Claude stops generating its own titles; a rename holds only until the next turn) and that it applies from the next spawn or respawn.
  • readPinCliSessionNameEnabled() in hooks-config.ts reads it fresh from settings.json. Session refreshes it at the start of startInteractive() and in _buildRespawnPaneOptionsWithResumePin() (restart and respawn paths), so cliPinnedName decides per launch with no server restart. Off returns exactly the old manual ? name : undefined.
  • PUT /api/settings needs no code: nothing acts on the value there, since it is only read at spawn. The schema comment says so.
  • Docs and JSDoc from items 2 and 3 updated (CLAUDE.md, architecture-invariants, agent-control-plan, messaging.md, verbs.md, mux-interface.ts, tmux-manager.ts, claude-session-title.ts), plugin mirror synced, changeset reworded.
  • test/claude-resume-title.test.ts pins both sides: off (absent, empty or false) leaves placeholder and auto names unpinned while a manual name still pins; on pins placeholder, auto, manual and never a blank name; and one session follows the setting across two respawns.

Typecheck, lint, format and the full npm test pass (582 files, 11590 tests).

@Ark0N
Ark0N merged commit 76479fd into Ark0N:master Oct 18, 2026
2 checks passed
Ark0N pushed a commit that referenced this pull request Oct 18, 2026
…s reference

The new App Settings row had no zh-CN entry, so it read in English in a
Chinese UI, and docs/wiki/Settings-Reference.md did not list it. Adds the
label and description to i18n.js, a row in the Agents & CLIs table, and a
JSDOM test that runs the real translator over the real index.html.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ark0N pushed a commit that referenced this pull request Oct 18, 2026
…with --name set to its tab name

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Ark0N

Ark0N commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Merged and shipped in 1.43.0 as the opt-in Pin tab names on the CLI setting. Thanks @opticon454, that was a fast and complete turnaround on the decision: off is byte-identical to #457 on every spawn path, the setting is read fresh at each start and respawn, and the docs and skill pages moved with it.

On top I added the zh-CN strings for the setting, a row in the Settings Reference wiki page, and a small test that runs the real translator over them.

@opticon454
opticon454 deleted the feat/cli-session-name branch October 18, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants