[BUG] Opening a conversation in the desktop app resumes the session and runs SessionStart hooks

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

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

In the desktop app, clicking a conversation in the sidebar respawns the session process and fires the SessionStart hook with source: resume. Nothing has been typed and nothing has been asked for. Opening a conversation to look at it is treated exactly the same as deciding to carry on with it.

That matters because SessionStart hooks are allowed to do real work. A hook can make network calls, invoke a model, take a lock, or change state on disk. So opening the wrong conversation while hunting for the right one can cost real time and money, and it can have side effects that are awkward to undo. There is no confirmation, and nothing in the UI to tell you a session has just restarted rather than simply been displayed.

There is also no way to stop a session from inside the app. Ctrl+W closes the tab but leaves the session running, and deleting the conversation is the only in-app route, which throws away the transcript with it. You can stop one from outside, by killing the process, restarting WSL, or restarting the app, but the last two take out every session rather than the one you meant, and none of it helps for long: opening the conversation afterwards simply starts it again, hooks and all.

Environment: Claude Code desktop app on Windows, version 1.52386.3, Code tab pointed at a WSL workspace. Note that the version field below is my separately installed WSL CLI, which takes no part in this. The app runs its own bundled CLI at ~/.claude/remote/ccd-cli/2.1.266, and that is the process being respawned. I have only tested under WSL, but I see nothing WSL specific about it, since the session process and the SessionStart hook are the app's own behaviour, and only the paths and the pgrep check below are platform specific.

What Should Happen?

Opening a conversation should show me the transcript and start nothing until I ask for it.

Concretely, any of these would fix it, and they combine well:

  1. Resuming becomes an explicit action rather than a side effect of opening a conversation.
  2. A session whose process has gone, whether I stopped it or the app was restarted, comes back as suspended rather than being started again silently when I open it.
  3. The prompt box for a suspended session looks visibly different, with a label saying that submitting will resume the session, plus a separate control to resume without sending a prompt.
  4. Where the app can tell that SessionStart hooks are configured for that working directory, the same label says so, for example "resuming will run the SessionStart hook".
  5. A setting, global or per workspace, for whether opening a conversation auto-resumes.

Points 1 and 2 both need a deliberate way to stop a session, so that would have to come with them.

Error Messages/Logs

No error output. The hook runs successfully, which is the problem.

Steps to Reproduce

  1. Create a throwaway workspace with a SessionStart hook that just records when it runs:

mkdir -p /tmp/hooktest/.claude
cat > /tmp/hooktest/.claude/settings.json <<'EOF'
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|clear|resume|compact",
"hooks": [
{ "type": "command", "command": "date -Iseconds >> /tmp/hooktest/hook.log" }
]
}
]
}
}
EOF

  1. Open /tmp/hooktest in the desktop app Code tab, send one message, and let it finish. /tmp/hooktest/hook.log now has one line.
  2. Press Ctrl+W to close the tab.
  3. Click that conversation in the sidebar to bring it back. Do not type anything.
  4. cat /tmp/hooktest/hook.log

Expected: still one line, because nothing was asked for.
Actual: a second line. The session process has been respawned and the hook has run, from the click alone.

Also run pgrep -af ccd-cli before step 3 and after step 4. The pid for that workspace changes, which is the respawn behind the hook firing.

The repro above is written for a Unix shell. The hook command can be anything that leaves a trace, so the same steps should work on macOS or native Windows with the equivalent settings.json.

Claude Model

Other

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.270 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

_No response_

View original on GitHub ↗