claude-code - 💡(How to fix) Fix Resume picker shows no sessions when cwd is inside a git submodule

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When cwd is inside a git submodule, claude --resume (and /resume) reports "No conversations found to resume" even when the project bucket for that path contains many sessions. Sessions are still being written to the correct bucket — the bug is in how the picker reads them.

Root Cause

The resume picker resolves the project path via git worktree list --porcelain (function gkH in the bundled CLI):

async function gkH(H) {
  let { stdout: q } = await P8(C8(), ["worktree", "list", "--porcelain"], { cwd: H, ... });
  let T = q.split("\n").filter($ => $.startsWith("worktree ")).map($ => $.slice(9).normalize("NFC"));
  let A = T.find($ => H === $ || H.startsWith($ + path.sep));
  ...
}

For a submodule, git worktree list --porcelain returns the main worktree as the internal git dir, not the checkout path:

$ cd packages/bundles && git worktree list --porcelain
worktree /Users/me/Projects/langdock/.git/modules/packages/bundles
HEAD ...
branch refs/heads/...

The cwd is /Users/me/Projects/langdock/packages/bundles. None of the returned worktree paths equal it, and cwd.startsWith(worktreePath + sep) is false for every entry (the .git/modules/... path is not an ancestor of the checkout). So A is undefined, the worktree list passed to the session loader (MY6) doesn't include the actual checkout path, and the loader returns no sessions for that bucket.

filterResumableSessions (V1K) then sees an empty list and the picker reports "No conversations found to resume." Meanwhile sessions are still written to ~/.claude/projects/<cwd-encoded-as-slug>/... via a separate code path that uses cwd directly, so the bucket fills up but reads can never find it.

Fix Action

Fix / Workaround

Workarounds

Code Example

async function gkH(H) {
  let { stdout: q } = await P8(C8(), ["worktree", "list", "--porcelain"], { cwd: H, ... });
  let T = q.split("\n").filter($ => $.startsWith("worktree ")).map($ => $.slice(9).normalize("NFC"));
  let A = T.find($ => H === $ || H.startsWith($ + path.sep));
  ...
}

---

$ cd packages/bundles && git worktree list --porcelain
worktree /Users/me/Projects/langdock/.git/modules/packages/bundles
HEAD ...
branch refs/heads/...
RAW_BUFFERClick to expand / collapse

Summary

When cwd is inside a git submodule, claude --resume (and /resume) reports "No conversations found to resume" even when the project bucket for that path contains many sessions. Sessions are still being written to the correct bucket — the bug is in how the picker reads them.

Environment

  • Claude Code: 2.1.132
  • Platform: macOS (Darwin 25.3.0, arm64)
  • Repo layout: parent repo with a git submodule at packages/bundles (its .git is a file pointing to <parent>/.git/modules/packages/bundles)

Reproduction

  1. Have a parent repo containing a git submodule at, e.g., packages/bundles.
  2. From the parent repo root, start a Claude Code session, then cd packages/bundles (or start a session there directly). Have a real conversation. Exit.
  3. cd packages/bundles && claude --resume

Expected: The picker lists sessions from the submodule's project bucket (~/.claude/projects/-...-langdock-packages-bundles/).

Actual: "No conversations found to resume." — even though ~/.claude/projects/-...-langdock-packages-bundles/ contains 100+ jsonl files (including ones written today).

Resuming from the parent repo root does show those bundles sessions (because the parent worktree path is a prefix of the bundles project path).

Root cause

The resume picker resolves the project path via git worktree list --porcelain (function gkH in the bundled CLI):

async function gkH(H) {
  let { stdout: q } = await P8(C8(), ["worktree", "list", "--porcelain"], { cwd: H, ... });
  let T = q.split("\n").filter($ => $.startsWith("worktree ")).map($ => $.slice(9).normalize("NFC"));
  let A = T.find($ => H === $ || H.startsWith($ + path.sep));
  ...
}

For a submodule, git worktree list --porcelain returns the main worktree as the internal git dir, not the checkout path:

$ cd packages/bundles && git worktree list --porcelain
worktree /Users/me/Projects/langdock/.git/modules/packages/bundles
HEAD ...
branch refs/heads/...

The cwd is /Users/me/Projects/langdock/packages/bundles. None of the returned worktree paths equal it, and cwd.startsWith(worktreePath + sep) is false for every entry (the .git/modules/... path is not an ancestor of the checkout). So A is undefined, the worktree list passed to the session loader (MY6) doesn't include the actual checkout path, and the loader returns no sessions for that bucket.

filterResumableSessions (V1K) then sees an empty list and the picker reports "No conversations found to resume." Meanwhile sessions are still written to ~/.claude/projects/<cwd-encoded-as-slug>/... via a separate code path that uses cwd directly, so the bucket fills up but reads can never find it.

Suggested fix

When gkH finds no worktree entry that matches cwd (or when the matching entry is under .git/modules/), fall back to the cwd itself as the project path. Alternatively, detect submodules (e.g., parse .git as a file containing gitdir: ...) and substitute the real checkout dir for the .git/modules/... path returned by git worktree list.

Workarounds

  • Resume from the parent repo root (sessions in subdirectories show up via the startsWith check).
  • Name sessions upfront: claude -n my-task then claude --resume my-task — name-based resume bypasses the picker filter.
  • Resume by exact session ID: claude --resume <uuid> also bypasses the picker.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING