Initial public release of Warp.

Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
David Stern
2026-04-28 08:43:33 -05:00
commit 0dbd3d567a
4982 changed files with 1431549 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
# APP-3858: Change CLI Sharing Entrypoint to Remote Control
## Summary
Rebrand the CLI agent footer "Share session" button as "Remote control" and streamline the interaction so that a single click starts sharing, auto-copies the link to the clipboard, and shows a toast. The share modal is bypassed entirely. Once sharing is active, the same button becomes a "Stop sharing" button.
## Problem
The current "Share session" label doesn't communicate the primary use case: accessing a CLI agent session on your phone to track progress or steer it. Users don't equate "sharing" with mobile access. The current flow also requires an extra step through the share modal, which is unexpected for this use case.
## Goals
- Rename the feature to "Remote control" across the CLI agent footer entrypoint.
- One-click start: clicking the chip starts sharing immediately (without scrollback, just the current block), auto-copies the link, and shows a toast.
- Once sharing is active, the chip switches to a "Stop sharing" chip.
- Replace the `Icon::Share` icon with a phone icon (`phone-01.svg`). Use the existing `Icon::StopFilled` for the stop state.
- Add a `/remote-control` slash command that triggers the same action as clicking the chip.
## Non-goals
- Renaming the feature in contexts outside the CLI agent footer (pane header overflow menu, right-click context menu, the share modal itself). Those are separate entry points with different audiences.
- "Text link to my device" functionality (stretch goal for a follow-up).
- Changes to the viewer experience or the sharing protocol.
- Changes to the ambient agent / cloud mode share button.
## User Experience
### Before sharing
- The CLI agent footer renders a chip with the phone icon (`Icon::Phone01`) and label `/remote-control`.
- Typing `/remote-control` in the input triggers the same start-sharing action.
- The chip is only visible when `FeatureFlag::CreatingSharedSessions` and `ContextFlag::CreateSharedSession` are enabled (same gating as today).
### Starting a share (single click or slash command)
1. User clicks the `/remote-control` chip or types `/remote-control` in the input.
2. The session begins sharing immediately without scrollback (`SharedSessionScrollbackType::None`). This must be allowed even when agent conversations exist (bypassing the normal guard that blocks no-scrollback shares when `FeatureFlag::AgentSharedSessions` is enabled and conversations are present).
3. As soon as the session is established, the sharing link is auto-copied to the user's clipboard.
4. A toast appears: "Remote control link copied."
5. The share modal does **not** open.
### While sharing is active
- The chip changes to show a filled stop square (`Icon::StopFilled`) with label `Stop sharing`.
- Clicking the chip stops the sharing session.
### After sharing ends
- The chip reverts to its pre-sharing state (phone icon, `/remote-control` label).
### Edge cases
- If the session is already being shared (e.g. started from the pane header menu), the footer button should reflect the active sharing state (show stop button).
- If another share was started via a different entry point that used the share modal, the footer chip still shows "Stop sharing" while the session is active.
- If sharing fails to start (e.g. network error), the button should revert to its default state. Existing error handling for `SharePending` → failure applies.
### Banners
When sharing is started from the remote control entrypoint, the inline banners use different copy than the default:
- Start banner: "Remote control active" (instead of "Sharing started")
- End banner: "Remote control stopped" (instead of "Sharing ended")
Shares started from other entry points (pane header, share modal, etc.) keep the default "Sharing started" / "Sharing ended" copy. This intentionally deviates from the Figma mocks, which show the generic phrasing.
## Success Criteria
1. The CLI agent footer chip displays the phone icon and `/remote-control` label when no session is being shared.
2. Clicking the chip starts sharing without scrollback and does **not** open the share modal.
3. After sharing starts, the link is in the user's clipboard and a "Remote control link copied." toast is visible.
4. While sharing is active, the chip shows `StopFilled` icon with label "Stop sharing".
5. Clicking the stop chip ends the sharing session and the chip reverts to its default state.
6. The chip correctly reflects sharing state even when sharing was started/stopped from a different entry point.
7. Typing `/remote-control` in the agent input triggers the same start-sharing flow.
## Validation
- Build the app and verify the button icon, tooltip, and click behavior in a CLI agent session.
- Verify that clicking the button copies a valid sharing link to the clipboard.
- Verify the toast appears.
- Verify the button toggles to stop state while sharing is active.
- Verify the button reverts after stopping.
- Existing shared session tests should continue to pass since the underlying sharing mechanism is unchanged.
## Open Questions
- Should the agent view (non-CLI) share button also be rebranded to "Remote control", or only the CLI agent footer? (Current decision: only CLI agent footer for now.)
+146
View File
@@ -0,0 +1,146 @@
# APP-3858: Tech Spec — Remote Control Entrypoint
## Problem
The CLI agent footer's "Share session" button opens the share modal, which is an unnecessary step for the primary use case (quick mobile handoff). We need to make it a one-click action that starts sharing without scrollback, auto-copies the link, and shows a stop button while active.
## Relevant Code
- `crates/warp_core/src/ui/icons.rs (10-296)``Icon` enum; needs `Phone01` variant
- `app/assets/bundled/svg/phone-01.svg` — phone icon for start-state (on branch)
- `Icon::StopFilled` — existing icon reused for stop-state
- `app/src/search/slash_command_menu/static_commands/commands.rs` — slash command definitions
- `app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs (491-500)``share_session_button` creation
- `app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs (1104-1108)` — CLI toolbar `ShareSession` render
- `app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs (1636-1644)` — agent view toolbar `ShareSession` render
- `app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs (1893, 2025-2027)``AgentInputFooterAction::ShareSession` handler
- `app/src/ai/blocklist/agent_view/agent_input_footer/mod.rs (2037-2045)``AgentInputFooterEvent` enum
- `app/src/ai/blocklist/agent_view/agent_input_footer/toolbar_item.rs (48, 74, 88)``AgentToolbarItemKind::ShareSession` display label and icon
- `app/src/terminal/view/use_agent_footer/mod.rs (217-218, 851-852)` — event forwarding
- `app/src/terminal/view/use_agent_footer/mod.rs (1019-1041)``UseAgentToolbarEvent` enum
- `app/src/terminal/view/shared_session/view_impl.rs (415-472)``attempt_to_share_session` (scrollback guard at 436-448)
- `app/src/terminal/view/shared_session/view_impl.rs (476-520)``on_session_share_started` (auto-opens sharing dialog at 515)
- `app/src/terminal/view/shared_session/view_impl.rs (522-529)``stop_sharing_session`
- `app/src/terminal/view/shared_session/view_impl.rs (1288-1311)``copy_shared_session_link`
- `app/src/terminal/shared_session/mod.rs (39)``COPY_LINK_TEXT` constant
- `app/src/terminal/shared_session/mod.rs (267-290)``SharedSessionActionSource` enum
## Current State
**Button**: A single static `share_session_button` with `Icon::Share`, tooltip "Share session". Click dispatches `AgentInputFooterAction::ShareSession` → emits `AgentInputFooterEvent::OpenShareSessionModal`.
**Event flow**: `OpenShareSessionModal` bubbles through `UseAgentToolbarEvent::OpenShareSessionModal``TerminalView::open_share_session_modal` → opens the sharing dialog.
**Post-share**: `on_session_share_started` unconditionally auto-opens the sharing dialog so the user can copy the link.
**No stop affordance**: The button never changes. Stopping requires the pane header overflow menu.
## Proposed Changes
### 1. Add icon variant
In `crates/warp_core/src/ui/icons.rs`, add one variant:
- `Phone01``"bundled/svg/phone-01.svg"`
The stop state reuses the existing `Icon::StopFilled`.
### 2. Two buttons instead of one
Replace the single `share_session_button` field in `AgentInputFooter` with two fields:
**`start_remote_control_button`**: `Phone01` icon, label "/remote-control". On click dispatches `AgentInputFooterAction::StartRemoteControl`.
**`stop_remote_control_button`**: `StopFilled` icon, label "Stop sharing". On click dispatches `AgentInputFooterAction::StopRemoteControl`.
### 3. Split action and event enums
**`AgentInputFooterAction`** (mod.rs:1893): Replace `ShareSession` with:
- `StartRemoteControl`
- `StopRemoteControl`
**`AgentInputFooterEvent`** (mod.rs:2037): Replace `OpenShareSessionModal` with:
- `StartRemoteControl`
- `StopRemoteControl`
**`UseAgentToolbarEvent`** (use_agent_footer/mod.rs:1019): Replace `OpenShareSessionModal` with:
- `StartRemoteControl`
- `StopRemoteControl`
Each action handler is trivial — it just emits the corresponding event up the chain.
### 4. Swap buttons at render time
In `render_cli_toolbar_item` and `render_toolbar_item` for the `ShareSession` variant, instead of always rendering the start button, check `terminal_model.lock().shared_session_status()`:
- Not sharing → render `start_remote_control_button`
- `is_active_sharer()` or `is_share_pending()` → render `stop_remote_control_button`
The footer already re-renders on `CLIAgentSessionsModel` changes. We need to verify shared session status changes also trigger re-renders; if not, subscribe to the relevant model event.
### 5. Handle `StartRemoteControl` in `TerminalView`
In `handle_use_agent_footer_event` (use_agent_footer/mod.rs:217):
- Call `attempt_to_share_session(SharedSessionScrollbackType::None, Some(FooterChip), SessionSourceType::Terminal, ctx)` with a new `bypass_conversation_guard: bool` parameter set to `true`.
**Bypass the scrollback guard**: Add `bypass_conversation_guard: bool` to `attempt_to_share_session` (view_impl.rs:415). When `true`, skip the guard at lines 436-448. All existing callers pass `false`.
### 6. Auto-copy link on share start
Thread `source: Option<SharedSessionActionSource>` through the share-started flow:
- `Event::StartSharingCurrentSession` gains a `source` field
- Terminal manager forwards it to `on_session_share_started`
In `on_session_share_started` (view_impl.rs:476):
- When source is `FooterChip`: skip `toggle_sharing_dialog`, call `copy_shared_session_link`, show toast "Remote control link copied".
- All other sources: keep existing behavior (auto-open sharing dialog).
### 7. Handle `StopRemoteControl` in `TerminalView`
Call `self.stop_sharing_session(SharedSessionActionSource::FooterChip, ctx)`.
### 8. Update toolbar item metadata
In `toolbar_item.rs`:
- Display label: `"Share Session"``"/remote-control"`
- Icon: `Icon::Share``Icon::Phone01`
### 9. Add `/remote-control` slash command
Add a `REMOTE_CONTROL` static command in `commands.rs` with:
- name: `/remote-control`
- description: "Start remote control for this session"
- icon_path: `"bundled/svg/phone-01.svg"`
- availability: CLI agent sessions only
Register it in the command list. Handle it in the slash command dispatch to emit the same `StartRemoteControl` action as the chip.
### 10. Banner copy
When sharing is started from the remote control entrypoint (`SharedSessionActionSource::FooterChip`), the inline banners show:
- "Remote control active" (instead of "Sharing started")
- "Remote control stopped" (instead of "Sharing ended")
This is threaded via an `is_remote_control: bool` field on `SharedSessionBanners::ActiveShare` and `LastShared`.
## End-to-End Flow
```
Start:
click start_remote_control_button
→ AgentInputFooterAction::StartRemoteControl
→ AgentInputFooterEvent::StartRemoteControl
→ UseAgentToolbarEvent::StartRemoteControl
→ attempt_to_share_session(None, FooterChip, bypass=true)
→ terminal manager establishes connection
→ on_session_share_started(source=FooterChip)
→ skips sharing dialog, copies link, shows toast
→ footer re-renders: swaps to stop_remote_control_button
Stop:
click stop_remote_control_button
→ AgentInputFooterAction::StopRemoteControl
→ AgentInputFooterEvent::StopRemoteControl
→ UseAgentToolbarEvent::StopRemoteControl
→ stop_sharing_session(FooterChip)
→ footer re-renders: swaps back to start_remote_control_button
```
## Risks and Mitigations
- **Scrollback guard bypass**: Deliberately allowing no-scrollback shares for remote control. Guard still applies for all other entry points (share modal, context menu, etc.).
- **State sync**: Reading `shared_session_status()` at render time means the button reflects state changes from any entry point. Must verify shared session status changes trigger footer re-renders.
- **Threading source through share-started flow**: `Event::StartSharingCurrentSession` and the terminal manager callback need to carry the source. Keep it optional so existing callers are unaffected.
## Testing and Validation
- Existing shared session tests pass (protocol unchanged).
- Manual: start CLI agent → click "Remote control" → verify link copied + toast → button shows stop state → click stop → session ends + button reverts.
- Verify starting share from pane menu causes footer to show stop button.
## Follow-ups
- "Text link to my device" stretch goal.
- Rename agent view (non-CLI) share button if desired.