Skip to content

Add unified surface selection context API - #10022

Open
austinywang wants to merge 17 commits into
mainfrom
issue-10020-surface-selection-context
Open

Add unified surface selection context API#10022
austinywang wants to merge 17 commits into
mainfrom
issue-10020-surface-selection-context

Conversation

@austinywang

@austinywang austinywang commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #10020

Summary

This PR adds one discoverable selection capability across selectable cmux surfaces:

  • surface.read_selection for socket clients
  • cmux read-selection --surface <ref> for source-aware CLI output
  • cmux read-screen --selection as a text-only terminal-compatible alias
  • surface.read_selection in system.capabilities / cmux capabilities

The implementation is read-only: it does not focus a window, activate a workspace, move a pane, or mutate selection state.

Uniform selection model

Every supported panel implements the same async Panel.readSurfaceSelection() capability and returns an immutable Sendable snapshot. The socket response always includes:

  • has_selection
  • kind
  • text
  • base64
  • workspace, surface, and window ids/refs, with absent window identity encoded as JSON null

It conditionally includes file_path, one-based inclusive line_range, and url when that source context exists. A supported surface with no selection succeeds with has_selection: false and empty text/base64. Unsupported panel kinds return not_supported; a supported surface whose live backing object is unavailable returns unavailable.

Snapshot construction makes selected and no-selection states distinct, and line ranges reject zero, negative, or reversed bounds. Explicit window/group/workspace/surface/pane selectors are validated before routing and fail closed instead of degrading to the focused surface. Pane-to-surface resolution lives in the shared workspace/Dock topology helpers rather than in the selection command.

Surface providers

  • Terminal: reads the live Ghostty surface directly through ghostty_surface_read_selection, without requiring a mounted GhosttySurfaceScrollView.
  • File preview and Markdown text mode: reads NSTextView.selectedRange(), extracts UTF-16-safe text, normalizes the file path, and maps the range to one-based inclusive source lines, including CRLF and selected line terminators.
  • Markdown preview: reads the live selection from the renderer-owned WKWebView and returns the Markdown file path.
  • Browser: installs one document-start tracker in the page automation world, reads DOM and editable-control selections, and follows focused same-origin frames. WebKit does not project its live Selection object into isolated content worlds, so the tracker deliberately lives in the same world that observes the selection. It owns an immutable last-selection snapshot so native focus can move to the neighboring agent surface without WebKit erasing the context before the socket read. Real page selection/focus/input changes and navigation reconcile or clear that snapshot; password controls clear it immediately, and cross-origin frame contents remain inaccessible by design. The response reports the live user-visible URL and returns immediately for an uncommitted document.

Socket and concurrency design

surface.read_selection is a worker-lane method with mainThreadCallable: false. The typed request remains intact until the async handler resolves the target. AppKit, WebKit, workspace routing, Ghostty access, and ref minting remain on the main actor. Only the immutable Sendable capture crosses back to the socket worker, where the common payload and base64 are encoded.

The async payload builder has an explicit compiler-compatible @concurrent boundary. The existing transport processes each connection on its own dedicated OS thread specifically because synchronous request/reply commands can wait on main-actor or async bridges; selection reuses that contract without blocking the listener or Swift cooperative executor. It introduces no polling, sleeps, accessibility scraping, or per-kind socket methods.

CLI and discoverability

cmux read-selection prints kind plus any file/line/URL context followed by the selected text. --json preserves the complete common response, including a successful no-selection result. Plain output also exits zero for this valid state and prints the explicit Has selection: false marker.

cmux read-screen --selection uses the same RPC and prints selected text or the no-selection marker without source metadata. It rejects --scrollback and --lines. Both read commands avoid global --window prefocus so querying another surface does not steal focus.

The CLI contract, command help, command suggestions, and capabilities output make the method discoverable.

Related terminal work

This includes the terminal socket lane and read-screen --selection behavior requested by #7500. It intentionally does not close that issue because this PR does not add its DEBUG select_all end-to-end fixture. The PR provides the production terminal read capability and alias while leaving any remaining test-seam work to that issue.

Selection-change events

Push events are intentionally separated from this authoritative read path. AppKit, Ghostty, and WebKit expose selection changes through different owners and replacement lifecycles; adding per-panel listeners here would fragment ownership and risk leaks or accidental default disclosure of selected text.

The opt-in, debounced, polling-free event design is tracked at #10027. It will reuse this common result shape while owning observer and WebView teardown centrally.

Tests and validation

Behavior coverage includes:

  • worker-lane policy, main-thread rejection, capability discovery, unavailable terminal state, common socket payload, identity fields, and base64 round-trip
  • explicit CLI surface routing, source-aware plain output, complete JSON output, alias behavior, successful no-selection output, and focus-preserving global window routing
  • UTF-16, emoji, LF/CRLF, multiline, file/Markdown panel mapping, value invariants, and fail-closed pane routing
  • browser and Markdown DOM selection, retention across a native first-responder handoff, same-origin frame selection, editable-control selection, unloaded browser behavior, live URL reporting, and password suppression
  • Xcode project test-target wiring

The first commit contains only the regression tests; the second contains the production implementation and expanded behavior coverage.

Permitted local validation completed successfully: Swift frontend parsing, project normalization/checking, test-wiring lint, JSON validation, localization audit, file-length audit, and git diff --check. Per repository guidance, no local xcodebuild, XCUITest, build, launch, or dogfood run was performed on this machine. Required GitHub checks are the compilation and test source of truth.

Localization and budgets

All new CLI help, output labels, and socket error strings use String(localized:defaultValue:) and have English and Japanese catalog entries. The touched user-facing strings and docs were audited. Every new Swift file is below 500 lines. A clean Xcode 26 compile exposed one existing unbudgeted deprecated onChange overload in SidebarWorkspaceDescriptionText; the source was migrated to the modern two-argument callback instead of increasing the warning budget. No warning-budget or file-length-budget TSV was edited or regenerated.

Summary by CodeRabbit

  • New Features
    • Added the read-selection CLI command for retrieving selected text from terminals, browsers, files, and Markdown surfaces.
    • Added JSON output with selection metadata, including file paths, line ranges, URLs, and encoded content.
    • Added read-screen --selection as a compatible alias with workspace, window, surface, and pane targeting.
    • Added the surface.read_selection socket capability with structured routing and error responses.
  • Documentation
    • Documented command usage, output formats, supported surfaces, and error behavior.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ef7b83e7-bebd-453c-8072-fb35ed24e03a

📥 Commits

Reviewing files that changed from the base of the PR and between 64428da and 8c48965.

📒 Files selected for processing (1)
  • cmuxTests/SurfaceSelectionTests.swift

📝 Walkthrough

Walkthrough

The PR implements surface.read_selection across terminal, file-preview, markdown, and browser panels. It adds socket routing, worker-lane execution, CLI commands, selection metadata, localized help, documentation, and tests.

Changes

Surface selection implementation

