[FEATURE] Un-gate claude://code/continue?session=<local_id> — validation and lookup are already implemented

Status Open
Reported on v2.1.150
Maintainer reply None cached
Activity 4 comments · opened Aug 27, 2026

Summary

claude://code/continue?session=<local_session_id> already contains a complete implementation for focusing a specific desktop session — parameter validation, exact-ID lookup, and route resolution are all present in the shipped app — but the handler returns early behind a feature gate, so the link only brings the app to the foreground and stays on whatever session was last focused.

Please consider enabling this path (or exposing an equivalent documented one).

Use case

A session finishes work (or a scheduled reminder fires) and pushes a message to my phone. I have a dozen sessions open. The notification tells me something happened, but not which session said it — so I have to hunt through the sidebar.

The fix is for the notification to carry a "return to the sender session" link. That works end to end today except for the final hop.

What I found

Environment: Claude Desktop 1.37937.3, Claude Code 2.1.150, macOS 26.5.2.

1. claude://code/continue?session=<id> — validation and lookup are implemented, but gated

The URL handler validates the parameter:

function bBt(e){ return e === `last` || (e !== null && yBt.test(e)) }
// yBt = /^local_[A-Za-z0-9-]{1,64}$/

A local_… session ID passes this check. The resolver does an exact match and produces a route:

async function SBt(e){
  const t = await $j();
  await t.waitForSessionsLoaded();
  const n = (await t.getAllSessions()).filter(s => !s.isArchived);
  const r = e === `last`
    ? n.sort((a,b) => (b.lastActivityAt ?? 0) - (a.lastActivityAt ?? 0))[0]
    : n.find(s => s.sessionId === e);          // <- exact ID match already supported
  return r ? t.getSessionRoute(r.sessionId) : undefined;
}

But the entry point returns before any of that runs:

async function xBt(e,t,n,r,i){
  const a = wM();
  if (!await Mzt()) { P.info(`claudeURLHandler: code entry deep link gated off`); return }
  ...
}

Observed in ~/Library/Logs/Claude/main.log on every click:

claudeURLHandler: code entry deep link gated off

Result: the app comes to the foreground but does not switch sessions. From a user's point of view the link looks broken, with no error shown.

2. claude://resume?session=<cli_session_uuid> works, but duplicates instead of focusing

This path is not gated and does fire:

Resume deep link: importing CLI session 6df6752e-…

It calls importCliSession(), which creates a new session entry from the CLI transcript. The original desktop session stays where it is, and the sidebar now has two entries with the same conversation. Usable as a workaround, but it pollutes the session list every time.

3. The documented deep link cannot do this

Launch sessions from links covers claude-cli://open, registered by the CLI, which accepts only q, cwd, and repo. It starts a new terminal session; there is no parameter for resuming an existing one.

Why this issue rather than a +1 on the existing ones

#50345 (closed) asked for exactly this and reported that --resume <uuid> and various schemes were ignored. #81202 asks for the Cowork equivalent.

The new information here is that this is not a missing feature — it is a disabled one. The ID format is accepted, the lookup is exact, and the route is computed. Only Mzt() stands between the current behaviour and the desired one.

Request

Any of these would solve it:

  1. Enable the gate for claude://code/continue?session=<local_session_id>.
  2. Make claude://resume focus an existing session when the transcript is already imported, instead of importing a duplicate.
  3. Document a supported equivalent, so integrations do not have to rely on internals.

Workaround in the meantime

A local HTTP redirect service maps a short code to the session ID and 302s to the claude:// URL, and the notification includes the session's title so the right sidebar entry can at least be identified by name. Everything works up to the final hop.

View original on GitHub ↗

4 Comments

jacobchang-Nineder · 1 month ago

Follow-up after digging further. Two additions that narrow this down.

claude://resume cannot be used as a workaround for app-created sessions

The dedup guard in adoptCliSession only recognises an existing session when its ID is literally local_<cli_session_id>:

