Auto-rename active session to match current git branch (incl. parallel-agent / worktree workflows)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Problem description
Claude Code lets users name sessions via claude -n <name> at launch or /rename <name> mid-session, and the session picker already displays the current git branch alongside each row (sessions docs). So in principle the user can tell sessions apart from the picker — the branch is right there.
The actual pain is everything that depends on the session name (not the picker's branch column):
claude --resume <name>— resolves by name "across the current repository and its worktrees." If nobody manually renames, half the sessions in a project default to "the first prompt" or a conversation summary, and--resumebecomes a guessing game. If two sessions have the same auto-generated default, it gets worse.- Statusline, OS window title, prompt bar — any surface that displays the name shows whatever was set at launch, frozen. The branch shown next to it in the picker isn't carried into those surfaces.
- Logs / telemetry / external integration — anything that keys off the session name (file paths under
~/.claude/projects/, custom hooks, IDE integrations) sees stale names indefinitely.
The root cause is structural: the session name is a free-form user-managed string, but the work being done is branch-scoped. The name and the branch are decoupled, so the name needs constant manual maintenance to stay useful. In a single-session workflow nobody bothers (and they don't have to — there's only one session). In a multi-agent / multi-worktree workflow where six Claude CLIs are open in parallel, nobody is going to /rename six times after every checkout. The cost-benefit just doesn't work out for the user, so they stop, and the names rot.
This is the workflow Claude Code seems built for — multiple agents running in parallel, often in git worktrees, each on a different branch of the same repo. The session model supports it; the naming UX fights it.
Who this affects
Anyone running more than one Claude CLI against the same repo, or one CLI across multiple branches in sequence:
- Solo devs with parallel feature work via
git worktree. - Teams using Claude Code as a per-agent assistant where each branch has a dedicated session.
- Anyone scripting
claude --resume(e.g. wrapping it in editor shortcuts or shell scripts) — needs deterministic, predictable names.
Proposed Solution
Proposed solution
Auto-update the session name to track the current git branch, by default in git repos.
Specifically:
- At session launch: if cwd is a git repo, set name to
$(git branch --show-current). - After any Bash command containing
git checkout,git switch, orgit branch -m: re-read and update. - Detached HEAD:
(detached) <short-sha>. - Non-git directory: don't auto-name; leave whatever default Claude already does.
- Manual
/renametakes precedence: an explicit user rename freezes the auto-track until they clear the override (e.g./rename --autoto resume tracking, or until they restart the session). Protects intentional names likeprod-incident-2026-05-26.
Configurable in ~/.claude/settings.json:
{
"session": {
"autoNameFromGitBranch": true, // default true in git repos
"freezeOnManualRename": true // explicit /rename pins the name
}
}
This makes the name mean "what branch is this session working on right now" by default, which is what users already assume when they go to claude --resume <branch>.
Alternative Solutions
Alternative solutions (in order of decreasing scope)
Option A — full auto-tracking (the proposed solution above)
Best UX, removes the manual step entirely. Requires Claude Code to observe checkouts (post-Bash inspection or .git/HEAD watcher).
Option B — expose sessionTitle on the SessionStart hook
UserPromptSubmit hooks already support a sessionTitle field in their stdout JSON (hooks docs). SessionStart does not — its supported output fields are additionalContext, initialUserMessage, watchPaths only.
Add sessionTitle to SessionStart's supported fields and the community can implement auto-naming via a one-liner:
# ~/.claude/hooks/session-start.sh
#!/usr/bin/env bash
echo "{\"hookSpecificOutput\":{\"sessionTitle\":\"$(git branch --show-current 2>/dev/null || echo session)\"}}"
This is the smallest possible change — one JSON field — and unblocks the launch-time half of the problem without any core auto-tracking. Wouldn't handle in-session checkouts, but it'd cover the parallel-agent / worktree spawn case which is the most painful one.
Option C — /rename --git one-shot
A discoverable manual re-sync command. Cheaper to implement than full auto-tracking and gives users a low-friction way to fix names without retyping the branch. Still requires the user to remember to run it — the multi-agent friction remains.
Option D — surface the branch in places that currently only show the name
Window title, statusline default, --resume listing: show <name> [<branch>] when they differ. Doesn't fix the underlying decoupling but at least makes the drift visible everywhere, not just in the picker.
Of these, B is the lowest-cost intervention that unblocks the most-painful use case (parallel agents in worktrees, all defaulting to branch names without anyone thinking about it). A is the right destination; B is the right next step.
Priority
Medium - Would be very helpful
Feature Category
CLI commands and flags
Use Case Example
Use cases
1. Parallel agents on the same repo
Claude #1 on CustomLFO, Claude #2 on main, Claude #3 on a hotfix. The picker shows three rows, each with its branch column — fine for the picker. But:
claude --resume CustomLFOfrom another shell: nobody renamed any of them, so this either fails or resolves ambiguously to whichever has a matching default summary.- Statusline / window title show whatever-the-launch-named-them. After a few checkouts none of those are accurate.
If each session had been auto-named to its current branch, --resume <branch> is the obvious deterministic command.
2. Worktrees of the same repo
git worktree add ../repo-branchB branchB. The picker entry for the branchB worktree session has a different cwd from the main worktree session, but the session name default is still a free-form string. --resume doesn't help disambiguate without manual naming.
3. In-session checkout
Start a session on feature-A. Halfway through, git checkout feature-B to fix something. Don't run /rename. Now the picker's branch column says feature-B (great) but the session name still says feature-A (or whatever the launch default was). Anything that keys off the name has wrong data.
4. --resume ergonomics
After a week of work in a repo, claude --resume shows N sessions. The picker UX (Ctrl+B to filter by branch) is documented and helps inside the picker. But scripting / muscle-memory wants claude --resume <branch> from the shell. That requires the title to be the branch name. Today that only happens if the user manually maintains it.
Why the existing affordances aren't enough
| Existing affordance | Why it's insufficient |
|---|---|
| Picker shows branch column | Only inside the interactive picker. Doesn't help --resume <name>, statusline, window title, scripting, hooks. |
| Ctrl+B filters picker by current branch | Same scope limit — picker only. Also requires the user to be using the picker UI, not a quick shell command. |
| /rename <branch> after every checkout | Friction. Nobody does it consistently, especially in parallel-agent workflows. The user already told Claude the info via git checkout; requiring a second redundant command means paying the same tax twice. |
| claude -n "$(git branch --show-current)" alias | Only fires at launch. In-session checkouts don't update. --resume ignores the alias. |
Additional Context
Edge cases
- Submodules: cwd inside a submodule has its own branch. Default to the outermost repo's branch (most users think at parent-repo level); configurable override.
- External branch change: a different terminal does
git checkoutwhile Claude is idle. A.git/HEADwatcher catches this; a one-shot at session start doesn't. - Branch names with
/(feature/foo): valid title,/renamealready accepts them. - Very long branch names: truncate for display, keep full string for
--resumematching. - Detached HEAD via bisect: a single session may go through many short-SHA detached states. Auto-renaming every iteration would spam the picker. Could be opted out of, or coalesced (don't auto-rename while a bisect is in progress).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