Skip to content

Allow importing setup from other editors#325311

Draft
cwebster-99 wants to merge 10 commits into
mainfrom
cwebster-99-import-from-cursor
Draft

Allow importing setup from other editors#325311
cwebster-99 wants to merge 10 commits into
mainfrom
cwebster-99-import-from-cursor

Conversation

@cwebster-99

Copy link
Copy Markdown
Member

This pull request introduces a new "Import from External Editor" feature to the workbench, allowing users to import settings, keybindings, snippets, and extensions from other editors into VS Code. It provides both the underlying service API and the user interface integration, including notification prompts and commands.

External Editor Import Service API:

  • Added a new IExternalEditorImportService interface and related types in externalEditorImport.ts to support detection of external editors, previewing importable items, and performing imports.

Workbench Integration and User Experience:

  • Registered ExternalEditorImportService as a singleton and contributed a new workbench notification (ExternalEditorImportNotificationContribution) that prompts returning users to import customizations from detected editors, avoiding repeated prompts.
  • Implemented the runExternalEditorImport function to handle the import process, show progress notifications, and summarize results for the user.
  • Added two new commands:

cwebster-99 and others added 5 commits July 8, 2026 13:52
Detects an installed Cursor editor and offers one-click import of settings,
keybindings, snippets, and extensions. Surfaces as an onboarding step for
first-time users and as a notification for returning users. Adds a new
externalEditorImport contrib with a detection + import service and a
workbench.action.importFromExternalEditor command.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 10, 2026 14:38

Copilot AI left a comment

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.

Pull request overview

Adds external-editor setup import support, currently targeting Cursor.

Changes:

  • Adds detection, preview, and import APIs for settings, keybindings, snippets, themes, and extensions.
  • Adds commands, progress reporting, notifications, and onboarding integration.
  • Adds service-level tests for detection and core import behavior.
Show a summary per file
File Description
workbench.common.main.ts Loads the new contribution.
onboardingTypes.ts Defines import onboarding metadata.
onboardingVariationA.ts Implements the import onboarding step.
variationA.css Styles the new step.
externalEditorImportService.test.ts Tests detection and imports.
externalEditorImport.ts Defines the service API.
externalEditorImportService.ts Implements detection and importing.
externalEditorImport.contribution.ts Registers commands and notifications.

Review details

  • Files reviewed: 8/8 changed files
  • Comments generated: 16
  • Review effort level: Medium

Comment on lines +59 to +63
readonly settingsImported: number;
readonly keybindingsImported: boolean;
readonly snippetsImported: number;
readonly extensionsInstalled: number;
readonly extensionsFailed: number;
return;
}

const rows = this._getImportRows(source).filter(row => row.available);
Comment on lines +1248 to +1252
// Only stay on the step when there was genuinely nothing to bring over.
if (!importedAnything && result.extensionsFailed === 0) {
this.notificationService.info(localize('onboarding.import.nothing', "Nothing new to import from {0}.", source.label));
return false;
}
Comment on lines +736 to +737
private deepEqual(a: unknown, b: unknown): boolean {
return JSON.stringify(a) === JSON.stringify(b);
Comment on lines +576 to +580
for (const child of sourceStat.children) {
if (child.isDirectory) {
continue;
}
const targetUri = URI.joinPath(targetSnippetsHome, child.name);
parts.push(localize('externalImport.keybindings', "keyboard shortcuts"));
}
if (result.snippetsImported > 0) {
parts.push(localize('externalImport.snippetsCount', "{0} snippet files", result.snippetsImported));
parts.push(localize('externalImport.snippetsCount', "{0} snippet files", result.snippetsImported));
}
if (result.extensionsInstalled > 0) {
parts.push(localize('externalImport.extensionsCount', "{0} extensions", result.extensionsInstalled));
Comment thread src/vs/workbench/contrib/welcomeOnboarding/browser/media/variationA.css Outdated
Comment thread src/vs/workbench/contrib/welcomeOnboarding/browser/media/variationA.css Outdated
Comment on lines +114 to +117
const source = sources[0];
if (!source) {
return;
}
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cwebster-99 and others added 2 commits July 10, 2026 12:57
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>

Copilot AI left a comment

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.

Review details

  • Files reviewed: 12/12 changed files
  • Comments generated: 5
  • Review effort level: Medium

Comment on lines +493 to +497
const preferredHcDark = settings['workbench.preferredHighContrastColorTheme'];
const preferredHcLight = settings['workbench.preferredHighContrastLightColorTheme'];
const preferredDark = settings['workbench.preferredDarkColorTheme'];
const preferredLight = settings['workbench.preferredLightColorTheme'];
if (typeof preferredHcDark === 'string') {
Comment on lines +220 to +223
if (!token?.isCancellationRequested && selection.snippets && source.hasSnippets) {
const result = await this.importSnippets(source);
snippetsImported = result.imported;
snippetsFailed = result.failed;
return { imported: false, failed: true };
}

const newEntries = sourceKeybindings.filter(entry => !existingKeybindings!.some(existing => equals(existing, entry)));
cwebster-99 and others added 2 commits July 10, 2026 13:27
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
On web the path service synthesizes a home directory from the workspace root, so a repo containing e.g. .config/Cursor/User could be misidentified as an installed editor and offered as trusted import data. Skip detection entirely on web.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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.

2 participants