[FEATURE] $.ui.selection() should report where a selection is (element key and offsets), not just its text

Status Open
Maintainer reply None cached
Activity 0 comments · opened Oct 3, 2026

Problem Statement

In a plugin (hooks module) pane, $.ui.selection() resolves only { text, requestId? }.
requestId is only set for transcript rows, so for a selection inside a pane the plugin
learns what was selected but not where.

That makes any "annotate the selection" feature ambiguous whenever the selected text occurs
more than once in the underlying data. I hit this building a code/Markdown review pane
(select text, mark it, send all marks to Claude): selecting a common word such as storage
matches several places in the file, and the plugin cannot tell which one the user meant.
Workarounds are all lossy:

  • Search the whole file for the text and refuse if there is more than one match.
  • Rely on the Code line-number gutter being copied along with the text (only works if the

selection starts on the gutter, and the plugin must strip it from the text).

  • Ask the user to pick among the matches in the pane (works, but the user already pointed

at one place and has to point again).

Proposed Solution

Extend the UiSelection result with the position of the selection inside the drawn tree:

type UiSelection = {
  text: string
  requestId?: string
  // new, present for selections inside a plugin's Pane or Client surface
  start?: { key: string; offset: number }
  end?: { key: string; offset: number }
}
  • key is the key the plugin gave the element (e.g. a Box per Markdown block or per

code chunk), or the nearest keyed ancestor.

  • offset is a character offset into that element's drawn text: source for Code, the

rendered text for Markdown/Text. Offsets into the rendered text are enough: the plugin
can already map rendered text back to its own source.

  • For Code with startLine, the line number would also be useful, but it can be derived

from offset and source.

Alternative Solutions

  • Make the Code gutter non-selectable and expose startLine in the result, so the line is

known without parsing copied text.

  • An onSelect-style event on Text/Code/Markdown that carries the position, so the

plugin does not have to poll the selection after a button press.

Use Case Example

A review pane renders a file as keyed blocks. The user selects one occurrence of a word and
presses a hotkey to mark it as a question. The plugin gets { text: "storage", start: { key:
"seg-3", offset: 12 }, ... }
, maps it to line 5 of the file, and stores the annotation
exactly there, with no lookup ambiguity and no extra step for the user.

Additional Context

  • Related umbrella issue for the plugin/mod API: #91870.
  • API surface: $.ui.selection() in claude-code/index.d.ts (UiSelection).
  • Sample plugin that needs this: a Markdown/code review pane that sends annotations to Claude.

View original on GitHub ↗