Programmatic session naming — hook-callable rename + Skill tool as hook target

Status Fixed / completed
Maintainer reply None cached
Activity 7 comments · opened Apr 7, 2026 · closed Aug 17, 2026

Problem

When running multiple sessions across repos and skills, session titles default to generic names, creating working memory tax when switching between them. Manually renaming is possible but breaks flow.

Two missing pieces block automation:

  1. No hook-callable rename — \/rename\ exists but is interactive-only. Hooks (shell commands) have no mechanism to set or update the session title.
  2. Skill tool isn't hookable — \PreToolUse\/\PostToolUse\ support named tools (\Bash\, \Edit\, \Agent\, etc.) but \Skill\ isn't a matchable target, so there's no hook point when a skill is invoked.

Proposed solution

  • Expose session rename via hook output — e.g., a structured JSON field hooks can return: \{"session_title": "wolf-way goforit"}\
  • Add \Skill\ as a matchable tool name in \PreToolUse\/\PostToolUse\ hooks, with \tool_input.skill\ in the hook payload

Desired behavior

A \PreToolUse\ hook on \Skill\ fires, reads \tool_input.skill\, sets the session title to \{repo} {skill}\ — session is named before the skill even runs. Zero manual steps.

Scope

Applies to Claude Code CLI today. Claude Desktop would benefit from the same platform capability once available.

View original on GitHub ↗

5 Comments

danrfhughes · 4 months ago

+1 on this — my use case overlaps the first half (hook-callable rename) and adds a data point on why the obvious DIY workaround doesn't work.

Use case

SessionEnd hook that reads a pending title from ~/.claude/.rename-pending/<sid>.txt (written by some upstream process — backlog item id, commit subject, etc.) and applies it to the just-ended session.

What I tried

Since Claude Code itself writes {"type":"custom-title", ...} lines into the session JSONL during init / /rename, I wrote a hook that does the same. Two iterations:

  1. Append at EOF — no sidebar update.
  2. Replace the first existing custom-title line (or insert after line 1) via atomic temp-file + rename — still no sidebar update, even after desktop-app relaunch.

So the JSONL isn't authoritative for the sidebar. Corroborated by #37449 ("stat-log index not synced from JSONL") and #39228 (sessions with custom-title mid-file disappear from the panel — so the reader is position-sensitive and index-cached).

Concrete API suggestion

Matches the proposal in this issue. A SessionEnd (or new SessionRename) hook returning JSON on stdout:

{ "sessionTitle": "my custom title" }

The runtime would:

  • Update the internal stat-log/index so the sidebar reflects it without app relaunch.
  • Optionally also write the custom-title line to the JSONL for continuity with the existing on-disk format.

Stdin to the hook already carries session_id and transcript_path; returning a title on the same channel means no consumer has to reverse-engineer the index format (which is the thing that burned me — I never found where the sidebar actually reads from).

Scope note

Also relevant for #36379 (auto-titles override user renames) and #41378 (desktop app doesn't reflect title changes until reactivation) — a single authoritative write path from hooks would simplify the fix for all three.

danrfhughes · 4 months ago

human here - I just want the session names to reflect the work, not the first action ('check memory' or whatever)

OleksandrKuklyshyn · 4 months ago

+1 — adding a concrete use case from a different angle.

As a user with a "prefix session title with #<num> — whenever a GitHub issue is referenced" convention enforced via memory rules, I have no way to apply this automatically. The model "knows" the rule and can include it in chapter titles via mark_chapter, but the session title in the sidebar stays whatever was inferred from my first prompt — usually something like "Investigate failing test" instead of "#5484 — Investigate failing test".

Use cases beyond the original

  • Issue-tracker prefix conventions (#1234 — ..., [ABC-42] ...)
  • Project/tenant tags ([acme] ..., [vd] ... for multi-tenant work)
  • Outcome-based renames at task close (already covered in #41888)

API preference

Of the options floated across #44786 / #40496 / #41888, the hook stdout JSON ({"sessionTitle": "..."}) is the most composable — it works from SessionStart, UserPromptSubmit, and SessionEnd uniformly, and doesn't require new tool plumbing. An MCP tool set_session_title would be a nice complement for in-conversation renames driven by the model itself.

Current workaround

Manual rename in the sidebar after each session — brittle and easy to forget. Tried writing custom-title lines into the JSONL (per this issue's investigation) — sidebar doesn't pick them up.

krisjaschkowitz · 4 months ago

+1 with a Windows Desktop App data point — this confirms the override behaviour is cross-platform, not just CLI/IDE.

Setup

  • Claude Code Desktop App (Windows 11), autoUpdatesChannel: "latest"
  • User-global UserPromptSubmit hook in ~/.claude/settings.json calling a script that emits {"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","sessionTitle":"YYYY.MM.DD MyProject"}}

Observed

  1. Hook fires correctly on every prompt — confirmed via diagnostic log written by the script itself:

``
=== <date> <time> ===
CLAUDE_PROJECT_DIR=<project>/.claude/worktrees/<id>
title=2026.05.01 MyProject
``

  1. JSON output is valid and matches the spec from the hooks doc.
  2. UI session title nevertheless shows the LLM-generated auto-summary (e.g. Add tests for core functionality for a test prompt). Hook-supplied title is never visibly applied — even after Claude Code restart and full Windows reboot.
  3. /rename not available in the Desktop App env (/rename isn't available in this environment.), so no in-app workaround.

Why this matters here

The fix proposed in this issue (authoritative hook stdout {"sessionTitle": "..."} write path that updates the index/sidebar without relaunch) would also resolve the silent override on Desktop App — the auto-titler currently wins the race against the hook output, leaving documented hookSpecificOutput.sessionTitle effectively non-functional for end users on Desktop.

Happy to share the full hook script + log if useful.

Donutellko · 1 month ago

The workaround that I'm currently using:

A UserPromptSubmit hook (in ~/.claude/settings.json) runs a script that reads transcript_path from stdin, extracts your last assistant turn, and greps for a marker like <!--rename: TITLE -->, emitting {"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","sessionTitle":"TITLE"}} — because only SessionStart/UserPromptSubmit (not Stop) can set the title, so the rename lands on your next message.

A CLAUDE.md rule instructs Claude to end replies with that marker when the session name is stale, so naming happens automatically with no /rename copy-pasting — just a one-message delay.

Showing cached comments. Read the full discussion on GitHub ↗