if (!this.sessions.has(`local_${e}`)) { /* delete-in-flight check */ }

That holds for sessions the CLI created, but not for sessions created inside the desktop app, which get an independent sessionId and carry the CLI transcript ID separately as cliSessionId.

On my machine, out of 142 sessions in ~/Library/Application Support/Claude/claude-code-sessions/, exactly 1 satisfied sessionId === "local_" + cliSessionId — and that one was a fork. For the other 141, claude://resume?session=<cliSessionId> imports a duplicate rather than focusing the existing session.

So the practical picture is: resume reliably duplicates, and code/continue is gated. Neither is usable for "return to the session that sent this notification".

&cwd= does not help

Some write-ups mention claude://resume?session=<uuid>&cwd=<path>. In this build the Resume branch reads only session; cwd is never accessed, so adding it changes nothing.

The gate looks account-scoped rather than local

Mzt() resolves through jzt(), which is keyed on accountUuid and resolves a numeric gate ID. If that is right, users cannot enable this locally even for testing — which is worth stating explicitly in the docs, since the URL is registered and silently does nothing when the gate is off. A visible message ("this deep link is not enabled for your account") would have saved a fair amount of debugging: the current behaviour is that the app comes to the foreground on the previously focused session, which is indistinguishable from a broken link.

Adjacent prior art

claude-control solves the equivalent problem for terminal-hosted sessions by focusing the terminal tab (AppleScript TTY matching for Terminal.app/iTerm2, remote control for kitty, wezterm cli for WezTerm, tmux send-keys). There is no equivalent for sessions living inside the desktop app, which is what this request is about.

digorgonzola · 1 month ago

Independent repro on a newer build — same gate.

Confirming this on Claude Desktop 1.44121.2 / Claude Code 2.1.255 / macOS 26 (Darwin 25.6). Same behavior exactly: claude://code/continue?session=<local_…> logs claudeURLHandler: code entry deep link gated off and only foregrounds the app.

Worth adding that the dev override is a dead end for normal users — Qgt (the force-on gate set) is built from CLAUDE_DEV_FORCE_GATES, but it's short-circuited to an empty set when app.isPackaged, so there's no way to self-enable this on a production install.

Concrete use case: I built a local dashboard over ~/.claude/sessions + the CCD store (claude-code-sessions/) that shows every live/open session and which ones are waiting on you. Resolving cliSessionId → local_ sessionId for the deep link works perfectly — the only missing hop is this gate. Un-gating it (or exposing a documented "focus existing session" link that doesn't duplicate the way claude://resume does) would let notifications and any multi-session tool jump straight to the right chat. +1.

jacobchang-Nineder · 2 hours ago

Update: works on Claude Desktop 2.37337.1 (macOS 26 / Darwin 25.5).

claude://code/continue?session=<local_id> now switches to the target session. I tested it by switching to another session, confirming it was the focused pane, and then switching back. main.log no longer shows code entry deep link gated off.

In this build the check is no longer a hard-off gate. It passes when the user is logged in and deep links haven't been disabled by policy.

The app also exposes its own per-session link now, claude://claude.ai/epitaxy/<local_id>, which also lands on the right session.

I'll leave closing to the maintainers, since the earlier report on 1.44121.2 may still apply to 1.x builds.

digorgonzola · 1 hour ago

Follow-up to my earlier report: resolved for me too.

Retested on Claude Desktop 2.37337.1 / Claude Code 2.1.300 / macOS 26 (Darwin 25.6). This is the same machine that reproduced the gate on 1.44121.2.

  • claude://code/continue?session=<local_id> now switches to the target session. I opened a link to a second session, then a link back to the first. The lastFocusedAt of each session record changed 3 s apart, which matches the two clicks.
  • main.log shows no code entry deep link gated off line. The last one in my rotated logs is from 2026-09-04.

The dashboard use case I described above now works end to end, and I have removed the gate caveat from it. I agree with @jacobchang-Nineder: maintainers can close this if 1.x builds are no longer a concern.