Skip to content

feat(uri): add warposs://pane/{uuid} deep link for pane focus#9655

Merged
seemeroland merged 8 commits intowarpdotdev:masterfrom
Akeuuh:axel/feat-pane-deeplink
May 6, 2026
Merged

feat(uri): add warposs://pane/{uuid} deep link for pane focus#9655
seemeroland merged 8 commits intowarpdotdev:masterfrom
Akeuuh:axel/feat-pane-deeplink

Conversation

@Akeuuh
Copy link
Copy Markdown
Contributor

@Akeuuh Akeuuh commented Apr 30, 2026

Description

Adds a warposs://pane/{uuid_hex} deep link that focuses a specific terminal pane by its persistent session UUID. This enables external tools to programmatically switch to a given pane/tab/window in Warp.

What

  • PaneGroup::find_pane_by_session_uuid — new method that iterates terminal panes and matches by persistent UUID bytes, returning the PaneId
  • UriHost::Pane — new URI host variant with full handler: decodes 32-char hex UUID, walks all workspaces/windows via WorkspaceRegistry::all_workspaces(), dispatches handle_pane_navigation_event to focus the tab, and calls show_window_and_focus_app to bring the window forward
  • 5 unit tests — host parsing, full URI validation, empty path safety, invalid hex safety, case-insensitive hex decoding

Why

External tools (e.g. orchestration UIs) that know a pane's UUID need a way to switch focus to that pane without user interaction. The pane UUID is already persisted in SQLite and is stable across sessions.

How

  • Handler parses hex from URL path, converts to [u8; 16] via u8::from_str_radix (no new crate dependency)
  • Cross-window lookup via existing WorkspaceRegistry::all_workspaces() + tab_views() pattern (matches focus_terminal_view_in_other_window)
  • WindowBehaviorHint::Nothing since handler explicitly manages window focus
  • O(n) pane iteration — deep links are rare, no cache needed

Testing

  • Unit tests for URI parsing and validation (5 tests in uri_test.rs)
  • Manual testing: open "warposs://pane/{uuid}" correctly focuses the target pane across tabs and windows

Co-Authored-By: Warp [email protected]

@cla-bot cla-bot Bot added the cla-signed label Apr 30, 2026
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented Apr 30, 2026

@Akeuuh

I ran into an unexpected error while working on this.

Powered by Oz

Akeuuh and others added 3 commits April 30, 2026 21:51
Add PaneGroup::find_pane_by_session_uuid(&[u8]) -> Option<PaneId>
that iterates terminal panes and matches by persistent session UUID.
This enables deep link handlers to locate a specific pane across
all windows without exposing session_uuid() outside pane_group.

Co-Authored-By: Warp <[email protected]>
Add UriHost::Pane variant that accepts a 32-char hex UUID in the path,
decodes it to bytes, walks all workspaces/windows to find the matching
terminal pane via find_pane_by_session_uuid, then focuses the window
and dispatches handle_pane_navigation_event to switch to that tab.

Uses WindowBehaviorHint::Nothing since the handler explicitly calls
show_window_and_focus_app. Allows arbitrary path in validate_custom_uri.

Co-Authored-By: Warp <[email protected]>
Cover host parsing, full URI validation, empty path handling,
invalid hex rejection, and case-insensitive hex decoding.

Co-Authored-By: Warp <[email protected]>
@Akeuuh Akeuuh force-pushed the axel/feat-pane-deeplink branch from 7f548d4 to a0e5fae Compare April 30, 2026 19:53
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a warposs://pane/{uuid_hex} custom URI host that decodes a 32-character pane UUID, searches registered workspaces for the matching terminal pane, and dispatches the existing pane navigation action to focus it. It also adds URI parsing and validation coverage for the new host.

Concerns

  • No blocking correctness or security concerns found in the changed diff lines.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot requested a review from seemeroland April 30, 2026 20:00
@seemeroland
Copy link
Copy Markdown
Contributor

