Skip to content

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

Closed
Akeuuh wants to merge 19 commits intowarpdotdev:masterfrom
Akeuuh:aleclercq/feat-pane-deeplink
Closed

feat(uri): add warposs://pane/{uuid} deep link for pane focus#9613
Akeuuh wants to merge 19 commits intowarpdotdev:masterfrom
Akeuuh:aleclercq/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]

anshul-garg27 and others added 19 commits April 30, 2026 08:15
### Description

The Warp Drive import flow lets users pick workflow (YAML) and notebook
(Markdown) files. The picker uses `FileType::Yaml` and
`FileType::Markdown` from `warpui_core::platform::file_picker`, which
previously listed only `yaml` and `md`. That doesn't match what the
importer is willing to ingest:

-
[`app/src/drive/import/nodes.rs`](https://github.com/warpdotdev/warp/blob/main/app/src/drive/import/nodes.rs)
(`TryFrom<&Path> for FileType`) accepts both `.yaml` and `.yml` for
workflows.
-
[`warp_util::file_type::is_markdown_file`](https://github.com/warpdotdev/warp/blob/main/crates/warp_util/src/file_type.rs)
recognises both `.md` and `.markdown` (`MARKDOWN_EXTENSIONS`).
- The import modal's helper text in `modal_body.rs` already advertises
`"md, yaml, yml"` to users.

The result: a user can drag-and-drop a `.yml` workflow or `.markdown`
notebook and it imports cleanly, but the file picker filter hides those
same files when they click "Choose files…". This change brings the
picker in line with what the rest of the import path already accepts.

I left `FileType::Image` alone — that one has a separate user-facing
contract (the theme creator body explicitly says \"(.png, .jpg)\"), so
broadening it would need its own design decision.

### Testing

- Added two unit tests covering both extensions for `FileType::Yaml` and
`FileType::Markdown`.
- `cargo fmt -p warpui_core -- --check`
- Couldn't run the full `cargo nextest` locally (Metal toolchain not
available on this machine), the change is well-scoped to a const-array
literal so risk is low.

### Server API

No server changes.

### Agent Mode

Not applicable.

### Changelog Entries

- Warp Drive import file picker now lists `.yml` and `.markdown` files
in addition to `.yaml` and `.md`.

---------

Co-authored-by: anshul-garg27 <[email protected]>
Co-authored-by: anshul-garg27 <[email protected]>
## Description

The link to the tree-sitter docs in
`crates/languages/grammars/README.md` is missing the closing `]`, so
GitHub renders it as plain text instead of a link:

```diff
-We need a [TSLanguage(https://tree-sitter.github.io/tree-sitter/using-parsers#the-basic-objects) object to parse a source code file.
+We need a [TSLanguage](https://tree-sitter.github.io/tree-sitter/using-parsers#the-basic-objects) object to parse a source code file.
```

## Testing

Docs-only change. Verified the rendered link is clickable in the GitHub
Markdown preview.

Co-authored-by: anshul-garg27 <[email protected]>
## Description

Fixes 18 spelling typos across 16 code-comment locations. All changes
are inside `//` or `///` comments; no functional code is touched.
Categories:

- `concious` -> `conscious`, `Wether` -> `Whether`, `psuedo` ->
`pseudo`, `occassion` -> `occasion`, `calcuates` -> `calculates`
(single-word slips)
- `succesful` / `succesfully` -> `successful` / `successfully` (x3)
- `recieve` / `recieved` / `recieves` -> `receive` / `received` /
`receives` (x4)
- `occured` -> `occurred` (x2)
- `seperate`, `seperator`, `indvidual`, `accross`, `refering` ->
standard spellings

Skipped intentionally:
- `crates/ai/src/diff_validation/mod_test.rs:13` - the typo there is
inside a verbatim GNU/Linux copypasta string used as test input.
- `resources/bundled/mcp_skills/figma/...` - vendor documentation.

## Testing

Comment-only changes; no test impact.

## Agent Mode

- [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Co-authored-by: BennyWaitWhat <[email protected]>
## Description

This passes the app version through to `clap`, so that the `--version`
flag is supported.

## Testing

Ran locally with `--version` and `-V`, using a fake Git release tag.

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

## Changelog Entries for Stable
CHANGELOG-BUG-FIX: Added `--version` flag support in the Oz CLI
## Description

Adds Block's [Goose](https://github.com/block/goose) to the `CLIAgent`
enum so that running `goose` in a Warp terminal triggers the CLI-agent
toolbar, status, brand color, and icon — the same wrapper experience the
other recognized agents (Claude Code, Codex, Gemini, Amp, Droid,
OpenCode, Copilot, Pi, Auggie, Cursor) already get.

Without this change, `goose` runs as a plain terminal command and none
of the wrapper UI activates, even though the rest of the CLI-agent
infrastructure works fine for it once detection is in place.

Goose is wired in as a third-party agent without a first-party plugin
(mirroring Pi / Copilot / Cursor):
- No `CliAgentPluginManager` — falls through to the `None` arm in
`plugin_manager_for_with_shell`
- No `CLIAgentSessionHandler` — falls through to the `None` arm in
`create_handler`, and is implicitly excluded from `is_agent_supported`
via `matches!`
- Default `Inline` rich-input submit strategy

The `enum_iterator::Sequence`-driven detection in `CLIAgent::detect`
picks `goose` up automatically from `command_prefix()`, so no detection
plumbing is needed beyond the variant.

### Files touched
| File | Change |
|---|---|
| `app/src/terminal/cli_agent.rs` | New `GOOSE_COLOR` const (`#101010`),
`Goose` enum variant, match arms in `command_prefix`, `display_name`,
`icon`, `supported_skill_providers`, `brand_color`, `From<CLIAgent> for
CLIAgentType` |
| `app/src/server/telemetry/events.rs` | `CLIAgentType::Goose` |
| `crates/warp_core/src/ui/icons.rs` | `Icon::GooseLogo` + path mapping
`bundled/svg/goose.svg` |
| `app/assets/bundled/svg/goose.svg` | Official Block/Goose logo
(Apache-2.0), re-saved with the bundled-SVG `#FF0000` placeholder fill
so the runtime icon renderer applies the brand color |
| `app/src/terminal/cli_agent_sessions/plugin_manager/mod.rs` | Add
`CLIAgent::Goose` to the no-plugin-manager arm |
| `app/src/terminal/cli_agent_sessions/listener/mod.rs` | Add
`CLIAgent::Goose` to the no-handler arm |
| `app/src/terminal/view/use_agent_footer/mod.rs` | Add
`CLIAgent::Goose` to the `Inline` rich-input submit strategy arm |
| `app/src/terminal/cli_agent_tests.rs` | Add `("goose",
CLIAgent::Goose)` to `test_detect_known_agents` |

## Testing

Added `("goose", CLIAgent::Goose)` to the existing
`test_detect_known_agents` table — this is the standard regression
coverage pattern used for every other agent in this file. The test
exercises `CLIAgent::detect("goose", None, None, ctx)` and asserts it
returns `Some(CLIAgent::Goose)`.

The compiler enforces correctness for everything else: every
non-catch-all `match` on `CLIAgent` must list every variant
exhaustively, so any missed match arm would be a build failure rather
than silent wrong behavior at runtime.

**Local presubmit note:** `cargo fmt --check` passes locally. The full
`./script/presubmit` requires the Metal Toolchain (not just Xcode) to
compile shaders during the `warpui` build, and on this machine the asset
downloads but doesn't activate without further intervention. Relying on
CI to run the full `cargo clippy --workspace --all-targets --tests -- -D
warnings` and `cargo nextest run --workspace`.

## Server API dependencies

This PR does not depend on any server API changes.

## Agent Mode
- [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

## Changelog Entries for Stable

CHANGELOG-IMPROVEMENT: Recognize Block's `goose` CLI agent — running
`goose` now activates the CLI-agent toolbar, status, brand color, and
icon like other recognized third-party agents.

Fixes warpdotdev#9038
## Summary
- Ignore `.claude/worktrees/` so Claude Code worktrees created under
`.claude/` aren't surfaced as untracked files.

## Test plan
- [x] `git status` no longer shows `.claude/worktrees/` entries when a
worktree exists there.
…v#9410)

### Description

\`docker/linux-dev/README.md\` still referenced the private
\`warp-internal\` repository in two places (a sentence about the repo
root, and a comment in the docker-run snippet). External contributors
following this doc would be looking for a repo they can't access.

Updated:

- \"You'll run all of these commands from the \`warp-internal\`
repository's root directory.\" → drop the repo name (\"the repository's
root directory\").
- \"This can be the \`warp-internal\` repository or some parent
directory of your choice.\" → \"the \`warp\` repository or some parent
directory of your choice.\"

Doc-only.

### Testing

Markdown only.

### Server API

No server changes.

### Agent Mode

Not applicable.

### Changelog Entries

None.

Co-authored-by: anshul-garg27 <[email protected]>
…arpdotdev#9409)

## Description

Renames a misspelled identifier (`delimeter` -> `delimiter`) across two
modules. Pure rename: 2 files, +9/-9 lines, no behavioral change.

**`app/src/env_vars/mod.rs`** - 6 changes:
- `pub fn export_variables(&self, delimeter: &str, ...)` -> `delimiter`
(parameter name)
- Internal call site
- Private `serialize_variables_internal(..., delimeter: &str, ...)`
parameter
- Three doc comments referencing the parameter

**`app/src/external_secrets/mod.rs`** - 3 changes:
- `static ref WARP_SECRET_DELIMETER` -> `WARP_SECRET_DELIMITER` (the
constant *identifier*)
- Two usages of the constant

### What is intentionally preserved

The **string literal value** `"/warp-secret-delimeter/"` on line 22 is
**kept as-is**. It is the runtime separator embedded in the `lpass
--format=%an{}%ai` command and split back out of lpass's output
(`line.split(*WARP_SECRET_DELIMITER)`). Changing the value would mean
output emitted with one delimiter is parsed with another, breaking
LastPass secret enumeration. Only the Rust identifier name is corrected;
the on-the-wire token is unchanged.

### Caller analysis

All three external call sites of `export_variables` (in
`drive/index.rs`, `drive/export.rs`, `terminal/input.rs`) use positional
arguments. Rust does not have named arguments, so the parameter rename
is invisible to callers and breaks nothing.

### Related

The comment `// Used as a delimeter to separate metadata` on line 20 of
`external_secrets/mod.rs` is deliberately left for PR warpdotdev#9404 (the round-3
typo bundle), which already includes that fix. Different lines, no
conflict.

## Testing

Pure identifier rename; no logic touched. The string-literal
preservation note above is the only correctness-relevant detail.

## Agent Mode

- [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Co-authored-by: BennyWaitWhat <[email protected]>
### Description

Two README files in \`crates/\` had typos and one had an ambiguous file
reference:

**\`crates/warpui_core/README.md\`**
- \"to do describe\" → \"To describe\"
- \"appearence\" → \"appearance\"
- \"precicely\" → \"precisely\"
- \"handlign\" → \"handling\"

**\`crates/lsp/README.md\`**
- \"implmentation\" → \"implementation\"
- The README said \"See main.rs for an example implementation\" but
there is no \`main.rs\` in \`crates/lsp/src/\`. The example actually
lives at \`crates/lsp/examples/rust-lsp/main.rs\`, so I made the path
explicit.

Doc-only changes.

### Testing

Markdown only.

### Server API

No server changes.

### Agent Mode

Not applicable.

### Changelog Entries

None.

Co-authored-by: anshul-garg27 <[email protected]>
### Description

The env_vars README ("up-to-date as of 6/26/2024") still references
three filenames that have moved or been renamed in the meantime. The
prose description of each file still matches the actual contents — only
the filenames changed.

| README path | Actual path |
|---|---|
| \`app/src/server/update_manager.rs\` |
\`app/src/server/cloud_objects/update_manager.rs\` |
| \`command_dialog/view.rs\` | \`command_dialog/command_dialog_view.rs\`
|
| \`section_headers_and_footers.rs\` | \`fixed_view_components.rs\`
(still defines \`render_trash_banner\` and \`render_save_button\`) |

I deliberately left the rest of the README alone — the other paths it
points at all still exist (verified locally with \`test -f\`).

### Testing

Markdown only — nothing to run.

### Server API

No server changes.

### Agent Mode

Not applicable.

### Changelog Entries

None.

Co-authored-by: anshul-garg27 <[email protected]>
### Description

Spotted while running another doc audit: `app/src/persistence/README.md`
still describes the migration workflow in terms of the pre-open-source
layout. `schema.rs` and `schema.patch` actually live under
`crates/persistence/` now, and the doc also still tells contributors to
`cd <warp-internal repo>`.

Three small text-only fixes:

- `app/src/persistence/schema.rs` → `crates/persistence/src/schema.rs`
- `app/src/persistence/schema.patch` → `crates/persistence/schema.patch`
- `cd <warp-internal repo>` → `cd <repo root>` (this is the public repo
now; contributors clone it under whatever name they pick)

I deliberately left the `our fork of diesel_cli` paragraph alone —
`script/install_cargo_build_deps` calls `cargo binstall --force -y
diesel_cli` which suggests it currently uses upstream, but I'd rather a
maintainer confirm whether the bundled-SQLite behavior the README claims
is still accurate before rewording that section.

### Testing

Markdown only — nothing to run.

### Server API

No server changes.

### Agent Mode

Not applicable.

### Changelog Entries

None.

---------

Co-authored-by: anshul-garg27 <[email protected]>
## Description

Fixes a typo in the `process_emphasis` doc comment in
`crates/markdown_parser/src/markdown_parser.rs`: `performace` →
`performance`.

## Testing

Doc-comment-only change.

Co-authored-by: anshul-garg27 <[email protected]>
## Description
Simplifies the public-facing pull request template by removing
internal-only sections and guiding contributors toward the
issue-readiness workflow.

Changes:
- Removed the `Server API dependencies` section and its internal Notion
links.
- Removed the `Changelog Entries for Stable` section (internal release
process).
- Removed the testing-policy Notion link from the `Testing` section.
- Added a `Linked Issue` section with checkboxes asking authors to
confirm:
  - The linked issue is labeled `ready-to-spec` or `ready-to-implement`.
- Screenshots or a short video of the implementation are included where
appropriate.
- Added a `Screenshots / Videos` section as a place to attach that
media.

## Testing
Documentation-only change; verified the rendered template via `git
diff`.

_Conversation:
https://staging.warp.dev/conversation/7821ed8c-960f-406d-bec1-485a6c540873_
_Run:
https://oz.staging.warp.dev/runs/019dd545-1271-74cb-81ad-2545e30fb1fc_

_This PR was generated with [Oz](https://warp.dev/oz)._

---------

Co-authored-by: Oz <[email protected]>
…, and FAQ (warpdotdev#9473)

## Description

Surface the **`#oss-contributors`** Slack channel
([link](https://warpcommunity.slack.com/archives/C0B0LM8N4DB)) as the
dedicated place for contributors to chat with each other and the Warp
team in the docs new contributors actually read.

- **`README.md`** — adds a `[!TIP]` callout under "Open Source &
Contributing", and updates the "Support and Questions" bullet to point
at `#oss-contributors`.
- **`CONTRIBUTING.md`** — adds a `[!TIP]` callout near the top so
contributors see it as soon as they land, and updates the "Getting Help"
bullet at the bottom.
- **`FAQ.md`** — updates the "Where do I get help?" bullet.

The existing
[`go.warp.dev/join-preview`](https://go.warp.dev/join-preview) link is
preserved as the workspace on-ramp for people who aren't yet in the Warp
Slack.

## Testing

Docs-only change — rendered the markdown locally to confirm the
GitHub-flavored `[!TIP]` callouts and Slack/`go.warp.dev` links render
correctly.

## Server API dependencies

N/A — docs only.

## Agent Mode

- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

## Changelog Entries for Stable

<!-- Docs-only change; no changelog entry. -->

---


[Conversation](https://staging.warp.dev/conversation/1011b077-6ef3-4516-857f-85043490d114)

Co-Authored-By: Oz <[email protected]>

Co-authored-by: Oz <[email protected]>
…otdev#9328)

## Description


[APP-3805](https://linear.app/warpdotdev/issue/APP-3805/client-server-version-skew)
— handle client/server version skew for the SSH remote-server binary.

Previously the remote binary lived at a single unversioned path. When a
client updated but the remote still had an older binary, the two could
silently go out of sync.

This PR does three things:

1. **Version the installed path.** The binary is now written to
`{dir}/{binary_name}-{version}`, so any client-server drift becomes a
path miss and triggers a reinstall. The unversioned path is kept for
`cargo run` / `deploy_remote_server` dev loops.
2. **Check versions on handshake.** `initialize()` now compares
`server_version` against the client's release tag. On mismatch, the
manager deletes the stale binary, tears the session down, and emits
`SessionConnectionFailed` so the failed-banner path fires.
3. **Auto-update without a prompt.** When `check_binary()` misses but
the remote already has an install directory, we skip the "Install Warp
SSH tools?" modal and install directly with `is_update: true`. The
shimmer reads "Updating Warp SSH Extension..." instead of
"Installing...". Dev clients without a release tag fall through to the
normal prompt so they don't accidentally CDN-install over a
locally-deployed binary.

## Testing

- `cargo test -p remote_server`, `cargo clippy -D warnings`, `cargo fmt`
— all clean.
- Manual against `[email protected]`:
  - Fresh install: modal → "Installing Warp SSH Extension..." → Ready.
- Reconnect with a newer client tag: handshake mismatch detected, stale
binary removed, reconnect reinstalls.
- Reconnect with an older client tag while a newer versioned binary is
on the remote: auto-update, no modal, "Updating..." shimmer.
  - Forced install failure on the update path: failed banner renders.

## Server API dependencies

None — warp-server already supports `?version=` on `/download/cli`
(#10284).

---------

Co-authored-by: Oz <[email protected]>
## Description

The onboarding flow managed by `OnboardingCalloutModel` was getting
triggered when Warp runs in headless SDK/CLI mode. There is no real user
to interact with the callout in those runs, so the tutorial would
silently take over the input and discard the prompt the SDK had
submitted.

This PR adds an `AppExecutionMode::can_show_onboarding` gate (which
mirrors the other `is_app()`-based capability checks) and uses it to
skip every onboarding entry point in SDK mode:

- `Workspace::start_agent_onboarding_tutorial`
- `Workspace::dispatch_tutorial_when_bootstrapped`
- `Workspace::should_show_agent_onboarding`
- `Workspace::should_trigger_get_started_onboarding`
- `Workspace::check_and_trigger_onboarding`

In `App` mode behavior is unchanged.

## Testing

`cargo check -p warp_core` and `cargo check -p warp` both pass.

## Server API dependencies

No server changes.

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

## Changelog Entries for Stable

CHANGELOG-BUG-FIX: Don't trigger the agent onboarding tutorial when Warp
is running in headless SDK/CLI mode.

_Conversation:
https://staging.warp.dev/conversation/e7e67056-a174-4995-9fb0-54c104d09d12_
_Run:
https://oz.staging.warp.dev/runs/019dde8f-ff05-716f-8c3a-e7644e40f40d_

_This PR was generated with [Oz](https://warp.dev/oz)._

Co-authored-by: Oz <[email protected]>
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]>
@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'm starting a first review of this pull request.

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).

You can view the conversation on Warp.

I completed the review and posted feedback on 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

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_hex} route that decodes a persistent pane UUID, searches existing workspaces for a matching terminal pane, and dispatches the existing pane-navigation focus action.

Concerns

  • One route-shape tightening suggestion is noted inline; no blocking correctness or security issues found in the changed lines.

Verdict

Found: 0 critical, 0 important, 1 suggestions

Approve with nits

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
Comment on lines +458 to +463
let uuid_hex = url
.path_segments()
.into_iter()
.flatten()
.last()
.unwrap_or("");
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.

💡 [SUGGESTION] The pane route is documented as exactly /pane/{uuid}, but last() also accepts /pane/anything/{uuid}; parse exactly one segment so malformed links do not focus a pane.

Suggested change
let uuid_hex = url
.path_segments()
.into_iter()
.flatten()
.last()
.unwrap_or("");
let mut path_segments = url.path_segments().into_iter().flatten();
let uuid_hex = match (path_segments.next(), path_segments.next()) {
(Some(uuid_hex), None) => uuid_hex,
_ => "",
};

@oz-for-oss oz-for-oss Bot requested a review from seemeroland April 30, 2026 15:31
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.

The code looks good to me, but 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?

Comment thread app/src/uri/mod.rs

let Some(uuid_bytes) = uuid_bytes else {
log::warn!(
"warposs://pane/ received invalid UUID hex (safe: len={})",
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: let's exclude the warposs prefix since not all builds use this name - this is only for builds built from the open source repo. Our official stable binary is just warp

Comment thread app/src/uri/mod.rs
);
}
} else {
log::warn!("warposs://pane/ could not find pane with given UUID");
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.

same nit

@captainsafia captainsafia added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label Apr 30, 2026 — with Warp Dev Github Integration
@Akeuuh Akeuuh force-pushed the aleclercq/feat-pane-deeplink branch from 3fcb57c to 7f548d4 Compare April 30, 2026 19:45
@Akeuuh
Copy link
Copy Markdown
Contributor Author

Akeuuh commented Apr 30, 2026

Reopening with renamed branch (axel/ prefix per convention)

@Akeuuh Akeuuh closed this 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’s description focuses on a pane deep link, but the diff also changes remote-server install/versioning, CLI agent detection, onboarding behavior, PR templates, docs, icons, and file picker behavior. The pane URI pieces are small; the blocking issues are in the remote-server changes.

Concerns

  • The SSH remote-server proxy launch no longer passes the hidden identity key, which can collapse identity-scoped daemon/socket isolation onto the empty identity.
  • The new version compatibility helper rejects the Local/Oss self-heal install path when it downloads a latest-for-channel binary that reports a release version.
  • The PR scope and description do not match the submitted diff, so the final PR should either be split or have an accurate description/testing section before merge.

Security

  • The remote-server identity-key regression is security-relevant because identity keys partition remote daemon sockets/PID files between app identities.

Verdict

Found: 0 critical, 2 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 on lines 192 to +196
let socket_path = self.socket_path.clone();
let remote_proxy_command = self.remote_proxy_command();
Box::pin(async move {
let mut args = ssh_args(&socket_path);
args.push(remote_proxy_command);
let binary = remote_server::setup::remote_server_binary();
let mut args = remote_server::ssh::ssh_args(&socket_path);
args.push(format!("{binary} remote-server-proxy"));
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.

⚠️ [IMPORTANT] [SECURITY] This drops the hidden --identity-key argument when launching remote-server-proxy, so sessions fall back to the empty identity and can reuse the wrong daemon/socket. Keep using remote_proxy_command() so the quoted identity key is passed through.

Suggested change
let socket_path = self.socket_path.clone();
let remote_proxy_command = self.remote_proxy_command();
Box::pin(async move {
let mut args = ssh_args(&socket_path);
args.push(remote_proxy_command);
let binary = remote_server::setup::remote_server_binary();
let mut args = remote_server::ssh::ssh_args(&socket_path);
args.push(format!("{binary} remote-server-proxy"));
let socket_path = self.socket_path.clone();
let remote_proxy_command = self.remote_proxy_command();
Box::pin(async move {
let mut args = remote_server::ssh::ssh_args(&socket_path);
args.push(remote_proxy_command);

match (client, server.is_empty()) {
(Some(c), false) => c == server,
(None, true) => true,
(Some(_), true) | (None, false) => false,
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.

⚠️ [IMPORTANT] This rejects Local/Oss clients after the self-heal install path downloads a latest-for-channel binary: the client has None but the installed dev artifact reports a non-empty version, so the code deletes the binary and fails on every reconnect. Either make version compatibility channel-aware or skip this check for unversioned channels.

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

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants