# resume picker: fix worktree-clash guidance (wrong session + shell injection)

`784ad29`→[main](/content/gh/entireio/cli/commits/main/index.html)·

The "branch checked out in another worktree" path told the user to run
\`entire resume <branch>\`, which resumes the branch's LATEST checkpoint — reintroducing the wrong-session bug for the clash case when several sessions share a branch. It also interpolated the branch (and path) into a copy-paste shell command unquoted, so a branch like \`x;echo pwn\` or a path with shell metacharacters could execute unintended tokens.

Now the guidance points the user to re-run the picker in that worktree
(\`cd <path> && entire session resume\`), which preserves the
selected-session flow (the picker resumes the exact session by its
checkpoint). The branch is no longer part of the command — it appears
only in non-executable prose — and the worktree path is shell-quoted via
a new shellQuote helper.

Message building is factored into worktreeClashMessage; tests cover the
picker-not-branch-arg guidance and injection-safety for both a malicious
branch name and a path containing $(...) or apostrophes.

## Sessions

2fe06f6e777dView transcript

[?\
Interactive Resume Picker for SessionsClaude Code·Opus 4.8\[1m\]·5 steps](/content/gh/entireio/cli/session/d7eb2c7b-65ce-4dbe-b20a-285326019897#timeline-2fe06f6e777d/index.html)

## Changes

2

- cmd/entire/cli  
  
  - Mresume_picker.go+34/-5
  
  - Mresume_picker_test.go+81

```
119 unmodified lines

return fmt.Sprintf("%s · \"%s\" · %s · last active %s", item.branch, prompt, agentLabel, when)

// shellQuote wraps a string in single quotes for safe inclusion in a copy-paste
// /bin/sh command, escaping any embedded single quotes. Prevents shell
// metacharacters in paths (or other interpolated values) from being executed.
func shellQuote(s string) string {
    return "'" + strings.ReplaceAll(s, "'", "'\\'\'") + "'"
}

// worktreeClashMessage builds the guidance shown when the chosen session's branch
// is already checked out in another worktree. It steers the user to re-run the
// picker in that worktree (which resumes the exact selected session by its
// checkpoint) rather than `entire resume <branch>` (which would resume the
// branch's latest checkpoint and pick the wrong session when several share it).
// The only value placed in the copy-paste command is the worktree path, and it
// is shell-quoted; the branch name appears only in non-executable prose.
func worktreeClashMessage(branch, otherPath, lastPrompt string) string {
    var b strings.Builder
    fmt.Fprintf(&b, "Branch %q is already checked out in another worktree:\n", branch)
    fmt.Fprintf(&b, "  %s\n", otherPath)
    if prompt := strings.TrimSpace(lastPrompt); prompt != "" {
        fmt.Fprintf(&b, "\nResume this session (%q) there by running the picker in that worktree:\n",
            stringutil.TruncateRunes(stringutil.CollapseWhitespace(prompt), 50, "..."))
    } else {
        b.WriteString("\nResume this session there by running the picker in that worktree:\n")
    }
    fmt.Fprintf(&b, "  cd %s && entire session resume\n", shellQuote(otherPath))
    return b.String()
}

// branchCheckedOutElsewhere reports whether branch is checked out in a worktree
// other than the current one, returning that worktree's path.
func branchCheckedOutElsewhere(ctx context.Context, branch string) (string, bool) {
    // implementation here...  
}
```

Mcmd/entire/cli/resume_picker_test.go+81

```