Layer / File(s) Summary
Selection models and panel readers
Sources/Panels/*, Sources/SurfaceSelection*
New sendable selection models and readers support native text, terminal, browser, markdown, and file-preview selections.
Socket capture and routing
Sources/TerminalController*, Sources/Workspace+RemoteTmuxControlTopology.swift
The v2 socket method validates selectors, resolves targets, reads panels asynchronously, and returns selection data or structured failures.
CLI selection commands
CLI/*, Resources/Localizable.xcstrings
The CLI adds read-selection and the read-screen --selection alias with plain and JSON output, metadata formatting, option validation, help, usage, and localization.
Validation and public contract
cmuxTests/*, docs/cli-contract.md, Packages/macOS/CmuxControlSocket/Tests/*
Tests cover panel readers, routing, output, capability advertisement, worker execution, dispatch rejection, and unavailable results. Documentation defines the socket and CLI contract.
Project integration
cmux.xcodeproj/project.pbxproj, Sources/Sidebar/SidebarWorkspaceDescriptionText.swift
The Xcode project includes the new sources and tests. The sidebar change handler uses the two-parameter closure form.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant SocketWorker
  participant TerminalController
  participant Panel
  CLI->>SocketWorker: read-selection selectors
  SocketWorker->>TerminalController: surface.read_selection
  TerminalController->>Panel: readSurfaceSelection()
  Panel-->>TerminalController: SurfaceSelectionReadResult
  TerminalController-->>SocketWorker: selection payload
  SocketWorker-->>CLI: plain or JSON output
Loading

Possibly related issues

  • manaflow-ai/cmux#10027: The new surface.read_selection snapshot API provides the foundation for future opt-in selection-change events, but this PR does not add event publishing.

Possibly related PRs

  • manaflow-ai/cmux#9708: Both PRs update socket execution-policy coverage for commands that run on the socket worker.
  • manaflow-ai/cmux#9861: Both PRs modify remote-tmux pane-targeting and workspace routing behavior.

Suggested reviewers: lawrencecchen


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (3 errors, 2 warnings)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error The new production surface.read_selection path calls v2AsyncResultCall, which uses DispatchSemaphore.wait to block a socket worker for up to five seconds while async work runs. Use an async response or continuation-based completion path, with cancellation-aware timeout handling if required, instead of blocking on semaphore.wait.
Cmux Swift Package Boundaries ❌ Error The diff adds public Foundation selection models in app Sources/Panels; they form a shared API used by native and WebKit providers, but no SwiftPM target owns them. Create Packages/macOS/CmuxSurfaceSelection with SurfaceSelectionSnapshot as the first public type, plus LineRange and ReadResult; keep AppKit, WebKit, Ghostty, and routing glue in the app.
Cmux Full Internationalization ❌ Error The PR adds 19 user-facing Localizable.xcstrings keys with only en/ja, while the touched catalog already supports 20 locales; 18 locale entries are missing. Add translated entries in Resources/Localizable.xcstrings for ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant for every new key.
Out of Scope Changes check ⚠️ Warning The selection and routing changes are in scope, but the SidebarWorkspaceDescriptionText onChange update is not tied to the linked selection objective. Remove the unrelated SidebarWorkspaceDescriptionText change or document the required dependency that makes it necessary for this feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 2.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (20 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies issue #10020 by adding CLI and socket access to selections across document, Markdown, browser, and terminal surfaces.
Cmux Swift Actor Isolation ✅ Passed New value models and socket captures are explicitly nonisolated Sendable; AppKit/WebKit panels and capture routing use MainActor boundaries, with no new shared mutable Sendable class.
Cmux Browser Automation Off-Main ✅ Passed No browser.* command changed. surface.read_selection uses the socket-worker policy, @MainActor WebKit access, and policy coverage asserting non-main routing.
Cmux Expensive Synchronous Load ✅ Passed Feature diff adds no agent-history loader or transcript/store/directory scan; its only JSONDecoder parses a bounded WebKit selection payload, and the socket method runs on the worker lane.
Cmux Cache Substitution Correctness ✅ Passed The diff adds live AppKit, WebKit, and Ghostty reads; SurfaceSelectionSnapshot is an immutable handoff, not a persisted cache, and no persistence, history, or undo read is replaced.
Cmux No Hacky Sleeps ✅ Passed The full diff contains Swift sources/tests plus localization, Xcode wiring, and Markdown docs; it introduces no TypeScript, JavaScript, shell, or build/runtime sleep or timer code.
Cmux Algorithmic Complexity ✅ Passed The production diff uses linear topology traversal and fixed-size selector checks; it adds no nested same-collection scan, batch rescan, repeated sorting/filtering, or sublinear-at-scale algorithm.
Cmux Swift Concurrency ✅ Passed The feature diff adds async/await and @MainActor bridges only; no new Dispatch queues, Combine state, completion APIs, or fire-and-forget Tasks. The sole continuation is a test WKNavigationDelegate...
Cmux Swift @Concurrent ✅ Passed The diff marks nonisolated async v2SurfaceReadSelection with @concurrent; AppKit/WebKit readers remain intentionally @MainActor, with no invalid annotation or un hopped heavy async helper found.
Cmux Swiftpm Lockfiles ✅ Passed PR diff changes no Package.swift, Package.resolved, .gitignore, workflow, or SwiftPM package-reference entries; the Xcode project edit only adds source/test files.
Cmux Swift Logging ✅ Passed The feature diff adds only intended CLI output; it adds no app/runtime print, debugPrint, dump, NSLog, ad hoc diagnostics, Logger, or sensitive-data logging.
Cmux User-Facing Error Privacy ✅ Passed Added socket errors use generic localized messages; WebKit failures map to unavailable, and no new error path exposes vendor names, raw upstream text, credentials, tokens, or payload dumps.
Cmux Swiftui State Layout ✅ Passed The diff adds no ObservableObject/@published, GeometryReader, lazy-row store reference, or render-time state mutation; it removes layout state and only incidentally updates legacy onChange/AppKit b...
Cmux Architecture Rethink ✅ Passed The diff adds no forbidden production timing, lock, polling, or observer primitives; both CLI paths use one shared helper, and selection crosses via immutable Sendable snapshots.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR adds no standalone production window or close-key workaround. Its only new NSWindow is in cmuxTests/SurfaceSelectionTests.swift, a permitted test-only fixture; selection changes do not affec...
Cmux Source Artifacts ✅ Passed The cumulative diff contains only source, tests, docs, localization, and Xcode config paths; it adds no artifact directories, binary files, logs, screenshots, recordings, caches, or build output.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR adds no test/debug-named member or test-build guard in production Sources; v2EnsureHandleRef is widened only to support the production SurfaceSelection extension, with no test accessor added.
Cmux No Ambient Global State ✅ Passed The added production APIs are methods on CMUXCLI, TerminalController, and panel types; new reader/capture types are constructable value types, with no new top-level API function, mutable global, na...
Title check ✅ Passed The title clearly summarizes the primary change: a unified surface selection context API.
Description check ✅ Passed The description thoroughly covers the change, design, testing, documentation, and limitations, but omits the template's demo video, review trigger, and checklist sections.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-10020-surface-selection-context

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+SurfaceSelection.swift:
- Around line 74-82: Update the selection handling in the relevant CLI
read-selection flow so a valid has_selection: false response returns success
instead of throwing CLIError. Define a plain-output representation for the
no-selection case that clearly distinguishes it from selection text, while
preserving existing behavior when a selection is present.

In `@cmuxTests/CLIExplicitSurfaceRoutingTests.swift`:
- Around line 136-144: Expand the assertions in the CLI JSON response test
around jsonObject so they validate every field in the no-selection payload,
including text, base64, workspace_id, workspace_ref, and surface_id alongside
the existing fields. Ensure the expected values match the complete socket
response returned by the explicit surface routing command.

In `@cmuxTests/SurfaceSelectionTests.swift`:
- Around line 81-82: Remove the fixed .timeLimit(.minutes(1)) attribute from
browserAndMarkdownPreviewReadLiveDOMSelection, leaving the correctness test’s
existing navigation-completion synchronization unchanged.
- Around line 100-101: Add positive selection coverage in
SurfaceSelectionTests.swift alongside the existing password-input cases: create
a non-password text input or textarea with selected content, then assert
hasSelection is true and the selected text matches the expected value. Keep the
existing password-selection assertions unchanged.

In `@Resources/Localizable.xcstrings`:
- Around line 102-106: Update the socket selection error localizations around
socket.surfaceSelection.tabManagerUnavailable to use stable product-facing
wording instead of internal identifiers such as TabManager or
panel.panelType.rawValue. Use wording equivalent to “Selection reading is
currently unavailable” and “This surface does not support selection reads,”
while retaining raw values only in structured diagnostics or internal logs.

In `@Sources/Panels/SurfaceSelectionSnapshot.swift`:
- Around line 12-26: Make SurfaceSelectionSnapshot construction enforce valid
selected and no-selection states rather than accepting an unrestricted
hasSelection Boolean; update Sources/Panels/SurfaceSelectionSnapshot.swift lines
12-26 accordingly. In SurfaceSelectionLineRange’s initializer at
Sources/Panels/SurfaceSelectionLineRange.swift lines 8-11, require start >= 1
and end >= start, returning or propagating an invalid conversion result so
callers handle failure before creating a snapshot.

In `@Sources/TerminalController`+SurfaceSelection.swift:
- Around line 74-75: Update the surface-selection routing around v2UUID and the
target-resolution logic near lines 157-160 to distinguish an absent pane_id from
a present but unparseable one. When pane_id is supplied and v2UUID returns nil,
return not_found or the established invalid-selector error instead of falling
back to the focused surface; preserve normal resolution for valid or omitted
pane_id values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 08a13cfd-26ea-4e56-a60d-ad1c5a8433d5

📥 Commits

Reviewing files that changed from the base of the PR and between 5269a5a and 932782b.

📒 Files selected for processing (27)
  • CLI/CMUXCLI+CommandSuggestions.swift
  • CLI/CMUXCLI+SurfaceSelection.swift
  • CLI/cmux.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Wire/ControlCommandExecutionPolicy.swift
  • Resources/Localizable.xcstrings
  • Sources/Panels/BrowserPanel.swift
  • Sources/Panels/FilePreviewPanel.swift
  • Sources/Panels/MarkdownPanel.swift
  • Sources/Panels/MarkdownWebRenderer.swift
  • Sources/Panels/MarkdownWebSupport.swift
  • Sources/Panels/NativeTextSurfaceSelectionReader.swift
  • Sources/Panels/Panel.swift
  • Sources/Panels/SurfaceSelectionLineRange.swift
  • Sources/Panels/SurfaceSelectionReadResult.swift
  • Sources/Panels/SurfaceSelectionSnapshot.swift
  • Sources/Panels/TerminalPanel.swift
  • Sources/Panels/WebSurfaceSelectionReader.swift
  • Sources/SurfaceSelectionSocketCapture.swift
  • Sources/SurfaceSelectionSocketCaptureOutcome.swift
  • Sources/SurfaceSelectionSocketFailure.swift
  • Sources/TerminalController+SurfaceSelection.swift
  • Sources/TerminalController.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/CLIExplicitSurfaceRoutingTests.swift
  • cmuxTests/SurfaceSelectionTests.swift
  • cmuxTests/TerminalControllerSocketSecurityTests.swift
  • docs/cli-contract.md

Comment thread CLI/CMUXCLI+SurfaceSelection.swift
Comment thread cmuxTests/CLIExplicitSurfaceRoutingTests.swift
Comment thread cmuxTests/SurfaceSelectionTests.swift Outdated
Comment thread cmuxTests/SurfaceSelectionTests.swift
Comment thread Resources/Localizable.xcstrings Outdated
Comment thread Sources/Panels/SurfaceSelectionSnapshot.swift Outdated
Comment thread Sources/TerminalController+SurfaceSelection.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/cli-contract.md (1)

243-243: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a UUID for surface_id in the raw RPC example.

surface.read_selection validates surface_id as a UUID. surface:2 returns invalid_params, so this documented command fails. Use a UUID value in the JSON parameters.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/cli-contract.md` at line 243, Update the surface.read_selection raw RPC
example to use a valid UUID for the surface_id JSON parameter instead of
surface:2, while preserving the command structure and parameter name.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@docs/cli-contract.md`:
- Line 243: Update the surface.read_selection raw RPC example to use a valid
UUID for the surface_id JSON parameter instead of surface:2, while preserving
the command structure and parameter name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 35c5cc92-eaf1-4c39-8bb8-3a463dc939ef

📥 Commits

Reviewing files that changed from the base of the PR and between 932782b and 3caaad1.

📒 Files selected for processing (14)
  • CLI/CMUXCLI+SurfaceSelection.swift
  • Resources/Localizable.xcstrings
  • Sources/Panels/Panel.swift
  • Sources/Panels/SurfaceSelectionLineRange.swift
  • Sources/Panels/SurfaceSelectionReadResult.swift
  • Sources/Panels/SurfaceSelectionSnapshot.swift
  • Sources/Sidebar/SidebarWorkspaceDescriptionText.swift
  • Sources/TerminalController+ControlSurfaceDock.swift
  • Sources/TerminalController+SurfaceSelection.swift
  • Sources/Workspace+RemoteTmuxControlTopology.swift
  • cmuxTests/CLIExplicitSurfaceRoutingTests.swift
  • cmuxTests/SurfaceSelectionTests.swift
  • cmuxTests/TerminalControllerSocketSecurityTests.swift
  • docs/cli-contract.md

@austinywang

austinywang commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Fixed the latest CodeRabbit documentation finding in 64428da. The raw surface.read_selection RPC example now uses a valid UUID for surface_id, while the ref-based CLI examples continue to use surface:2.

@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: expose the active surface's text selection to the agent (file/document surfaces, CLI + events)

1 participant