feat: launch Copilot in remote mode with QR code sharing - #197
Draft
catatafishen wants to merge 11 commits into
Draft
feat: launch Copilot in remote mode with QR code sharing#197catatafishen wants to merge 11 commits into
catatafishen wants to merge 11 commits into
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 14, 2026 05:20
1ede350 to
81a8c34
Compare
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 14, 2026 07:56
5bd0d9d to
d60cfa1
Compare
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 14, 2026 19:59
355f187 to
3319d13
Compare
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 15, 2026 09:59
9c11643 to
0f6446d
Compare
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 15, 2026 12:25
0f6446d to
29a1b48
Compare
Adds support for GitHub Copilot CLI remote control mode (`--remote` flag), which lets users share their Copilot session via a QR code or link that opens on GitHub web or mobile. Changes: - CopilotClient: adds `setRemoteMode(boolean)` and `setRemoteUrlListener()` methods; `buildCommand()` inserts `--remote` at position 1 when enabled; `registerHandlers()` override scans stderr for GitHub URLs (ANSI-stripped) and fires the listener once (fire-once semantics) - ActiveAgentManager: adds `setRemoteMode()`, `isRemoteMode()`, and `setRemoteUrlListener()` public API; threads remote mode and listener into `CopilotClient` in `start()` via instanceof pattern match - AcpConnectPanel: adds "Remote control (share session)" checkbox visible only when the Copilot profile is selected; wires checkbox to `agentManager.setRemoteMode()` - ChatToolWindowContent: registers the remote URL listener before `loadModelsAsync()` so it is attached before `acpClient.start()` fires; `showRemoteSessionUrl()` shows the dialog on the EDT - RemoteSessionPanel (new): non-modal `DialogWrapper` showing a 200×200 QR code, the URL label, a Copy link button, and an Open in browser button Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…active When the "Remote control" checkbox is checked and the user clicks Connect, register a URL listener before starting the agent so the GitHub remote session URL emitted to stderr by the Copilot CLI is captured and displayed. Adds StatusBanner.showRemoteSessionUrl(url) — an info banner with "Copy URL" and "Open in Browser" actions, following the same pattern as showDeviceCode. Wires the listener in AcpConnectPanel.doConnect() when remote mode is enabled, so the banner appears as soon as the CLI prints the URL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The previous implementation had two bugs: 1. AcpConnectPanel registered a listener using its own statusBanner, which is hidden once the chat panel is shown after connecting. ChatToolWindowContent then overwrote that listener with a dialog (RemoteSessionPanel), so neither the banner nor the dialog appeared. 2. The Copilot CLI with --remote --acp --stdio emits no URL to stderr (confirmed by testing), so the URL-based approach can never fire. Fix: - Show "Remote mode active" info banner immediately in the onSuccess callback of loadModelsAsync when isRemoteMode is true. This uses the chat panel's statusBanner, which is the correct visible banner. - Keep the URL listener in ChatToolWindowContent pointing at the statusBanner (not a dialog) so it works if the CLI ever provides a URL. - Remove the listener from AcpConnectPanel.doConnect() — it used the wrong banner and was always overwritten anyway. - Delete RemoteSessionPanel.kt — no longer referenced anywhere. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the CLI is launched with --remote and remote sessions are disabled for the repository, the CLI prints an error to stderr (in interactive mode). This change wires up detection and display: - CopilotClient: add REMOTE_NOT_ENABLED_PATTERN and remoteErrorListener field + setRemoteErrorListener(). The stderr handler (already active when remoteMode=true) now also checks for the "not enabled" pattern via extractRemoteNotEnabledError() and fires the listener fire-once. Strips ANSI codes and leading CLI decoration chars (!, ►, ●) before matching. - ActiveAgentManager: add pendingRemoteErrorListener field + setRemoteErrorListener(). configureCopilotClientForStart() now passes it to CopilotClient alongside the URL listener. - ChatToolWindowContent: register the error listener in connectToAgent() when remote mode is active. On fire, shows statusBanner.showError(message) — replaces the "Remote mode active" info banner with a visible error. - Tests: extractRemoteNotEnabledError unit tests (plain, bang prefix, ANSI, unrelated lines), stderr handler tests (fires once, URL does not fire error listener), ActiveAgentManager delegation tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ning The "Remote control (share session)" checkbox is now in the Copilot settings page (Settings → Agents → GitHub Copilot → Configuration) instead of the connect panel. Key changes: - CopilotClientConfigurable: accept Project (previously ignored), add remoteSessionCheckbox and a red warning label explaining that Copilot in ACP mode does not expose the session URL needed to connect remotely, making the feature non-functional until Copilot adds ACP support. apply()/reset()/isModified() wired to ActiveAgentManager.setRemoteMode()/isRemoteMode(). - ActiveAgentManager: setRemoteMode() now persists the value via PropertiesComponent (key copilot.remoteMode) so the setting survives IDE restarts. KEY_REMOTE_MODE added alongside KEY_AUTO_CONNECT. Constructor already loaded from PropertiesComponent. - AcpConnectPanel: checkbox and all its visibility/reset logic was already removed in the previous session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tionFactory - Remove `final` from `CopilotClient` so tests can subclass it - Add `propertiesProvider` Supplier to `ActiveAgentManager` for constructor-free injection of `PropertiesComponent` in tests (avoids IntelliJ platform dependency) - Rewrite `ActiveAgentManagerRemoteModeTest` with `InMemoryPropertiesComponent` stub and `ReflectionFactory.newConstructorForSerialization` allocation - Rewrite `CopilotClientRemoteModeTest.allocateClient()` to use `ReflectionFactory` instead of Mockito inline mock maker, which fails on JetBrains JVM 25 when multiple test classes load the same class before Mockito can instrument it - Add `TestCopilotClient` subclass that overrides `getResumeSessionId()` so buildCommand tests work without platform services - Fix `UsageStatisticsLoaderTest` missing imports (`LinkedHashSet`, `Set`) - Add `mockito-extensions/org.mockito.plugins.MockMaker` resource for compatibility - All 46 remote mode tests now pass Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…atisticsService - Fix UsageStatisticsLoaderTest: invokeCollectTurnStats was reflectively looking for a 7-param collectTurnStats(Path, String, LocalDate, LocalDate, Map, Set, Map) that doesn't exist; updated helper to use the real 5-param signature. Also corrected turnStatsWithoutTimestamp_usesLastSeenTimestampFallback assertions: the test was asserting entry-level agent overrides the session agent, which contradicts usesSessionAgentEvenWhenEntriesHaveDifferentAgentFields; corrected to expect session- level agent and added the date assertion that actually tests the timestamp fallback. - Fix ToolCallStatisticsService.initialize(): throwing IllegalStateException when project.getBasePath() returns null causes initialize_nullBasePath_doesNotThrowAndLeavesQueriesEmpty to fail; changed to log a warning and return early so callers see empty statistics rather than a crash on default/null-path projects. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
catatafishen
force-pushed
the
feat/copilot-remote-mode
branch
from
April 17, 2026 05:03
29a1b48 to
10f461f
Compare
…ticsService Align with master's behavior — null basePath must fail loudly so misconfigured projects surface visibly rather than silently dropping tool call statistics. Updates the companion test to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Owner
Author
|
This doesn't seem to be supported in ACP mode. I'll leave the change here and test it a bit more before deciding if it should be scrapped. |
catatafishen
marked this pull request as draft
May 3, 2026 10:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for GitHub Copilot CLI remote control mode (
--remoteflag), enabling users to share their Copilot session via a QR code or link that can be opened on GitHub web or mobile.See the GitHub changelog for the underlying feature.
Changes
CopilotClientsetRemoteMode(boolean)andsetRemoteUrlListener(Consumer<String>)methodsbuildCommand()inserts--remoteat argv[1] when enabledregisterHandlers()override scans stderr for GitHub URLs (ANSI-stripped, fire-once semantics)ActiveAgentManagersetRemoteMode(),isRemoteMode(), andsetRemoteUrlListener()public APICopilotClientinsidestart()AcpConnectPanelagentManager.setRemoteMode()ChatToolWindowContentloadModelsAsync()so it is attached beforeacpClient.start()firesshowRemoteSessionUrl()opens the dialog on the EDTRemoteSessionPanel(new)DialogWrappershowing:QrCodePanel)Testing
The
--remoteflag is currently not functional when the Copilot CLI runs in ACP (Agent-Computer Protocol) mode. In interactive terminal mode the remote session URL is printed to stderr and can be captured by the plugin. In ACP mode the URL is not emitted, so the QR dialog is never triggered.📋 Draft Support Ticket (not posted yet)
Title: [Feature Request] ACP mode: emit remote session URL for plugin integration
To: GitHub Copilot CLI team
The Copilot CLI
--remoteflag (public preview, Apr 2026) enables session sharing via a QR code/link. This works in interactive terminal mode, where the session URL is printed to stderr and can be captured by IDE plugins.However, when running in ACP mode (
--acpflag), the remote session URL is not emitted. This prevents IDE plugins (such as AgentBridge) from intercepting the URL and showing the QR code dialog to the user — even though the plugin is fully implemented to support this workflow (see this PR).Request: Please emit the remote session URL in a machine-readable way when the CLI is started in ACP mode — for example, as a structured stderr event, a dedicated ACP protocol message, or a JSON line on stdout. This would allow ACP client plugins to surface the QR code and share-link dialog to the user.