seemeroland commented Apr 30, 2026

Same question and nits as in the original review: #9613 (review)

How do you anticipate users getting the session_uuid to use with this URI? I don't believe we expose this in a nice way. Were you thinking of reading from sqlite? Trying to understand the use case for this

@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented Apr 30, 2026

Same question and nits as in the original review: #9613 (review)

How do you anticipate users getting the session_uuid to use with this URI? I don't believe we expose this in a nice way. Were you thinking of reading from sqlite? Trying to understand the use case for this

My bad, it's true I did not explain the usecase

I'm using ( and try to contribute to ) an open source project : Open Vibe Island (https://github.com/Octane0411/open-vibe-island), a macOS menubar app that monitors AI coding agents running inside Warp.
When I click on a running agent session in the Open Vibe Island notch UI, I want to jump directly to that Warp pane — hence the pane/ deep link.

How an external app retrieves pane UUIDs:
Warp persists terminal pane state in a local SQLite database:
~/Library/Application Support/dev.warp.Warp-Stable/warp.sqlite

The terminal_panes table has a uuid column (16-byte BLOB, unique):
SELECT hex(uuid), cwd, is_active FROM terminal_panes WHERE is_active = 1;

The returned hex string is used directly in the deep link:
warp://pane/A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4

This is the same approach Warp itself uses for persistence — the UUID is the canonical pane identifier across restarts. An external app just reads the same DB.

No new API surface is needed: the SQLite file is already world-readable on macOS, and the schema is stable (diesel-managed migrations).

Thank you for taking time on this PR ;-)

@seemeroland

oz-for-oss[bot]
oz-for-oss Bot previously requested changes Apr 30, 2026
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a warposs://pane/{uuid} custom URI host that decodes a 32-character hex UUID, searches registered workspaces for a matching terminal pane UUID, and dispatches the existing pane navigation action to focus it.

Concerns

  • The new pane UUID lookup scans all terminal pane contents, including panes retained but hidden by pane-tree state, so a stale or hidden pane UUID can be treated as a successful match instead of being ignored.
  • The case-insensitive decoding test reimplements the decoding logic locally instead of exercising the production decode path.

Verdict

Found: 0 critical, 1 important, 1 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/pane_group/mod.rs Outdated
Comment thread app/src/uri/uri_test.rs Outdated
find_pane_by_session_uuid now skips panes hidden for undo-close so
deep links cannot resolve to unfocusable targets.

Extract decode_uuid_hex helper shared between handler and tests.
Add coverage for wrong-length and invalid-char hex inputs.
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

Adds a warposs://pane/{uuid} URI host that decodes 32-char hex session UUIDs, finds a matching visible terminal pane across registered workspaces, focuses the corresponding pane/tab/window, and adds URI/hex parsing unit coverage.

Concerns

  • Supplemental security pass: no blocking issues found. The handler avoids logging UUID values and rejects malformed hex before lookup.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented Apr 30, 2026

/oz-review

oz-for-oss[bot]
oz-for-oss Bot previously requested changes Apr 30, 2026
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a warposs://pane/{uuid} custom URI host that looks up terminal panes by persistent session UUID and focuses the matching pane across workspaces/windows.

Concerns

  • The UUID decoder can panic on non-ASCII path segments because it slices a UTF-8 string at fixed byte offsets after only checking byte length. Since custom URIs are external inputs, malformed links should be rejected without crashing.

Verdict

Found: 1 critical, 0 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/uri/mod.rs
Use as_bytes() + chunks_exact(2) instead of str slicing by byte offset,
which can panic on multi-byte UTF-8 characters in external URI input.
@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented May 1, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 1, 2026

@Akeuuh

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

oz-for-oss[bot]
oz-for-oss Bot previously requested changes May 1, 2026
Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a warposs://pane/{uuid} custom URI host that scans registered workspaces for a terminal pane by persistent session UUID and focuses the containing window/tab/pane.

Concerns

  • [SECURITY] The new route places a stable pane/session identifier in url.path(), but handle_incoming_uri logs scheme/host/path through safe_url_log_fields before dispatch. That means pane deeplinks will persist capability-like focus tokens in release logs unless the pane path is redacted or the token is moved out of logged fields.

Security

  • Redact pane deeplink UUIDs from URI logs before enabling this route.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/uri/mod.rs
Pane UUIDs are stable session identifiers — logging them via
safe_url_log_fields persists focus tokens. Redact path for pane URIs.
@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented May 1, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 1, 2026

@Akeuuh

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I reviewed this pull request and requested human review from: @seemeroland.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot dismissed stale reviews from themself May 1, 2026 20:23

Oz no longer requests changes for this pull request after the latest automated review.

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a pane URI host for focusing an existing terminal pane by its persistent session UUID, including UUID hex decoding, workspace-wide lookup, window focus/navigation dispatch, safe URL logging redaction, and unit coverage for parsing/validation helpers.

Concerns

  • No blocking correctness or security concerns found in the changed lines.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a pane URI host for focusing an existing terminal pane by its persistent session UUID, including UUID hex decoding, workspace-wide lookup, window focus/navigation dispatch, safe URL logging redaction, and unit coverage for parsing/validation helpers.

Concerns

  • No blocking correctness or security concerns found in the changed lines.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@seemeroland seemeroland left a comment

Choose a reason for hiding this comment

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

I see, we probably should expose IDs in another way rather than require querying the sqlite table, but it seems fine to add the URI regardless. The session UUID is specifically for a terminal pane, and is different from the PaneId which is usually used to identify a pane generically (there are other types of panes than terminal panes).

Since you need the UUID to be stable across session restarts, the session UUID seems fine. But I would rename to make it clear that this is not a pane ID. Specifically:

  • The URI should be /session/{uuid}

Comment thread app/src/pane_group/mod.rs Outdated

/// Returns the [`PaneId`] of the terminal pane whose persistent UUID matches
/// the given bytes, or `None` if no such pane exists in this group.
pub fn find_pane_by_session_uuid(&self, uuid: &[u8]) -> Option<PaneId> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: find_terminal_pane_by_session_uuid

Comment thread app/src/uri/mod.rs Outdated
/// Actions triggered from Linear integrations (e.g. work on issue).
Linear,
/// Focuses a specific terminal pane by its persistent UUID.
Pane,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Session, assuming we want to find by session UUID and not PaneId

Comment thread app/src/uri/mod.rs Outdated
url.path(),
)
let host = url.host_str().unwrap_or("-");
let path = if host == "pane" { "[redacted]" } else { url.path() };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: I know the oz review flagged this, but I don't think the path is sensitive info and it should be fine to log it. I don't think we need to change this and I don't love this special check for pane host

The URI identifies a terminal session UUID, not a generic PaneId.
- UriHost::Pane → UriHost::Session, route is now warposs://session/{uuid}
- find_pane_by_session_uuid → find_terminal_pane_by_session_uuid
- Remove unnecessary path redaction in safe_url_log_fields
@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented May 5, 2026

@seemeroland Thanks for the review! All addressed in 6dd92af:

  • UriHost::PaneUriHost::Session, route is now warposs://session/{uuid}
  • find_pane_by_session_uuidfind_terminal_pane_by_session_uuid
  • Removed the path redaction special-case in safe_url_log_fields

Let me know if anything else needs adjusting.

@Akeuuh Akeuuh requested a review from seemeroland May 5, 2026 22:06
Copy link
Copy Markdown
Contributor

@seemeroland seemeroland left a comment

Choose a reason for hiding this comment

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

Thanks for iterating!

@seemeroland seemeroland enabled auto-merge (squash) May 6, 2026 04:09
@seemeroland seemeroland merged commit 27f4933 into warpdotdev:master May 6, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants