diff --git a/src/ConnectedMode.UnitTests/UI/ConnectedModeUIManagerTests.cs b/src/ConnectedMode.UnitTests/UI/ConnectedModeUIManagerTests.cs
new file mode 100644
index 0000000000..a01030637b
--- /dev/null
+++ b/src/ConnectedMode.UnitTests/UI/ConnectedModeUIManagerTests.cs
@@ -0,0 +1,41 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.ConnectedMode.UI;
+using SonarLint.VisualStudio.TestInfrastructure;
+
+namespace SonarLint.VisualStudio.ConnectedMode.UnitTests.UI
+{
+    [TestClass]
+    public class ConnectedModeUIManagerTests
+    {
+        [TestMethod]
+        public void MefCtor_CheckIsExported()
+        {
+            MefTestHelpers.CheckTypeCanBeImported<ConnectedModeUIManager, IConnectedModeUIManager>(
+                MefTestHelpers.CreateExport<IConnectedModeServices>(),
+                MefTestHelpers.CreateExport<IConnectedModeBindingServices>());
+        }
+
+        [TestMethod]
+        public void MefCtor_CheckIsNonShared()
+            => MefTestHelpers.CheckIsNonSharedMefComponent<ConnectedModeUIManager>();
+    }
+}
diff --git a/src/ConnectedMode/UI/ConnectedModeUIManager.cs b/src/ConnectedMode/UI/ConnectedModeUIManager.cs
new file mode 100644
index 0000000000..ffbac0d468
--- /dev/null
+++ b/src/ConnectedMode/UI/ConnectedModeUIManager.cs
@@ -0,0 +1,53 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using System.ComponentModel.Composition;
+using System.Diagnostics.CodeAnalysis;
+using System.Windows;
+using SonarLint.VisualStudio.ConnectedMode.UI.ManageBinding;
+
+namespace SonarLint.VisualStudio.ConnectedMode.UI;
+
+public interface IConnectedModeUIManager
+{
+    void ShowManageBindingDialog(bool useSharedBindingOnInitialization = false);
+}
+
+[Export(typeof(IConnectedModeUIManager))]
+[PartCreationPolicy(CreationPolicy.NonShared)]
+internal sealed class ConnectedModeUIManager : IConnectedModeUIManager
+{
+    private readonly IConnectedModeServices connectedModeServices;
+    private readonly IConnectedModeBindingServices connectedModeBindingServices;
+
+    [ImportingConstructor]
+    public ConnectedModeUIManager(IConnectedModeServices connectedModeServices, IConnectedModeBindingServices connectedModeBindingServices)
+    {
+        this.connectedModeServices = connectedModeServices;
+        this.connectedModeBindingServices = connectedModeBindingServices;
+    }
+
+    [ExcludeFromCodeCoverage] // UI, not really unit-testable
+    public void ShowManageBindingDialog(bool useSharedBindingOnInitialization = false)
+    {
+        var manageBindingDialog = new ManageBindingDialog(connectedModeServices, connectedModeBindingServices, useSharedBindingOnInitialization);
+        manageBindingDialog.ShowDialog(Application.Current.MainWindow);
+    }
+}
diff --git a/src/EmbeddedSonarAnalyzer.props b/src/EmbeddedSonarAnalyzer.props
index ac945cbb14..440356b8c3 100644
--- a/src/EmbeddedSonarAnalyzer.props
+++ b/src/EmbeddedSonarAnalyzer.props
@@ -9,6 +9,6 @@
     <EmbeddedSonarJSAnalyzerVersion>10.14.0.26080</EmbeddedSonarJSAnalyzerVersion>
     <EmbeddedSonarSecretsJarVersion>2.15.0.3845</EmbeddedSonarSecretsJarVersion>
     <!-- SLOOP: Binaries for SonarLint Out Of Process -->
-    <EmbeddedSloopVersion>10.6.0.79033</EmbeddedSloopVersion>
+    <EmbeddedSloopVersion>10.7.1.79146</EmbeddedSloopVersion>
   </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/src/Integration.UnitTests/Binding/BindingSuggestionHandlerTests.cs b/src/Integration.UnitTests/Binding/BindingSuggestionHandlerTests.cs
index ad5dca437a..0fe1167a30 100644
--- a/src/Integration.UnitTests/Binding/BindingSuggestionHandlerTests.cs
+++ b/src/Integration.UnitTests/Binding/BindingSuggestionHandlerTests.cs
@@ -19,11 +19,11 @@
  */
 
 using SonarLint.VisualStudio.ConnectedMode.Binding.Suggestion;
+using SonarLint.VisualStudio.ConnectedMode.UI;
 using SonarLint.VisualStudio.Core.Notifications;
 using SonarLint.VisualStudio.Core;
 using SonarLint.VisualStudio.TestInfrastructure;
 using SonarLint.VisualStudio.Core.Binding;
-using SonarLint.VisualStudio.Integration.TeamExplorer;
 using SonarLint.VisualStudio.Integration.Binding;
 
 namespace SonarLint.VisualStudio.Integration.UnitTests.Binding;
@@ -31,6 +31,24 @@ namespace SonarLint.VisualStudio.Integration.UnitTests.Binding;
 [TestClass]
 public class BindingSuggestionHandlerTests
 {
+    private BindingSuggestionHandler testSubject;
+    private INotificationService notificationService;
+    private IActiveSolutionBoundTracker activeSolutionBoundTracker;
+    private IIDEWindowService ideWindowService;
+    private IConnectedModeUIManager connectedModeManager;
+    private IBrowserService browserService;
+
+    [TestInitialize]
+    public void TestInitialize()
+    {
+        notificationService = Substitute.For<INotificationService>();
+        activeSolutionBoundTracker = Substitute.For<IActiveSolutionBoundTracker>();
+        ideWindowService = Substitute.For<IIDEWindowService>();
+        connectedModeManager = Substitute.For<IConnectedModeUIManager>();
+        browserService = Substitute.For<IBrowserService>();
+        testSubject = new BindingSuggestionHandler(notificationService, activeSolutionBoundTracker, ideWindowService, connectedModeManager, browserService);
+    }
+
     [TestMethod]
     public void MefCtor_CheckExports()
     {
@@ -38,7 +56,7 @@ public void MefCtor_CheckExports()
             MefTestHelpers.CreateExport<INotificationService>(),
             MefTestHelpers.CreateExport<IActiveSolutionBoundTracker>(),
             MefTestHelpers.CreateExport<IIDEWindowService>(),
-            MefTestHelpers.CreateExport<ITeamExplorerController>(),
+            MefTestHelpers.CreateExport<IConnectedModeUIManager>(),
             MefTestHelpers.CreateExport<IBrowserService>());
     }
 
@@ -47,9 +65,8 @@ public void MefCtor_CheckExports()
     [DataRow(SonarLintMode.Connected)]
     public void Notify_BringsWindowToFront(SonarLintMode sonarLintMode)
     {
-        var ideWindowService = Substitute.For<IIDEWindowService>();
+        MockCurrentConfiguration(sonarLintMode);
 
-        var testSubject = CreateTestSubject(sonarLintMode: sonarLintMode, ideWindowService: ideWindowService);
         testSubject.Notify();
 
         ideWindowService.Received().BringToFront();
@@ -58,9 +75,8 @@ public void Notify_BringsWindowToFront(SonarLintMode sonarLintMode)
     [TestMethod]
     public void Notify_WithStandaloneProject_PromptsToConnect()
     {
-        var notificationService = Substitute.For<INotificationService>();
+        MockCurrentConfiguration(SonarLintMode.Standalone);
 
-        var testSubject = CreateTestSubject(sonarLintMode: SonarLintMode.Standalone, notificationService: notificationService);
         testSubject.Notify();
 
         notificationService.Received().ShowNotification(Arg.Is<INotification>(
@@ -73,9 +89,8 @@ public void Notify_WithStandaloneProject_PromptsToConnect()
     [TestMethod]
     public void Notify_WithBoundProject_ShowsConflictMessage()
     {
-        var notificationService = Substitute.For<INotificationService>();
+        MockCurrentConfiguration(SonarLintMode.Connected);
 
-        var testSubject = CreateTestSubject(sonarLintMode: SonarLintMode.Connected, notificationService: notificationService);
         testSubject.Notify();
 
         notificationService.Received().ShowNotification(Arg.Is<INotification>(
@@ -86,30 +101,28 @@ public void Notify_WithBoundProject_ShowsConflictMessage()
     }
 
     [TestMethod]
-    public void Notify_ConnectAction_OpensSonarQubePage()
+    public void Notify_ConnectAction_ShowsManageBindingDialog()
     {
-        var notificationService = Substitute.For<INotificationService>();
-        var teamExplorerController = Substitute.For<ITeamExplorerController>();
+        MockCurrentConfiguration(SonarLintMode.Standalone);
 
-        var testSubject = CreateTestSubject(sonarLintMode: SonarLintMode.Standalone, notificationService: notificationService, teamExplorerController: teamExplorerController);
         testSubject.Notify();
+
         var notification = (Notification)notificationService.ReceivedCalls().Single().GetArguments().Single();
         var connectAction = notification.Actions.First(x => x.CommandText.Equals(BindingStrings.BindingSuggestionConnect));
 
-        teamExplorerController.DidNotReceive().ShowSonarQubePage();
+        connectedModeManager.DidNotReceive().ShowManageBindingDialog();
         connectAction.Action(notification);
 
-        teamExplorerController.Received().ShowSonarQubePage();
+        connectedModeManager.Received().ShowManageBindingDialog();
     }
 
     [TestMethod]
     public void Notify_LearnMoreAction_OpensDocumentationInBrowser()
     {
-        var notificationService = Substitute.For<INotificationService>();
-        var browserService = Substitute.For<IBrowserService>();
+        MockCurrentConfiguration(SonarLintMode.Standalone);
 
-        var testSubject = CreateTestSubject(sonarLintMode: SonarLintMode.Standalone, notificationService: notificationService, browserService: browserService);
         testSubject.Notify();
+
         var notification = (Notification)notificationService.ReceivedCalls().Single().GetArguments().Single();
         var connectAction = notification.Actions.First(x => x.CommandText.Equals(BindingStrings.BindingSuggestionLearnMore));
 
@@ -119,20 +132,10 @@ public void Notify_LearnMoreAction_OpensDocumentationInBrowser()
         browserService.Received().Navigate(DocumentationLinks.OpenInIdeBindingSetup);
     }
 
-    private BindingSuggestionHandler CreateTestSubject(SonarLintMode sonarLintMode,
-        INotificationService notificationService = null,
-        IIDEWindowService ideWindowService = null,
-        ITeamExplorerController teamExplorerController = null,
-        IBrowserService browserService = null)
+    private void MockCurrentConfiguration(SonarLintMode sonarLintMode)
     {
-        notificationService ??= Substitute.For<INotificationService>();
-        var activeSolutionBoundTracker = Substitute.For<IActiveSolutionBoundTracker>();
-        ideWindowService ??= Substitute.For<IIDEWindowService>();
-        teamExplorerController ??= Substitute.For<ITeamExplorerController>();
-        browserService ??= Substitute.For<IBrowserService>();
-
-        activeSolutionBoundTracker.CurrentConfiguration.Returns(new BindingConfiguration(new BoundServerProject("solution", "server project", new ServerConnection.SonarCloud("org")), sonarLintMode, "a-directory"));
-
-        return new BindingSuggestionHandler(notificationService, activeSolutionBoundTracker, ideWindowService, teamExplorerController, browserService);
+        activeSolutionBoundTracker.CurrentConfiguration.Returns(new BindingConfiguration(
+            new BoundServerProject("solution", "server project", new ServerConnection.SonarCloud("org")), sonarLintMode,
+            "a-directory"));
     }
 }
diff --git a/src/Integration.UnitTests/MefServices/SharedBindingSuggestionServiceTests.cs b/src/Integration.UnitTests/MefServices/SharedBindingSuggestionServiceTests.cs
index e418188a31..b0500738ad 100644
--- a/src/Integration.UnitTests/MefServices/SharedBindingSuggestionServiceTests.cs
+++ b/src/Integration.UnitTests/MefServices/SharedBindingSuggestionServiceTests.cs
@@ -37,6 +37,7 @@ public class SharedBindingSuggestionServiceTests
     private IConnectedModeServices connectedModeServices;
     private IConnectedModeBindingServices connectedModeBindingServices;
     private IActiveSolutionTracker activeSolutionTracker;
+    private IConnectedModeUIManager connectedModeManager;
 
     [TestInitialize]
     public void TestInitialize()
@@ -45,8 +46,9 @@ public void TestInitialize()
         connectedModeServices = Substitute.For<IConnectedModeServices>();
         connectedModeBindingServices = Substitute.For<IConnectedModeBindingServices>();
         activeSolutionTracker = Substitute.For<IActiveSolutionTracker>();
+        connectedModeManager = Substitute.For<IConnectedModeUIManager>();
 
-        testSubject = new SharedBindingSuggestionService(suggestSharedBindingGoldBar, connectedModeServices, connectedModeBindingServices, activeSolutionTracker);
+        testSubject = new SharedBindingSuggestionService(suggestSharedBindingGoldBar, connectedModeServices, connectedModeBindingServices, connectedModeManager, activeSolutionTracker);
     }
 
     [TestMethod]
@@ -56,6 +58,7 @@ public void MefCtor_CheckExports()
             MefTestHelpers.CreateExport<ISuggestSharedBindingGoldBar>(),
             MefTestHelpers.CreateExport<IConnectedModeServices>(),
             MefTestHelpers.CreateExport<IConnectedModeBindingServices>(),
+            MefTestHelpers.CreateExport<IConnectedModeUIManager>(),
             MefTestHelpers.CreateExport<IActiveSolutionTracker>());
     }
 
@@ -127,6 +130,24 @@ public void Dispose_UnsubscribesFromActiveSolutionChanged()
         activeSolutionTracker.Received(1).ActiveSolutionChanged -= Arg.Any<EventHandler<ActiveSolutionChangedEventArgs>>();
     }
 
+    [TestMethod]
+    public void ActiveSolutionChanged_SolutionIsOpened_ShowsGoldBarAndShowManageBindingDialog()
+    {
+        MockSharedBindingConfigExists();
+        MockSolutionMode(SonarLintMode.Standalone);
+        Action showAction = null;
+        suggestSharedBindingGoldBar.When(x => x.Show(ServerType.SonarQube, Arg.Any<Action>())).Do(callInfo =>
+        {
+            showAction = callInfo.Arg<Action>();
+        });
+
+        RaiseActiveSolutionChanged(true);
+        showAction();
+
+        showAction.Should().NotBeNull();
+        connectedModeManager.Received(1).ShowManageBindingDialog(true);
+    }
+
     private void RaiseActiveSolutionChanged(bool isSolutionOpened)
     {
         activeSolutionTracker.ActiveSolutionChanged += Raise.EventWith(new ActiveSolutionChangedEventArgs(isSolutionOpened));
diff --git a/src/Integration.UnitTests/SLCore/SLCoreConstantsProviderTests.cs b/src/Integration.UnitTests/SLCore/SLCoreConstantsProviderTests.cs
index b830489f3f..75150fc50d 100644
--- a/src/Integration.UnitTests/SLCore/SLCoreConstantsProviderTests.cs
+++ b/src/Integration.UnitTests/SLCore/SLCoreConstantsProviderTests.cs
@@ -66,7 +66,7 @@ public void ClientConstants_ShouldBeExpected()
     public void FeatureFlags_ShouldBeExpected()
     {
         var testSubject = CreateTestSubject();
-        var expectedFeatureFlags = new FeatureFlagsDto(true, true, true, true, false, false, true, true);
+        var expectedFeatureFlags = new FeatureFlagsDto(true, true, true, true, false, false, true, true, true);
         var actual = testSubject.FeatureFlags;
 
         actual.Should().BeEquivalentTo(expectedFeatureFlags);
diff --git a/src/Integration.Vsix.UnitTests/Commands/PackageCommandManagerTests.cs b/src/Integration.Vsix.UnitTests/Commands/PackageCommandManagerTests.cs
index 2d760d38e7..f9b7a00f49 100644
--- a/src/Integration.Vsix.UnitTests/Commands/PackageCommandManagerTests.cs
+++ b/src/Integration.Vsix.UnitTests/Commands/PackageCommandManagerTests.cs
@@ -56,10 +56,10 @@ public void PackageCommandManager_Initialize()
                 Mock.Of<IProjectPropertyManager>(),
                 Mock.Of<IOutputWindowService>(),
                 Mock.Of<IShowInBrowserService>(),
-                Mock.Of<IBrowserService>(),
                 Mock.Of<PackageCommandManager.ShowOptionsPage>(),
                 Mock.Of<IConnectedModeServices>(),
-Mock.Of<IConnectedModeBindingServices>());
+Mock.Of<IConnectedModeBindingServices>(),
+                Mock.Of<IConnectedModeUIManager>());
 
             // Assert
             menuService.Commands.Should().HaveCountGreaterOrEqualTo(allCommands.Count, "Unexpected number of commands");
diff --git a/src/Integration.Vsix/Commands/ConnectedModeMenu/ManageConnectionsCommand.cs b/src/Integration.Vsix/Commands/ConnectedModeMenu/ManageConnectionsCommand.cs
index 00e50d7136..fa6210d877 100644
--- a/src/Integration.Vsix/Commands/ConnectedModeMenu/ManageConnectionsCommand.cs
+++ b/src/Integration.Vsix/Commands/ConnectedModeMenu/ManageConnectionsCommand.cs
@@ -18,28 +18,24 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Windows;
 using SonarLint.VisualStudio.ConnectedMode.UI;
-using SonarLint.VisualStudio.ConnectedMode.UI.ManageBinding;
 
 namespace SonarLint.VisualStudio.Integration.Vsix.Commands.ConnectedModeMenu
 {
     [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
     internal class ManageConnectionsCommand : VsCommandBase
     {
-        private readonly IConnectedModeServices connectedModeServices;
-        private readonly IConnectedModeBindingServices connectedModeBindingServices;
+        private readonly IConnectedModeUIManager connectedModeUiManager;
         internal const int Id = 0x102;
 
-        public ManageConnectionsCommand(IConnectedModeServices connectedModeServices, IConnectedModeBindingServices connectedModeBindingServices)
+        public ManageConnectionsCommand(IConnectedModeUIManager connectedModeUiManager)
         {
-            this.connectedModeServices = connectedModeServices;
-            this.connectedModeBindingServices = connectedModeBindingServices;
+            this.connectedModeUiManager = connectedModeUiManager;
         }
 
         protected override void InvokeInternal()
         {
-            new ManageBindingDialog(connectedModeServices, connectedModeBindingServices).ShowDialog(Application.Current.MainWindow);
+            connectedModeUiManager.ShowManageBindingDialog();
         }
     }
 }
diff --git a/src/Integration.Vsix/Commands/PackageCommandManager.cs b/src/Integration.Vsix/Commands/PackageCommandManager.cs
index f64268c804..ac92f70ecf 100644
--- a/src/Integration.Vsix/Commands/PackageCommandManager.cs
+++ b/src/Integration.Vsix/Commands/PackageCommandManager.cs
@@ -46,10 +46,10 @@ public void Initialize(
             IProjectPropertyManager projectPropertyManager,
             IOutputWindowService outputWindowService,
             IShowInBrowserService showInBrowserService,
-            IBrowserService browserService,
             ShowOptionsPage showOptionsPage,
             IConnectedModeServices connectedModeServices,
-            IConnectedModeBindingServices connectedModeBindingServices)
+            IConnectedModeBindingServices connectedModeBindingServices,
+            IConnectedModeUIManager connectedModeManager)
         {
             RegisterCommand((int)PackageCommandId.ProjectExcludePropertyToggle, new ProjectExcludePropertyToggleCommand(projectPropertyManager));
             RegisterCommand((int)PackageCommandId.ProjectTestPropertyAuto, new ProjectTestPropertySetCommand(projectPropertyManager, null));
@@ -65,11 +65,11 @@ public void Initialize(
             // Help menu buttons
             RegisterCommand(CommonGuids.HelpMenuCommandSet, ShowLogsCommand.Id, new ShowLogsCommand(outputWindowService));
             RegisterCommand(CommonGuids.HelpMenuCommandSet, ViewDocumentationCommand.Id, new ViewDocumentationCommand(showInBrowserService));
-            RegisterCommand(CommonGuids.HelpMenuCommandSet, AboutCommand.Id, new AboutCommand(browserService));
+            RegisterCommand(CommonGuids.HelpMenuCommandSet, AboutCommand.Id, new AboutCommand(connectedModeServices.BrowserService));
             RegisterCommand(CommonGuids.HelpMenuCommandSet, ShowCommunityPageCommand.Id, new ShowCommunityPageCommand(showInBrowserService));
 
             // Connected mode buttons
-            RegisterCommand(CommonGuids.ConnectedModeMenuCommandSet, ManageConnectionsCommand.Id, new ManageConnectionsCommand(connectedModeServices, connectedModeBindingServices));
+            RegisterCommand(CommonGuids.ConnectedModeMenuCommandSet, ManageConnectionsCommand.Id, new ManageConnectionsCommand(connectedModeManager));
             RegisterCommand(CommonGuids.ConnectedModeMenuCommandSet, SaveSharedConnectionCommand.Id, new SaveSharedConnectionCommand(connectedModeServices.ConfigurationProvider, connectedModeBindingServices.SharedBindingConfigProvider));
         }
 
diff --git a/src/Integration.Vsix/SonarLintIntegrationPackage.cs b/src/Integration.Vsix/SonarLintIntegrationPackage.cs
index e90c261661..83c6f039a3 100644
--- a/src/Integration.Vsix/SonarLintIntegrationPackage.cs
+++ b/src/Integration.Vsix/SonarLintIntegrationPackage.cs
@@ -96,10 +96,10 @@ private async Task InitOnUIThreadAsync()
                     serviceProvider.GetMefService<IProjectPropertyManager>(),
                     serviceProvider.GetMefService<IOutputWindowService>(),
                     serviceProvider.GetMefService<IShowInBrowserService>(),
-                    serviceProvider.GetMefService<IBrowserService>(),
                     ShowOptionPage,
                     serviceProvider.GetMefService<IConnectedModeServices>(),
-                    serviceProvider.GetMefService<IConnectedModeBindingServices>());
+                    serviceProvider.GetMefService<IConnectedModeBindingServices>(),
+                    serviceProvider.GetMefService<IConnectedModeUIManager>());
 
                 this.roslynSettingsFileSynchronizer = await this.GetMefServiceAsync<IRoslynSettingsFileSynchronizer>();
                 roslynSettingsFileSynchronizer.UpdateFileStorageAsync().Forget(); // don't wait for it to finish
diff --git a/src/Integration/Binding/BindingSuggestionHandler.cs b/src/Integration/Binding/BindingSuggestionHandler.cs
index 3be011760a..004eba1e98 100644
--- a/src/Integration/Binding/BindingSuggestionHandler.cs
+++ b/src/Integration/Binding/BindingSuggestionHandler.cs
@@ -20,10 +20,10 @@
 
 using System.ComponentModel.Composition;
 using SonarLint.VisualStudio.ConnectedMode.Binding.Suggestion;
+using SonarLint.VisualStudio.ConnectedMode.UI;
 using SonarLint.VisualStudio.Core.Binding;
 using SonarLint.VisualStudio.Core.Notifications;
 using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Integration.TeamExplorer;
 
 namespace SonarLint.VisualStudio.Integration.Binding
 {
@@ -34,20 +34,20 @@ internal class BindingSuggestionHandler : IBindingSuggestionHandler
         private readonly INotificationService notificationService;
         private readonly IActiveSolutionBoundTracker activeSolutionBoundTracker;
         private readonly IIDEWindowService ideWindowService;
-        private readonly ITeamExplorerController teamExplorerController;
+        private readonly IConnectedModeUIManager connectedModeUiManager;
         private readonly IBrowserService browserService;
 
         [ImportingConstructor]
         public BindingSuggestionHandler(INotificationService notificationService, 
             IActiveSolutionBoundTracker activeSolutionBoundTracker,
             IIDEWindowService ideWindowService,
-            ITeamExplorerController teamExplorerController,
+            IConnectedModeUIManager connectedModeUiManager,
             IBrowserService browserService)
         {
             this.notificationService = notificationService;
             this.activeSolutionBoundTracker = activeSolutionBoundTracker;
             this.ideWindowService = ideWindowService;
-            this.teamExplorerController = teamExplorerController;
+            this.connectedModeUiManager = connectedModeUiManager;
             this.browserService = browserService;
         }
 
@@ -62,7 +62,7 @@ public void Notify()
                 : BindingStrings.BindingSuggetsionBindingConflict;
 
             var connectAction = new NotificationAction(BindingStrings.BindingSuggestionConnect,
-                _ => teamExplorerController.ShowSonarQubePage(),
+                _ => connectedModeUiManager.ShowManageBindingDialog(),
                 true);
             var learnMoreAction = new NotificationAction(BindingStrings.BindingSuggestionLearnMore,
                 _ => browserService.Navigate(DocumentationLinks.OpenInIdeBindingSetup),
diff --git a/src/Integration/MefServices/SharedBindingSuggestionService.cs b/src/Integration/MefServices/SharedBindingSuggestionService.cs
index 89cbf795ed..49b0b53fa8 100644
--- a/src/Integration/MefServices/SharedBindingSuggestionService.cs
+++ b/src/Integration/MefServices/SharedBindingSuggestionService.cs
@@ -41,6 +41,7 @@ internal sealed class SharedBindingSuggestionService : ISharedBindingSuggestionS
         private readonly ISuggestSharedBindingGoldBar suggestSharedBindingGoldBar;
         private readonly IConnectedModeServices connectedModeServices;
         private readonly IConnectedModeBindingServices connectedModeBindingServices;
+        private readonly IConnectedModeUIManager connectedModeUiManager;
         private readonly IActiveSolutionTracker activeSolutionTracker;
 
         [ImportingConstructor]
@@ -48,11 +49,13 @@ public SharedBindingSuggestionService(
             ISuggestSharedBindingGoldBar suggestSharedBindingGoldBar,
             IConnectedModeServices connectedModeServices,
             IConnectedModeBindingServices connectedModeBindingServices,
+            IConnectedModeUIManager connectedModeUiManager,
             IActiveSolutionTracker activeSolutionTracker)
         {
             this.suggestSharedBindingGoldBar = suggestSharedBindingGoldBar;
             this.connectedModeServices = connectedModeServices;
             this.connectedModeBindingServices = connectedModeBindingServices;
+            this.connectedModeUiManager = connectedModeUiManager;
             this.activeSolutionTracker = activeSolutionTracker;
 
             this.activeSolutionTracker.ActiveSolutionChanged += OnActiveSolutionChanged;
@@ -76,8 +79,7 @@ public void Dispose()
 
         private void ShowManageBindingDialog()
         {
-            var manageBindingDialog = new ManageBindingDialog(connectedModeServices, connectedModeBindingServices, useSharedBindingOnInitialization:true);
-            manageBindingDialog.ShowDialog(Application.Current.MainWindow);
+            connectedModeUiManager.ShowManageBindingDialog(useSharedBindingOnInitialization:true);
         }
 
         private void OnActiveSolutionChanged(object sender, ActiveSolutionChangedEventArgs e)
diff --git a/src/Integration/SLCore/SLCoreConstantsProvider.cs b/src/Integration/SLCore/SLCoreConstantsProvider.cs
index 9b367e29b8..a72338a417 100644
--- a/src/Integration/SLCore/SLCoreConstantsProvider.cs
+++ b/src/Integration/SLCore/SLCoreConstantsProvider.cs
@@ -42,7 +42,7 @@ public SLCoreConstantsProvider(IVsInfoProvider vsInfoProvider)
 
         public ClientConstantsDto ClientConstants => new(vsInfoProvider.Name, $"SonarLint Visual Studio/{VersionHelper.SonarLintVersion}", Process.GetCurrentProcess().Id);
 
-        public FeatureFlagsDto FeatureFlags => new(true, true, true, true, false, false, true, true);
+        public FeatureFlagsDto FeatureFlags => new(true, true, true, true, false, false, true, true, true);
 
         public TelemetryClientConstantAttributesDto TelemetryConstants => new("visualstudio", "SonarLint Visual Studio", VersionHelper.SonarLintVersion, VisualStudioHelpers.VisualStudioVersion, new Dictionary<string, object>
         {
diff --git a/src/IssueViz.UnitTests/Editor/IssueSpanCalculatorTests.cs b/src/IssueViz.UnitTests/Editor/IssueSpanCalculatorTests.cs
index 8a0b324721..a193695461 100644
--- a/src/IssueViz.UnitTests/Editor/IssueSpanCalculatorTests.cs
+++ b/src/IssueViz.UnitTests/Editor/IssueSpanCalculatorTests.cs
@@ -18,12 +18,10 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Microsoft.VisualStudio.Text;
 using Moq;
-using SonarLint.VisualStudio.TestInfrastructure;
 using SonarLint.VisualStudio.IssueVisualization.Editor;
+using SonarLint.VisualStudio.TestInfrastructure;
 using SonarQube.Client;
 
 namespace SonarLint.VisualStudio.IssueVisualization.UnitTests.Editor
@@ -34,6 +32,8 @@ public class IssueSpanCalculatorTests
         private Mock<IChecksumCalculator> checksumCalculatorMock;
 
         private IssueSpanCalculator testSubject;
+        private const int SnapshotLength = 10000;
+        private const int SnapshotLineCount = 10000;
 
         [TestInitialize]
         public void TestInitialize()
@@ -331,6 +331,83 @@ public void CalculateSpan_TextRangeNull_ReturnsNull()
             checksumCalculatorMock.VerifyNoOtherCalls();
         }
 
+        [TestMethod]
+        public void CalculateSpan_ForStartAndEndLines_GetsPositionOfCorrectLines()
+        {
+            var startLine = CreateLineMock(lineNumber: 66, startPos: 1, endPos: 2);
+            var endLine = CreateLineMock(lineNumber: 224, startPos: 13, endPos: 23);
+            var textSnapshotMock = MockTextSnapshotForLines(startLine, endLine);
+
+            testSubject.CalculateSpan(textSnapshotMock.Object, startLine.LineNumber, endLine.LineNumber);
+
+            textSnapshotMock.Verify(mock => mock.GetLineFromLineNumber(startLine.LineNumber - 1), Times.Once);
+            textSnapshotMock.Verify(mock => mock.GetLineFromLineNumber(endLine.LineNumber - 1), Times.Once);
+        }
+
+        [TestMethod]
+        public void CalculateSpan_ForStartAndEndLines_ReturnsSnapshotSpanWithCorrectStartAndEnd()
+        {
+            var startLine = CreateLineMock(lineNumber:66, startPos:1, endPos:2);
+            var endLine = CreateLineMock(lineNumber:224, startPos:13, endPos:23);
+            var textSnapshotMock = MockTextSnapshotForLines(startLine, endLine);
+
+            var snapshotSpan = testSubject.CalculateSpan(textSnapshotMock.Object, startLine.LineNumber, endLine.LineNumber);
+            
+            snapshotSpan.HasValue.Should().BeTrue();
+            snapshotSpan.Value.Start.Position.Should().Be(startLine.Start.Position);
+            snapshotSpan.Value.End.Position.Should().Be(endLine.End.Position);
+        }
+        
+        [TestMethod]
+        [DataRow(0, 1)]
+        [DataRow(1, 0)]
+        [DataRow(SnapshotLineCount + 1, 1)]
+        [DataRow(1, SnapshotLineCount + 1)]
+        [DataRow(4, 1)]
+        public void CalculateSpan_ForInvalidStartAndEndLines_ReturnsNull(int startLineNumber, int endLineNumber)
+        {
+            var startLine = CreateLineMock(lineNumber:startLineNumber, startPos:1, endPos:2);
+            var endLine = CreateLineMock(lineNumber:endLineNumber, startPos:13, endPos:23);
+            var textSnapshotMock = MockTextSnapshotForLines(startLine, endLine);
+
+            var result = testSubject.CalculateSpan(textSnapshotMock.Object, startLine.LineNumber, endLine.LineNumber);
+
+            result.Should().BeNull();
+        }
+
+        [TestMethod]
+        public void IsSameHash_SnapshotIsSameAsText_ReturnsTrue()
+        {
+            var textSnapshotMock = new SnapshotSpan(CreateSnapshotMock().Object, 1, 1);
+            checksumCalculatorMock.Setup(mock => mock.Calculate(It.IsAny<string>())).Returns("sameHash");
+
+            var result = testSubject.IsSameHash(textSnapshotMock, "test");
+
+            result.Should().BeTrue();
+        }
+
+        [TestMethod]
+        public void IsSameHash_SnapshotIsSameAsText_ReturnsFalse()
+        {
+            var textSnapshotMock = new SnapshotSpan(CreateSnapshotMock().Object, 1, 1);
+            checksumCalculatorMock.SetupSequence(mock => mock.Calculate(It.IsAny<string>())).Returns("hash1").Returns("hash2");
+
+            var result = testSubject.IsSameHash(textSnapshotMock, "test");
+
+            result.Should().BeFalse();
+        }
+
+        private static Mock<ITextSnapshot> MockTextSnapshotForLines(ITextSnapshotLine startLine, ITextSnapshotLine endLine)
+        {
+            var textSnapshot = new Mock<ITextSnapshot>();
+            textSnapshot.SetupGet(x => x.LineCount).Returns(SnapshotLineCount);
+            textSnapshot.SetupGet(x => x.Length).Returns(SnapshotLength);
+            textSnapshot.Setup(x => x.GetLineFromLineNumber(startLine.LineNumber - 1)).Returns(startLine);
+            textSnapshot.Setup(x => x.GetLineFromLineNumber(endLine.LineNumber - 1)).Returns(endLine);
+
+            return textSnapshot;
+        }
+
         private class VSLineDescription
         {
             public int ZeroBasedLineNumber { get; set; }
@@ -339,7 +416,7 @@ private class VSLineDescription
             public string Text { get; set; }
         }
 
-        private static Mock<ITextSnapshot> CreateSnapshotMock(int bufferLineCount = 1000, int snapShotLength = 10000, params VSLineDescription[] lines)
+        private static Mock<ITextSnapshot> CreateSnapshotMock(int bufferLineCount = 1000, int snapShotLength = SnapshotLength, params VSLineDescription[] lines)
         {
             var textSnapshotMock = new Mock<ITextSnapshot>();
 
@@ -378,5 +455,19 @@ private static ITextSnapshotLine CreateLineMock(ITextSnapshot textSnapshot, VSLi
 
             return startLineMock.Object;
         }
+
+        private static ITextSnapshotLine CreateLineMock(int lineNumber, int startPos, int endPos)
+        {
+            var startLineMock = new Mock<ITextSnapshotLine>();
+            var textSnapshot = new Mock<ITextSnapshot>();
+
+            textSnapshot.SetupGet(x => x.Length).Returns(() => endPos +1);
+
+            startLineMock.SetupGet(x => x.LineNumber).Returns(() => lineNumber);
+            startLineMock.SetupGet(x => x.Start).Returns(() => new SnapshotPoint(textSnapshot.Object, startPos));
+            startLineMock.SetupGet(x => x.End).Returns(() => new SnapshotPoint(textSnapshot.Object, endPos));
+
+            return startLineMock.Object;
+        }
     }
 }
diff --git a/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionHandlerTests.cs b/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionHandlerTests.cs
new file mode 100644
index 0000000000..ec14ff22c1
--- /dev/null
+++ b/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionHandlerTests.cs
@@ -0,0 +1,378 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using System.IO;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using NSubstitute.ExceptionExtensions;
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.IssueVisualization.Editor;
+using SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+using SonarLint.VisualStudio.IssueVisualization.OpenInIde;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+using SonarLint.VisualStudio.TestInfrastructure;
+using FileEditDto = SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models.FileEditDto;
+
+namespace SonarLint.VisualStudio.IssueVisualization.UnitTests.FixSuggestion;
+
+[TestClass]
+public class FixSuggestionHandlerTests
+{
+    private const string ConfigurationScopeRoot = @"C:\";
+    private readonly ShowFixSuggestionParams suggestionWithOneChange = CreateFixSuggestionParams(changes: CreateChangesDto(1, 1, "var a=1;"));
+    private FixSuggestionHandler testSubject;
+    private IThreadHandling threadHandling;
+    private ILogger logger;
+    private IDocumentNavigator documentNavigator;
+    private IIssueSpanCalculator issueSpanCalculator;
+    private IOpenInIdeConfigScopeValidator openInIdeConfigScopeValidator;
+    private IIDEWindowService ideWindowService;
+    private IFixSuggestionNotification fixSuggestionNotification;
+
+    [TestInitialize]
+    public void TestInitialize()
+    {
+        threadHandling = new NoOpThreadHandler();
+        logger = Substitute.For<ILogger>();
+        documentNavigator = Substitute.For<IDocumentNavigator>();
+        issueSpanCalculator = Substitute.For<IIssueSpanCalculator>();
+        openInIdeConfigScopeValidator = Substitute.For<IOpenInIdeConfigScopeValidator>();
+        ideWindowService = Substitute.For<IIDEWindowService>();
+        fixSuggestionNotification = Substitute.For<IFixSuggestionNotification>();
+
+        testSubject = new FixSuggestionHandler(
+            threadHandling,
+            logger,
+            documentNavigator,
+            issueSpanCalculator,
+            openInIdeConfigScopeValidator,
+            ideWindowService,
+            fixSuggestionNotification);
+        MockConfigScopeRoot();
+        issueSpanCalculator.IsSameHash(Arg.Any<SnapshotSpan>(), Arg.Any<string>()).Returns(true);
+    }
+
+    [TestMethod]
+    public void MefCtor_CheckIsSingleton()
+    {
+        MefTestHelpers.CheckIsSingletonMefComponent<FixSuggestionHandler>();
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_RunsOnUIThread()
+    {
+        var threadHandlingMock = Substitute.For<IThreadHandling>();
+        var fixSuggestionHandler = new FixSuggestionHandler(
+            threadHandlingMock,
+            logger,
+            documentNavigator,
+            issueSpanCalculator,
+            openInIdeConfigScopeValidator,
+            ideWindowService,
+            fixSuggestionNotification);
+
+        fixSuggestionHandler.ApplyFixSuggestion(suggestionWithOneChange);
+
+        threadHandlingMock.ReceivedWithAnyArgs().RunOnUIThread(default);
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_OneChange_AppliesChange()
+    {
+        var suggestedChange = suggestionWithOneChange.fixSuggestion.fileEdit.changes[0];
+        MockCalculateSpan(suggestedChange);
+        var textView = MockOpenFile();
+        var edit = MockTextEdit(textView);
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        Received.InOrder(() =>
+        {
+            logger.WriteLine(FixSuggestionResources.ProcessingRequest, suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId);
+            ideWindowService.BringToFront();
+            fixSuggestionNotification.ClearAsync();
+            documentNavigator.Open(@"C:\myFile.cs");
+            textView.TextBuffer.CreateEdit();
+            issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), suggestedChange.beforeLineRange.startLine, suggestedChange.beforeLineRange.endLine);
+            edit.Replace(Arg.Any<Span>(), suggestedChange.after);
+            edit.Apply();
+            logger.WriteLine(FixSuggestionResources.DoneProcessingRequest, suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId);
+        });
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_TwoChanges_AppliesChangeOnce()
+    {
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>()).Returns(new SnapshotSpan());
+        var suggestionWithTwoChanges = CreateFixSuggestionParams(changes: [CreateChangesDto(1, 1, "var a=1;"), CreateChangesDto(2, 2, "var b=0;")]);
+        var textView = MockOpenFile();
+        var edit = MockTextEdit(textView);
+
+        testSubject.ApplyFixSuggestion(suggestionWithTwoChanges);
+
+        issueSpanCalculator.Received(2).CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>());
+        edit.Received(2).Replace(Arg.Any<Span>(), Arg.Any<string>());
+        edit.Received(1).Apply();
+    }
+
+    /// <summary>
+    /// The changes are applied from bottom to top to avoid changing the line numbers
+    /// of the changes that are below the current change.
+    ///
+    /// This is important when the change is more lines than the original line range.
+    /// </summary>
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenMoreThanOneFixes_ApplyThemFromBottomToTop()
+    {
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>()).Returns(new SnapshotSpan());
+        MockOpenFile();
+        ChangesDto[] changes = [CreateChangesDto(1, 1, "var a=1;"), CreateChangesDto(3, 3, "var b=0;")];
+        var suggestionParams = CreateFixSuggestionParams(changes: changes);
+
+        testSubject.ApplyFixSuggestion(suggestionParams);
+
+        Received.InOrder(() =>
+        {
+            issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), 3, 3);
+            issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), 1, 1);
+        });
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenApplyingChange_BringWindowToFront()
+    {
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        ideWindowService.Received().BringToFront();
+    }
+
+
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenApplyingChange_BringFocusToFirstChangedLines()
+    {
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>()).Returns(new SnapshotSpan());
+        ChangesDto[] changes = [CreateChangesDto(1, 1, "var a=1;"), CreateChangesDto(3, 3, "var a=1;")];
+        var suggestionParams = CreateFixSuggestionParams(changes: changes);
+        var firstSuggestedChange = suggestionParams.fixSuggestion.fileEdit.changes[0];
+        var firstAffectedSnapshot = MockCalculateSpan(firstSuggestedChange);
+        var textView = MockOpenFile();
+        MockConfigScopeRoot();
+
+        testSubject.ApplyFixSuggestion(suggestionParams);
+
+        textView.ViewScroller.ReceivedWithAnyArgs(1).EnsureSpanVisible(Arg.Any<SnapshotSpan>(), default);
+        textView.ViewScroller.Received(1).EnsureSpanVisible(firstAffectedSnapshot, EnsureSpanVisibleOptions.AlwaysCenter);
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_Throws_Logs()
+    {
+        var exceptionMsg = "error";
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>()).Throws(new Exception(exceptionMsg));
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        Received.InOrder(() =>
+        {
+            logger.WriteLine(FixSuggestionResources.ProcessingRequest, suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId);
+            logger.WriteLine(FixSuggestionResources.ProcessingRequestFailed, suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId, exceptionMsg);
+        });
+        logger.DidNotReceive().WriteLine(FixSuggestionResources.DoneProcessingRequest, suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId);
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenConfigRootScopeNotFound_ShouldLogFailureAndShowNotification()
+    {
+        var reason = "Scope not found";
+        MockFailedConfigScopeRoot(reason);
+        var suggestionParams = CreateFixSuggestionParams("SpecificConfigScopeId");
+
+        testSubject.ApplyFixSuggestion(suggestionParams);
+
+        logger.Received().WriteLine(FixSuggestionResources.GetConfigScopeRootPathFailed, "SpecificConfigScopeId", "Scope not found");
+        fixSuggestionNotification.Received(1).InvalidRequestAsync(reason);
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenLineNumbersDoNotMatch_ShouldLogFailure()
+    {
+        FailWhenApplyingEdit("Line numbers do not match");
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        logger.Received().WriteLine(FixSuggestionResources.ProcessingRequestFailed,
+            suggestionWithOneChange.configurationScopeId, suggestionWithOneChange.fixSuggestion.suggestionId,
+            "Line numbers do not match");
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_WhenApplyingChangeAndExceptionIsThrown_ShouldCancelEdit()
+    {
+        var edit = FailWhenApplyingEdit();
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        edit.DidNotReceiveWithAnyArgs().Replace(default, default);
+        edit.Received().Cancel();
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_FileCanNotBeOpened_LogsAndShowsNotification()
+    {
+        var errorMessage = "error";
+        documentNavigator.Open(Arg.Any<string>()).Throws(new Exception(errorMessage));
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        logger.Received().WriteLine(Resources.ERR_OpenDocumentException, GetAbsolutePathOfFile(suggestionWithOneChange), errorMessage);
+        fixSuggestionNotification.Received(1).UnableToOpenFileAsync(Arg.Is<string>(msg => msg == GetAbsolutePathOfFile(suggestionWithOneChange)));
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_FileContentIsNull_LogsAndShowsNotification()
+    {
+        documentNavigator.Open(Arg.Any<string>()).Returns((ITextView)null);
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        logger.DidNotReceive().WriteLine(Resources.ERR_OpenDocumentException, Arg.Any<string>(), Arg.Any<string>());
+        fixSuggestionNotification.Received(1).UnableToOpenFileAsync(Arg.Is<string>(msg => msg == GetAbsolutePathOfFile(suggestionWithOneChange)));
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_ClearsPreviousNotification()
+    {
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        fixSuggestionNotification.Received(1).ClearAsync();
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_OneChange_IssueCanNotBeLocated_ShowsNotificationAndDoesNotApplySuggestion()
+    {
+        var edit = MockTextEdit();
+        issueSpanCalculator.IsSameHash(Arg.Any<SnapshotSpan>(), Arg.Any<string>()).Returns(false);
+
+        testSubject.ApplyFixSuggestion(suggestionWithOneChange);
+
+        VerifyFixSuggestionNotApplied(edit);
+    }
+
+    [TestMethod]
+    public void ApplyFixSuggestion_TwoChanges_OneIssueCanNotBeLocated_ShowsNotificationAndDoesNotApplySuggestion()
+    {
+        var suggestionParams = CreateFixSuggestionParams(changes: [CreateChangesDto(1, 1, "var a=1;"), CreateChangesDto(2, 2, "var b=0;")]);
+        var edit = MockTextEdit();
+        issueSpanCalculator.IsSameHash(Arg.Any<SnapshotSpan>(), Arg.Any<string>()).Returns(
+            _ => true,
+            _ => false);
+
+        testSubject.ApplyFixSuggestion(suggestionParams);
+
+        VerifyFixSuggestionNotApplied(edit);
+    }
+
+    private void MockConfigScopeRoot()
+    {
+        openInIdeConfigScopeValidator.TryGetConfigurationScopeRoot(Arg.Any<string>(), out Arg.Any<string>(), out Arg.Any<string>()).Returns(
+            x =>
+            {
+                x[1] = ConfigurationScopeRoot;
+                return true;
+            });
+    }
+
+    private void MockFailedConfigScopeRoot(string failureReason)
+    {
+        openInIdeConfigScopeValidator.TryGetConfigurationScopeRoot(Arg.Any<string>(), out Arg.Any<string>(), out Arg.Any<string>()).Returns(
+            x =>
+            {
+                x[2] = failureReason;
+                return false;
+            });
+    }
+
+    private ITextView MockOpenFile()
+    {
+        var textView = Substitute.For<ITextView>();
+        documentNavigator.Open(Arg.Any<string>()).Returns(textView);
+        return textView;
+    }
+
+    private SnapshotSpan MockCalculateSpan(ChangesDto suggestedChange)
+    {
+        return MockCalculateSpan(suggestedChange.before, suggestedChange.beforeLineRange.startLine, suggestedChange.beforeLineRange.endLine);
+    }
+
+    private SnapshotSpan MockCalculateSpan(string text, int startLine, int endLine)
+    {
+        var affectedSnapshot = new SnapshotSpan();
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), startLine, endLine).Returns(affectedSnapshot);
+        issueSpanCalculator.IsSameHash(affectedSnapshot, text).Returns(true);
+        return affectedSnapshot;
+    }
+
+    private ITextEdit FailWhenApplyingEdit(string reason = "")
+    {
+        var edit = Substitute.For<ITextEdit>();
+        var textView = MockOpenFile();
+        textView.TextBuffer.CreateEdit().Returns(edit);
+        issueSpanCalculator.CalculateSpan(Arg.Any<ITextSnapshot>(), Arg.Any<int>(), Arg.Any<int>())
+            .Throws(new Exception(reason));
+        return edit;
+    }
+
+    private static ShowFixSuggestionParams CreateFixSuggestionParams(string scopeId = "scopeId",
+        string suggestionKey = "suggestionKey",
+        string idePath = @"myFile.cs",
+        params ChangesDto[] changes)
+    {
+        var fixSuggestion = new FixSuggestionDto(suggestionKey, "refactor", new FileEditDto(idePath, changes.ToList()));
+        var suggestionParams = new ShowFixSuggestionParams(scopeId, "key", fixSuggestion);
+        return suggestionParams;
+    }
+
+    private static ChangesDto CreateChangesDto(int startLine, int endLine, string before)
+    {
+        return new ChangesDto(new LineRangeDto(startLine, endLine), before, "");
+    }
+
+    private static string GetAbsolutePathOfFile(ShowFixSuggestionParams suggestionParams) =>
+        Path.Combine(ConfigurationScopeRoot, suggestionParams.fixSuggestion.fileEdit.idePath);
+
+    private ITextEdit MockTextEdit(ITextView textView = null)
+    {
+        var edit = Substitute.For<ITextEdit>();
+        textView ??= MockOpenFile();
+        textView.TextBuffer.CreateEdit().Returns(edit);
+        return edit;
+    }
+
+    private void VerifyFixSuggestionNotApplied(ITextEdit edit)
+    {
+        Received.InOrder(() =>
+        {
+            fixSuggestionNotification.UnableToLocateIssueAsync(Arg.Is<string>(msg => msg == GetAbsolutePathOfFile(suggestionWithOneChange)));
+            edit.Cancel();
+        });
+        edit.DidNotReceive().Apply();
+    }
+}
diff --git a/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionNotificationTests.cs b/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionNotificationTests.cs
new file mode 100644
index 0000000000..0bd1f84c36
--- /dev/null
+++ b/src/IssueViz.UnitTests/FixSuggestion/FixSuggestionNotificationTests.cs
@@ -0,0 +1,299 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.Core.InfoBar;
+using SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+using SonarLint.VisualStudio.TestInfrastructure;
+
+namespace SonarLint.VisualStudio.IssueVisualization.UnitTests.FixSuggestion;
+
+[TestClass]
+public class FixSuggestionNotificationTests
+{
+    private FixSuggestionNotification testSubject;
+    private IInfoBarManager infoBarManager;
+    private IOutputWindowService outputWindowService;
+    private IBrowserService browserService;
+    private IThreadHandling threadHandler;
+
+    [TestInitialize]
+    public void TestInitialize()
+    {
+        infoBarManager = Substitute.For<IInfoBarManager>();
+        outputWindowService = Substitute.For<IOutputWindowService>();
+        threadHandler = new NoOpThreadHandler();
+        browserService = Substitute.For<IBrowserService>();
+
+        testSubject = new FixSuggestionNotification(infoBarManager, outputWindowService, browserService, threadHandler);
+    }
+
+    [TestMethod]
+    public void MefCtor_CheckIsExported()
+    {
+        MefTestHelpers.CheckTypeCanBeImported<FixSuggestionNotification, IFixSuggestionNotification>(
+            MefTestHelpers.CreateExport<IInfoBarManager>(),
+            MefTestHelpers.CreateExport<IOutputWindowService>(),
+            MefTestHelpers.CreateExport<IBrowserService>(),
+            MefTestHelpers.CreateExport<IThreadHandling>());
+    }
+
+    [TestMethod]
+    public async Task Clear_NoPreviousInfoBar_NoException()
+    {
+        await testSubject.ClearAsync();
+
+        infoBarManager.ReceivedCalls().Should().BeEmpty();
+    }
+
+    [TestMethod]
+    public async Task Clear_HasPreviousInfoBar_InfoBarCleared()
+    {
+        var infoBar = MockInfoBar();
+        await MockPreviousInfoBar(infoBar);
+        
+        await testSubject.ClearAsync();
+
+        CheckInfoBarWithEventsRemoved(infoBar);
+    }
+
+    [TestMethod]
+    public async Task Show_NoPreviousInfoBar_InfoBarIsShown()
+    {
+        var infoBarText = "info bar text";
+        var infoBar = MockInfoBar();
+        MockAttachInfoBarToMainWindow(infoBar);
+
+        await testSubject.ShowAsync(infoBarText);
+
+        CheckInfoBarWithEventsAdded(infoBar, infoBarText);
+    }
+
+    [TestMethod]
+    public async Task Show_NoCustomText_InfoBarWithDefaultTextIsShown()
+    {
+        var infoBar = MockInfoBar(); 
+        MockAttachInfoBarToMainWindow(infoBar);
+
+        await testSubject.ShowAsync(null);
+
+        CheckInfoBarWithEventsAdded(infoBar, FixSuggestionResources.InfoBarDefaultMessage);
+    }
+
+    [TestMethod]
+    public async Task Show_HasPreviousInfoBar_InfoBarReplaced()
+    {
+        var firstInfoBar = MockInfoBar();
+        var secondInfoBar = MockInfoBar();
+        infoBarManager
+            .AttachInfoBarToMainWindow(Arg.Any<string>(), SonarLintImageMoniker.OfficialSonarLintMoniker, Arg.Any<string[]>())
+            .Returns(x => firstInfoBar, 
+                x=> secondInfoBar);
+
+        var text1 = "text1";
+        await testSubject.ShowAsync(text1); // show first bar
+        
+        CheckInfoBarWithEventsAdded(firstInfoBar, text1);
+        infoBarManager.ClearReceivedCalls();
+
+        var text2 = "text2";
+        await testSubject.ShowAsync(text2); // show second bar
+
+        CheckInfoBarWithEventsRemoved(firstInfoBar);
+        CheckInfoBarWithEventsAdded(secondInfoBar, text2);
+    }
+
+    [TestMethod]
+    public async Task Dispose_HasPreviousInfoBar_InfoBarRemoved()
+    {
+        var infoBar = MockInfoBar();
+        await MockPreviousInfoBar(infoBar);
+
+        testSubject.Dispose();
+
+        CheckInfoBarWithEventsRemoved(infoBar);
+    }
+
+    [TestMethod]
+    public void Dispose_NoPreviousInfoBar_NoException()
+    {
+        Action act = () => testSubject.Dispose();
+
+        act.Should().NotThrow();
+    }
+
+    [TestMethod]
+    public async Task InfoBarIsManuallyClosed_InfoBarDetachedFromToolWindow()
+    {
+        var infoBar = MockInfoBar();
+        await MockPreviousInfoBar(infoBar);
+
+        infoBar.Closed += Raise.EventWith(EventArgs.Empty);
+
+        CheckInfoBarWithEventsRemoved(infoBar);
+    }
+
+    [TestMethod]
+    public async Task InfoBarShowLogsButtonClicked_OutputWindowIsShown()
+    {
+        var infoBar = MockInfoBar();
+        await MockPreviousInfoBar(infoBar);
+
+        infoBar.ButtonClick += Raise.EventWith(new InfoBarButtonClickedEventArgs(FixSuggestionResources.InfoBarButtonShowLogs));
+
+        CheckInfoBarNotRemoved(infoBar);
+        outputWindowService.Received(1).Show();
+    }
+
+    [TestMethod]
+    public async Task InfoBarMoreInfoButtonClicked_DocumentationOpenInBrowser()
+    {
+        var infoBar = MockInfoBar();
+        await MockPreviousInfoBar(infoBar);
+
+        infoBar.ButtonClick += Raise.EventWith(new InfoBarButtonClickedEventArgs(FixSuggestionResources.InfoBarButtonMoreInfo));
+
+        CheckInfoBarNotRemoved(infoBar);
+        browserService.Received(1).Navigate(DocumentationLinks.OpenInIdeIssueLocation);
+    }
+
+    [TestMethod]
+    public async Task ShowAsync_VerifySwitchesToUiThreadIsCalled()
+    {
+        MockAttachInfoBarToMainWindow(Substitute.For<IInfoBar>());
+        var threadHandling = Substitute.For<IThreadHandling>();
+        threadHandling
+            .When(x => x.RunOnUIThreadAsync(Arg.Any<Action>()))
+            .Do(callInfo =>
+            {
+                infoBarManager.DidNotReceive().AttachInfoBarToMainWindow(Arg.Any<string>(), SonarLintImageMoniker.OfficialSonarLintMoniker, Arg.Any<string[]>());
+                callInfo.Arg<Action>().Invoke();
+                infoBarManager.Received(1).AttachInfoBarToMainWindow(Arg.Any<string>(), SonarLintImageMoniker.OfficialSonarLintMoniker, Arg.Any<string[]>());
+            });
+        var fixSuggestionNotification = new FixSuggestionNotification(infoBarManager,
+            outputWindowService,
+            browserService,
+            threadHandling);
+
+        await fixSuggestionNotification.ShowAsync( "some text");
+        await threadHandling.Received(1).RunOnUIThreadAsync(Arg.Any<Action>());
+    }
+
+    [TestMethod]
+    public async Task ClearAsync_VerifySwitchesToUiThreadIsCalled()
+    {
+        MockAttachInfoBarToMainWindow(Substitute.For<IInfoBar>());
+        var threadHandling = Substitute.For<IThreadHandling>();
+        var fixSuggestionNotification = new FixSuggestionNotification(infoBarManager,
+            outputWindowService,
+            browserService,
+            threadHandling);
+
+        await fixSuggestionNotification.ClearAsync();
+
+        await threadHandling.Received(1).RunOnUIThreadAsync(Arg.Any<Action>());
+    }
+
+    [TestMethod]
+    public async Task UnableToOpenFileAsync_CallsShowAsyncWithCorrectMessage()
+    {
+        var infoBar = MockInfoBar();
+        MockAttachInfoBarToMainWindow(infoBar);
+        var myPath = "c://myFile.cs";
+        
+        await testSubject.UnableToOpenFileAsync(myPath);
+
+        CheckInfoBarWithEventsAdded(infoBar, string.Format(FixSuggestionResources.InfoBarUnableToOpenFile, myPath));
+    }
+
+    [TestMethod]
+    public async Task InvalidRequestAsync_CallsShowAsyncWithCorrectMessage()
+    {
+        var infoBar = MockInfoBar();
+        MockAttachInfoBarToMainWindow(infoBar);
+        var reason = "wrong config scope";
+
+        await testSubject.InvalidRequestAsync(reason);
+
+        CheckInfoBarWithEventsAdded(infoBar, string.Format(FixSuggestionResources.InfoBarInvalidRequest, reason));
+    }
+
+    [TestMethod]
+    public async Task UnableToLocateIssueAsync_CallsShowAsyncWithCorrectMessage()
+    {
+        var infoBar = MockInfoBar();
+        MockAttachInfoBarToMainWindow(infoBar);
+        var myPath = "c://myFile.cs";
+
+        await testSubject.UnableToLocateIssueAsync(myPath);
+
+        CheckInfoBarWithEventsAdded(infoBar, string.Format(FixSuggestionResources.InfoBarUnableToLocateFixSuggestion, myPath));
+    }
+
+    private async Task MockPreviousInfoBar(IInfoBar infoBar = null)
+    {
+        infoBar ??= MockInfoBar();
+        MockAttachInfoBarToMainWindow(infoBar);
+        var someText = "some text";
+
+        await testSubject.ShowAsync(someText);
+
+        CheckInfoBarWithEventsAdded(infoBar, someText); 
+        outputWindowService.ReceivedCalls().Should().BeEmpty();
+    }
+
+    private void MockAttachInfoBarToMainWindow(IInfoBar infoBar)
+    {
+        infoBarManager
+            .AttachInfoBarToMainWindow(Arg.Any<string>(), SonarLintImageMoniker.OfficialSonarLintMoniker, Arg.Any<string[]>())
+            .Returns(infoBar);
+    }
+
+    private static IInfoBar MockInfoBar()
+    {
+        return Substitute.For<IInfoBar>();
+    }
+
+    private void CheckInfoBarWithEventsRemoved(IInfoBar infoBar)
+    {
+        infoBarManager.Received(1).DetachInfoBar(infoBar);
+
+        infoBar.Received(1).Closed -= Arg.Any<EventHandler>();
+        infoBar.Received(1).ButtonClick -= Arg.Any<EventHandler<InfoBarButtonClickedEventArgs>>();
+    }
+
+    private void CheckInfoBarNotRemoved(IInfoBar infoBar)
+    {
+        infoBarManager.DidNotReceive().DetachInfoBar(infoBar);
+    }
+
+    private void CheckInfoBarWithEventsAdded(IInfoBar infoBar, string text)
+    {
+        text ??= FixSuggestionResources.InfoBarDefaultMessage;
+        var buttonTexts = new[]{FixSuggestionResources.InfoBarButtonMoreInfo, FixSuggestionResources.InfoBarButtonShowLogs};
+        infoBarManager.Received(1).AttachInfoBarToMainWindow(
+                text,
+                SonarLintImageMoniker.OfficialSonarLintMoniker,
+                buttonTexts);
+
+        infoBar.Received(1).Closed += Arg.Any<EventHandler>();
+        infoBar.Received(1).ButtonClick += Arg.Any<EventHandler<InfoBarButtonClickedEventArgs>>();
+    }
+}
diff --git a/src/IssueViz/Editor/IIssueSpanCalculator.cs b/src/IssueViz/Editor/IIssueSpanCalculator.cs
index cf1a6d4e67..f813d1e98e 100644
--- a/src/IssueViz/Editor/IIssueSpanCalculator.cs
+++ b/src/IssueViz/Editor/IIssueSpanCalculator.cs
@@ -18,7 +18,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System;
 using System.ComponentModel.Composition;
 using Microsoft.VisualStudio.Text;
 using SonarLint.VisualStudio.Core.Analysis;
@@ -34,6 +33,17 @@ public interface IIssueSpanCalculator
         /// Returns null if no textRange is passed
         /// </summary>
         SnapshotSpan? CalculateSpan(ITextRange range, ITextSnapshot currentSnapshot);
+
+        /// <summary>
+        /// Returns the text span that is in the range of the provided lines
+        /// Returns null if the provided lines can not be found the snapshot
+        /// </summary>
+        SnapshotSpan? CalculateSpan(ITextSnapshot snapshot, int startLine, int endLine);
+
+        /// <summary>
+        /// Returns true only if the provided <param name="text"/> has the same hash as the text contained in the <paramref name="snapshotSpan"/>
+        /// </summary>
+        bool IsSameHash(SnapshotSpan snapshotSpan, string text);
     }
 
     [Export(typeof(IIssueSpanCalculator))]
@@ -105,6 +115,26 @@ internal IssueSpanCalculator(IChecksumCalculator checksumCalculator)
             return snapshotSpan;
         }
 
+        public SnapshotSpan? CalculateSpan(ITextSnapshot snapshot, int startLine, int endLine)
+        {
+            if (startLine < 1 || endLine < 1 || startLine > snapshot.LineCount || endLine > snapshot.LineCount || startLine > endLine)
+            {
+                return null;
+            }
+            var startPosition = snapshot.GetLineFromLineNumber(startLine - 1).Start.Position;
+            var endPosition = snapshot.GetLineFromLineNumber(endLine - 1).End.Position;
+            var span = Span.FromBounds(startPosition, endPosition);
+            return new SnapshotSpan(snapshot, span);
+        }
+
+        public bool IsSameHash(SnapshotSpan snapshotSpan, string text)
+        {
+            var snapsShotHash = checksumCalculator.Calculate(snapshotSpan.GetText());
+            var textHash = checksumCalculator.Calculate(text);
+
+            return snapsShotHash == textHash;
+        }
+
         private static bool RangeHasHash(ITextRange range)
             => !string.IsNullOrEmpty(range.LineHash);
 
diff --git a/src/IssueViz/FixSuggestion/FixSuggestionHandler.cs b/src/IssueViz/FixSuggestion/FixSuggestionHandler.cs
new file mode 100644
index 0000000000..5da49aefc5
--- /dev/null
+++ b/src/IssueViz/FixSuggestion/FixSuggestionHandler.cs
@@ -0,0 +1,188 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using System.ComponentModel.Composition;
+using System.IO;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Threading;
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.Infrastructure.VS;
+using SonarLint.VisualStudio.IssueVisualization.Editor;
+using SonarLint.VisualStudio.IssueVisualization.OpenInIde;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+namespace SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+
+[Export(typeof(IFixSuggestionHandler))]
+[PartCreationPolicy(CreationPolicy.Shared)]
+public class FixSuggestionHandler : IFixSuggestionHandler
+{
+    private readonly IOpenInIdeConfigScopeValidator openInIdeConfigScopeValidator;
+    private readonly IIDEWindowService ideWindowService;
+    private readonly IFixSuggestionNotification fixSuggestionNotification;
+    private readonly IThreadHandling threadHandling;
+    private readonly ILogger logger;
+    private readonly IDocumentNavigator documentNavigator;
+    private readonly IIssueSpanCalculator issueSpanCalculator;
+
+    [ImportingConstructor]
+    internal FixSuggestionHandler(
+        ILogger logger,
+        IDocumentNavigator documentNavigator,
+        IIssueSpanCalculator issueSpanCalculator,
+        IOpenInIdeConfigScopeValidator openInIdeConfigScopeValidator,
+        IIDEWindowService ideWindowService,
+        IFixSuggestionNotification fixSuggestionNotification) : 
+        this(
+            ThreadHandling.Instance,
+            logger,
+            documentNavigator,
+            issueSpanCalculator,
+            openInIdeConfigScopeValidator,
+            ideWindowService, 
+            fixSuggestionNotification)
+    {
+    }
+
+    internal FixSuggestionHandler(
+        IThreadHandling threadHandling,
+        ILogger logger,
+        IDocumentNavigator documentNavigator,
+        IIssueSpanCalculator issueSpanCalculator,
+        IOpenInIdeConfigScopeValidator openInIdeConfigScopeValidator,
+        IIDEWindowService ideWindowService, 
+        IFixSuggestionNotification fixSuggestionNotification)
+    {
+        this.threadHandling = threadHandling;
+        this.logger = logger;
+        this.documentNavigator = documentNavigator;
+        this.issueSpanCalculator = issueSpanCalculator;
+        this.openInIdeConfigScopeValidator = openInIdeConfigScopeValidator;
+        this.ideWindowService = ideWindowService;
+        this.fixSuggestionNotification = fixSuggestionNotification;
+    }
+
+    public void ApplyFixSuggestion(ShowFixSuggestionParams parameters)
+    {
+        try
+        {
+            logger.WriteLine(FixSuggestionResources.ProcessingRequest, parameters.configurationScopeId, parameters.fixSuggestion.suggestionId);
+            ideWindowService.BringToFront();
+            fixSuggestionNotification.ClearAsync().Forget();
+
+            if (!ValidateConfiguration(parameters.configurationScopeId, out var configurationScopeRoot, out var failureReason))
+            {
+                logger.WriteLine(FixSuggestionResources.GetConfigScopeRootPathFailed, parameters.configurationScopeId, failureReason);
+                fixSuggestionNotification.InvalidRequestAsync(failureReason).Forget();
+                return;
+            }
+
+            threadHandling.RunOnUIThread(() => ApplyAndShowAppliedFixSuggestions(parameters, configurationScopeRoot));
+            logger.WriteLine(FixSuggestionResources.DoneProcessingRequest, parameters.configurationScopeId, parameters.fixSuggestion.suggestionId);
+        }
+        catch (Exception exception) when (!ErrorHandler.IsCriticalException(exception))
+        {
+            logger.WriteLine(FixSuggestionResources.ProcessingRequestFailed, parameters.configurationScopeId, parameters.fixSuggestion.suggestionId, exception.Message);
+        }
+    }
+
+    private bool ValidateConfiguration(string configurationScopeId, out string configurationScopeRoot, out string failureReason)
+    {
+        return openInIdeConfigScopeValidator.TryGetConfigurationScopeRoot(configurationScopeId, out configurationScopeRoot, out failureReason);
+    }
+
+    private void ApplyAndShowAppliedFixSuggestions(ShowFixSuggestionParams parameters, string configurationScopeRoot)
+    {
+        var absoluteFilePath = Path.Combine(configurationScopeRoot, parameters.fixSuggestion.fileEdit.idePath);
+        var textView = GetFileContent(absoluteFilePath);
+        if (!ValidateFileExists(textView, absoluteFilePath))
+        {
+            return;
+        }
+        ApplySuggestedChanges(textView, parameters.fixSuggestion.fileEdit.changes, absoluteFilePath);
+    }
+
+    private void ApplySuggestedChanges(ITextView textView, List<ChangesDto> changes, string filePath)
+    {
+        var textEdit = textView.TextBuffer.CreateEdit();
+        try
+        {
+            for (var i = changes.Count - 1; i >= 0; i--)
+            {
+                var changeDto = changes[i];
+
+                var spanToUpdate = issueSpanCalculator.CalculateSpan(textView.TextSnapshot, changeDto.beforeLineRange.startLine, changeDto.beforeLineRange.endLine);
+                if (!ValidateIssueStillExists(spanToUpdate, changeDto, filePath))
+                {
+                    return;
+                }
+
+                if (i == 0)
+                {
+                    textView.Caret.MoveTo(spanToUpdate.Value.Start);
+                    textView.ViewScroller.EnsureSpanVisible(spanToUpdate.Value, EnsureSpanVisibleOptions.AlwaysCenter);
+                }
+                textEdit.Replace(spanToUpdate.Value, changeDto.after);
+            }
+            textEdit.Apply();
+        }
+        finally
+        {
+            textEdit.Cancel();
+        }
+    }
+
+    private bool ValidateIssueStillExists(SnapshotSpan? spanToUpdate, ChangesDto changeDto, string filePath)
+    {
+        if (spanToUpdate.HasValue && issueSpanCalculator.IsSameHash(spanToUpdate.Value, changeDto.before))
+        {
+            return true;
+        }
+
+        fixSuggestionNotification.UnableToLocateIssueAsync(filePath).Forget();
+        return false;
+    }
+
+    private bool ValidateFileExists(ITextView fileContent, string absoluteFilePath)
+    {
+        if (fileContent != null)
+        {
+            return true;
+        }
+
+        fixSuggestionNotification.UnableToOpenFileAsync(absoluteFilePath).Forget();
+        return false;
+    }
+
+    private ITextView GetFileContent(string filePath)
+    {
+        try
+        {
+            return documentNavigator.Open(filePath);
+        }
+        catch (Exception ex) when (!ErrorHandler.IsCriticalException(ex))
+        {
+            logger.WriteLine(Resources.ERR_OpenDocumentException, filePath, ex.Message);
+            return null;
+        }
+    }
+}
diff --git a/src/IssueViz/FixSuggestion/FixSuggestionResources.Designer.cs b/src/IssueViz/FixSuggestion/FixSuggestionResources.Designer.cs
new file mode 100644
index 0000000000..c6bab4bf50
--- /dev/null
+++ b/src/IssueViz/FixSuggestion/FixSuggestionResources.Designer.cs
@@ -0,0 +1,153 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SonarLint.VisualStudio.IssueVisualization.FixSuggestion {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class FixSuggestionResources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal FixSuggestionResources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SonarLint.VisualStudio.IssueVisualization.FixSuggestion.FixSuggestionResources", typeof(FixSuggestionResources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to [Fix Suggestion in IDE] Done processing request. Configuration scope: {0}, SuggestionId: {1}.
+        /// </summary>
+        internal static string DoneProcessingRequest {
+            get {
+                return ResourceManager.GetString("DoneProcessingRequest", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to [Fix Suggestion in IDE] Could not determine configuration scope root path for scope [{0}] due to: {1}.
+        /// </summary>
+        internal static string GetConfigScopeRootPathFailed {
+            get {
+                return ResourceManager.GetString("GetConfigScopeRootPathFailed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Learn more.
+        /// </summary>
+        internal static string InfoBarButtonMoreInfo {
+            get {
+                return ResourceManager.GetString("InfoBarButtonMoreInfo", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Show logs.
+        /// </summary>
+        internal static string InfoBarButtonShowLogs {
+            get {
+                return ResourceManager.GetString("InfoBarButtonShowLogs", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Could not handle Open in IDE request. See the Logs for more information..
+        /// </summary>
+        internal static string InfoBarDefaultMessage {
+            get {
+                return ResourceManager.GetString("InfoBarDefaultMessage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Unable to process Fix Suggestion in IDE request. Reason: {0}.
+        /// </summary>
+        internal static string InfoBarInvalidRequest {
+            get {
+                return ResourceManager.GetString("InfoBarInvalidRequest", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Fix Suggestion in IDE. Could not locate the issue in the file. Please ensure the file ({0}) has not been modified..
+        /// </summary>
+        internal static string InfoBarUnableToLocateFixSuggestion {
+            get {
+                return ResourceManager.GetString("InfoBarUnableToLocateFixSuggestion", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Fix Suggestion in IDE. Could not open File: {0}. Please ensure that you&apos;re on the correct branch and the file has not been deleted locally..
+        /// </summary>
+        internal static string InfoBarUnableToOpenFile {
+            get {
+                return ResourceManager.GetString("InfoBarUnableToOpenFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to [Fix Suggestion in IDE] Processing request. Configuration scope: {0}, SuggestionId: {1}.
+        /// </summary>
+        internal static string ProcessingRequest {
+            get {
+                return ResourceManager.GetString("ProcessingRequest", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to [Fix Suggestion in IDE] Fail to process request for configuration scope: {0}, SuggestionId: {1} due to {2}..
+        /// </summary>
+        internal static string ProcessingRequestFailed {
+            get {
+                return ResourceManager.GetString("ProcessingRequestFailed", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/src/IssueViz/FixSuggestion/FixSuggestionResources.resx b/src/IssueViz/FixSuggestion/FixSuggestionResources.resx
new file mode 100644
index 0000000000..d3e7aff8d3
--- /dev/null
+++ b/src/IssueViz/FixSuggestion/FixSuggestionResources.resx
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="DoneProcessingRequest" xml:space="preserve">
+    <value>[Fix Suggestion in IDE] Done processing request. Configuration scope: {0}, SuggestionId: {1}</value>
+  </data>
+  <data name="ProcessingRequest" xml:space="preserve">
+    <value>[Fix Suggestion in IDE] Processing request. Configuration scope: {0}, SuggestionId: {1}</value>
+  </data>
+  <data name="ProcessingRequestFailed" xml:space="preserve">
+    <value>[Fix Suggestion in IDE] Fail to process request for configuration scope: {0}, SuggestionId: {1} due to {2}.</value>
+  </data>
+  <data name="GetConfigScopeRootPathFailed" xml:space="preserve">
+    <value>[Fix Suggestion in IDE] Could not determine configuration scope root path for scope [{0}] due to: {1}</value>
+  </data>
+  <data name="InfoBarButtonMoreInfo" xml:space="preserve">
+    <value>Learn more</value>
+  </data>
+  <data name="InfoBarButtonShowLogs" xml:space="preserve">
+    <value>Show logs</value>
+  </data>
+  <data name="InfoBarDefaultMessage" xml:space="preserve">
+    <value>Could not handle Open in IDE request. See the Logs for more information.</value>
+  </data>
+  <data name="InfoBarUnableToOpenFile" xml:space="preserve">
+    <value>Fix Suggestion in IDE. Could not open File: {0}. Please ensure that you're on the correct branch and the file has not been deleted locally.</value>
+  </data>
+  <data name="InfoBarInvalidRequest" xml:space="preserve">
+    <value>Unable to process Fix Suggestion in IDE request. Reason: {0}</value>
+  </data>
+  <data name="InfoBarUnableToLocateFixSuggestion" xml:space="preserve">
+    <value>Fix Suggestion in IDE. Could not locate the issue in the file. Please ensure the file ({0}) has not been modified.</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/IssueViz/FixSuggestion/IFixSuggestionHandler.cs b/src/IssueViz/FixSuggestion/IFixSuggestionHandler.cs
new file mode 100644
index 0000000000..1c332843d8
--- /dev/null
+++ b/src/IssueViz/FixSuggestion/IFixSuggestionHandler.cs
@@ -0,0 +1,28 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+
+namespace SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+
+public interface IFixSuggestionHandler
+{
+    void ApplyFixSuggestion(ShowFixSuggestionParams parameters);
+}
diff --git a/src/IssueViz/FixSuggestion/IFixSuggestionNotification.cs b/src/IssueViz/FixSuggestion/IFixSuggestionNotification.cs
new file mode 100644
index 0000000000..c0fcb06f6d
--- /dev/null
+++ b/src/IssueViz/FixSuggestion/IFixSuggestionNotification.cs
@@ -0,0 +1,150 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using System.ComponentModel.Composition;
+using SonarLint.VisualStudio.Core;
+using SonarLint.VisualStudio.Core.InfoBar;
+
+namespace SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+
+public interface IFixSuggestionNotification
+{
+    Task UnableToOpenFileAsync(string filePath);
+    Task InvalidRequestAsync(string reason);
+    Task UnableToLocateIssueAsync(string filePath);
+    Task ShowAsync(string text);
+    Task ClearAsync();
+}
+
+[Export(typeof(IFixSuggestionNotification))]
+[PartCreationPolicy(CreationPolicy.Shared)]
+internal sealed class FixSuggestionNotification : IFixSuggestionNotification, IDisposable
+{
+    private readonly IInfoBarManager infoBarManager;
+    private readonly IOutputWindowService outputWindowService;
+    private readonly IBrowserService browService;
+    private readonly IThreadHandling threadHandling;
+    private readonly object lockObject = new();
+    private IInfoBar currentInfoBar;
+
+    [ImportingConstructor]
+    public FixSuggestionNotification(IInfoBarManager infoBarManager,
+        IOutputWindowService outputWindowService,
+        IBrowserService browService,
+        IThreadHandling threadHandling)
+    {
+        this.infoBarManager = infoBarManager;
+        this.outputWindowService = outputWindowService;
+        this.browService = browService;
+        this.threadHandling = threadHandling;
+    }
+
+    public async Task UnableToOpenFileAsync(string filePath)
+    {
+        var unableToOpenFileMsg = string.Format(FixSuggestionResources.InfoBarUnableToOpenFile, filePath);
+        await ShowAsync(unableToOpenFileMsg);
+    }
+
+    public async Task InvalidRequestAsync(string reason)
+    {
+        var unableToOpenFileMsg = string.Format(FixSuggestionResources.InfoBarInvalidRequest, reason);
+        await ShowAsync(unableToOpenFileMsg);
+    }
+
+    public async Task UnableToLocateIssueAsync(string filePath)
+    {
+        var unableToOpenFileMsg = string.Format(FixSuggestionResources.InfoBarUnableToLocateFixSuggestion, filePath);
+        await ShowAsync(unableToOpenFileMsg);
+    }
+
+    public async Task ShowAsync(string text)
+    {
+        await threadHandling.RunOnUIThreadAsync(() =>
+        {
+            lock (lockObject)
+            {
+                RemoveExistingInfoBar();
+                AddInfoBar(text);
+            }
+        });
+    }
+
+    public async Task ClearAsync()
+    {
+        await threadHandling.RunOnUIThreadAsync(() =>
+        {
+            lock (lockObject)
+            {
+                RemoveExistingInfoBar();
+            }
+        });
+    }
+
+    private void AddInfoBar(string text)
+    {
+        string[] buttonTexts = [FixSuggestionResources.InfoBarButtonMoreInfo, FixSuggestionResources.InfoBarButtonShowLogs];
+        var textToShow = text ?? FixSuggestionResources.InfoBarDefaultMessage;
+        currentInfoBar = infoBarManager.AttachInfoBarToMainWindow(textToShow, SonarLintImageMoniker.OfficialSonarLintMoniker, buttonTexts);
+        Debug.Assert(currentInfoBar != null, "currentInfoBar != null");
+
+        currentInfoBar.ButtonClick += HandleInfoBarAction;
+        currentInfoBar.Closed += CurrentInfoBar_Closed;
+    }
+
+    private void HandleInfoBarAction(object sender, InfoBarButtonClickedEventArgs e)
+    {
+        if (e.ClickedButtonText == FixSuggestionResources.InfoBarButtonMoreInfo)
+        {
+            browService.Navigate(DocumentationLinks.OpenInIdeIssueLocation);
+        }
+
+        if (e.ClickedButtonText == FixSuggestionResources.InfoBarButtonShowLogs)
+        {
+            outputWindowService.Show();
+        }
+    }
+
+    private void RemoveExistingInfoBar()
+    {
+        if (currentInfoBar != null)
+        {
+            currentInfoBar.ButtonClick -= HandleInfoBarAction;
+            currentInfoBar.Closed -= CurrentInfoBar_Closed;
+            infoBarManager.DetachInfoBar(currentInfoBar);
+            currentInfoBar = null;
+        }
+    }
+
+    private void CurrentInfoBar_Closed(object sender, EventArgs e)
+    {
+        lock (lockObject)
+        {
+            RemoveExistingInfoBar();
+        }
+    }
+
+    public void Dispose()
+    {
+        lock (lockObject)
+        {
+            RemoveExistingInfoBar();
+        }
+    }
+}
diff --git a/src/IssueViz/IssueViz.csproj b/src/IssueViz/IssueViz.csproj
index 2a27e1ccae..5a20da8e84 100644
--- a/src/IssueViz/IssueViz.csproj
+++ b/src/IssueViz/IssueViz.csproj
@@ -53,12 +53,23 @@
       <CopyToOutputDirectory>Never</CopyToOutputDirectory>
     </Page>
 
+    <Compile Update="FixSuggestion\FixSuggestionResources.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>FixSuggestionResources.resx</DependentUpon>
+    </Compile>
+
     <Compile Update="Resources.Designer.cs">
       <DesignTime>True</DesignTime>
       <AutoGen>True</AutoGen>
       <DependentUpon>Resources.resx</DependentUpon>
     </Compile>
 
+    <EmbeddedResource Update="FixSuggestion\FixSuggestionResources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>FixSuggestionResources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+
     <EmbeddedResource Update="Resources.resx">
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Resources.Designer.cs</LastGenOutput>
diff --git a/src/SLCore.IntegrationTests/SLCoreTestRunner.cs b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs
index e5749b93ec..8747db8bde 100644
--- a/src/SLCore.IntegrationTests/SLCoreTestRunner.cs
+++ b/src/SLCore.IntegrationTests/SLCoreTestRunner.cs
@@ -93,7 +93,7 @@ public void Start()
             var constantsProvider = Substitute.For<ISLCoreConstantsProvider>();
             constantsProvider.ClientConstants.Returns(new ClientConstantsDto("SLVS_Integration_Tests",
                 $"SLVS_Integration_Tests/{VersionHelper.SonarLintVersion}", Process.GetCurrentProcess().Id));
-            constantsProvider.FeatureFlags.Returns(new FeatureFlagsDto(true, true, false, true, false, false, true, false));
+            constantsProvider.FeatureFlags.Returns(new FeatureFlagsDto(true, true, false, true, false, false, true, false, false));
             constantsProvider.TelemetryConstants.Returns(new TelemetryClientConstantAttributesDto("slvs_integration_tests", "SLVS Integration Tests",
                 VersionHelper.SonarLintVersion, "17.0", new()));
             SetLanguagesConfigurationToDefaults(constantsProvider);
diff --git a/src/SLCore.Listeners.UnitTests/BranchListenerTests.cs b/src/SLCore.Listeners.UnitTests/BranchListenerTests.cs
index 191377faed..b85e671c23 100644
--- a/src/SLCore.Listeners.UnitTests/BranchListenerTests.cs
+++ b/src/SLCore.Listeners.UnitTests/BranchListenerTests.cs
@@ -18,8 +18,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Collections.Generic;
-using System.Threading.Tasks;
 using SonarLint.VisualStudio.SLCore.Core;
 using SonarLint.VisualStudio.SLCore.Listener.Branch;
 
@@ -66,5 +64,15 @@ public void DidChangeMatchedSonarProjectBranch_ReturnsTaskCompleted(object param
 
             result.Should().Be(Task.CompletedTask);
         }
+
+        [TestMethod]
+        public async Task MatchProjectBranchAsync_ReturnsAlwaysTrue()
+        {
+            var testSubject = new BranchListener();
+
+            var response = await testSubject.MatchProjectBranchAsync(new MatchProjectBranchParams("my_config_scope_id", "the_branch_name"));
+
+            response.Should().BeEquivalentTo(new MatchProjectBranchResponse(true));
+        }
     }
 }
diff --git a/src/SLCore.Listeners.UnitTests/Implementation/ShowFixSuggestionListenerTests.cs b/src/SLCore.Listeners.UnitTests/Implementation/ShowFixSuggestionListenerTests.cs
new file mode 100644
index 0000000000..23b8c5ecce
--- /dev/null
+++ b/src/SLCore.Listeners.UnitTests/Implementation/ShowFixSuggestionListenerTests.cs
@@ -0,0 +1,70 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Core;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+using FileEditDto = SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models.FileEditDto;
+
+namespace SonarLint.VisualStudio.SLCore.Listeners.UnitTests.Implementation;
+
+[TestClass]
+public class ShowFixSuggestionListenerTests
+{
+    private ShowFixSuggestionListener testSubject;
+    private IFixSuggestionHandler fixSuggestionHandler;
+
+    [TestInitialize]
+    public void Initialize()
+    {
+        fixSuggestionHandler = Substitute.For<IFixSuggestionHandler>();
+        testSubject = new ShowFixSuggestionListener(fixSuggestionHandler);
+    }
+    
+    [TestMethod]
+    public void MefCtor_CheckIsExported()
+    {
+        MefTestHelpers.CheckTypeCanBeImported<ShowFixSuggestionListener, ISLCoreListener>(
+            MefTestHelpers.CreateExport<IFixSuggestionHandler>());
+    }
+
+    [TestMethod]
+    public void MefCtor_CheckIsSingleton()
+    {
+        MefTestHelpers.CheckIsSingletonMefComponent<ShowFixSuggestionListener>();
+    }
+
+    [TestMethod]
+    public void ShowFixSuggestion_CallsHandler()
+    {
+        var listOfChanges = new List<ChangesDto>
+        {
+            new(new LineRangeDto(10, 10), "public void test()", "private void test()")
+        };
+        var fileEditDto = new FileEditDto(@"C:\Users\test\TestProject\AFile.cs", listOfChanges);
+        var fixSuggestionDto = new FixSuggestionDto("SUGGESTION_ID", "AN EXPLANATION", fileEditDto);
+        var parameters = new ShowFixSuggestionParams("CONFIG_SCOPE_ID", "S1234", fixSuggestionDto);
+        
+        testSubject.ShowFixSuggestion(parameters);
+        
+        fixSuggestionHandler.Received(1).ApplyFixSuggestion(parameters);
+    }
+}
diff --git a/src/SLCore.Listeners/Implementation/BranchListener.cs b/src/SLCore.Listeners/Implementation/BranchListener.cs
index 4a8ca833c3..b25421b6eb 100644
--- a/src/SLCore.Listeners/Implementation/BranchListener.cs
+++ b/src/SLCore.Listeners/Implementation/BranchListener.cs
@@ -18,9 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Collections.Generic;
 using System.ComponentModel.Composition;
-using System.Threading.Tasks;
 using SonarLint.VisualStudio.SLCore.Core;
 using SonarLint.VisualStudio.SLCore.Listener.Branch;
 
@@ -49,5 +47,14 @@ public Task DidChangeMatchedSonarProjectBranchAsync(object parameters)
         {
             return Task.CompletedTask;
         }
+
+        public Task<MatchProjectBranchResponse> MatchProjectBranchAsync(MatchProjectBranchParams parameters)
+        {
+            // At the moment we don't need to match the project branch as there is logic to handle the cases
+            // where there is a mismatch between the project branch and the server branch
+            // This is currently not fully supported because it depends on the showMessage method
+            // https://sonarsource.atlassian.net/browse/SLVS-1494
+            return Task.FromResult(new MatchProjectBranchResponse(true));
+        }
     }
 }
diff --git a/src/SLCore.Listeners/Implementation/ShowFixSuggestionListener.cs b/src/SLCore.Listeners/Implementation/ShowFixSuggestionListener.cs
new file mode 100644
index 0000000000..0a04d3ad1c
--- /dev/null
+++ b/src/SLCore.Listeners/Implementation/ShowFixSuggestionListener.cs
@@ -0,0 +1,44 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using System.ComponentModel.Composition;
+using SonarLint.VisualStudio.IssueVisualization.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Core;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+
+namespace SonarLint.VisualStudio.SLCore.Listeners.Implementation;
+
+[Export(typeof(ISLCoreListener))]
+[PartCreationPolicy(CreationPolicy.Shared)]
+public class ShowFixSuggestionListener : IShowFixSuggestionListener
+{
+    private readonly IFixSuggestionHandler fixSuggestionHandler;
+
+    [ImportingConstructor]
+    public ShowFixSuggestionListener(IFixSuggestionHandler fixSuggestionHandler)
+    {
+        this.fixSuggestionHandler = fixSuggestionHandler;
+    }
+
+    public void ShowFixSuggestion(ShowFixSuggestionParams parameters)
+    {
+        fixSuggestionHandler.ApplyFixSuggestion(parameters);
+    }
+}
diff --git a/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchParamsTests.cs b/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchParamsTests.cs
new file mode 100644
index 0000000000..e5d0e8c561
--- /dev/null
+++ b/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchParamsTests.cs
@@ -0,0 +1,45 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using Newtonsoft.Json;
+using SonarLint.VisualStudio.SLCore.Listener.Branch;
+
+namespace SonarLint.VisualStudio.SLCore.UnitTests.Listener.Branch;
+
+[TestClass]
+public class MatchProjectBranchParamsTests
+{
+    [TestMethod]
+    public void Deserialize_AsExpected()
+    {
+        var expectedObject = new MatchProjectBranchParams("CONFIG_SCOPE_ID", "remote-branch-name");
+        
+        const string serializedParams = """
+                                      {
+                                        "configurationScopeId": "CONFIG_SCOPE_ID",
+                                        "serverBranchToMatch": "remote-branch-name"
+                                      }
+                                      """;
+
+        var deserializedObject = JsonConvert.DeserializeObject<MatchProjectBranchParams>(serializedParams);
+
+        deserializedObject.Should().Be(expectedObject);
+    }
+}
diff --git a/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchResponseTests.cs b/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchResponseTests.cs
new file mode 100644
index 0000000000..fee99eccf9
--- /dev/null
+++ b/src/SLCore.UnitTests/Listener/Branch/MatchProjectBranchResponseTests.cs
@@ -0,0 +1,46 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using Newtonsoft.Json;
+using SonarLint.VisualStudio.SLCore.Listener.Branch;
+
+namespace SonarLint.VisualStudio.SLCore.UnitTests.Listener.Branch;
+
+[TestClass]
+public class MatchProjectBranchResponseTests
+{
+    [TestMethod]
+    [DataRow(true, "true")]
+    [DataRow(false, "false")]
+    public void Serialize_AsExpected(bool isBranchMatched, string expectedResponse)
+    {
+        var testSubject = new MatchProjectBranchResponse(isBranchMatched);
+
+        var expectedString = $$"""
+                               {
+                                 "isBranchMatched": {{expectedResponse}}
+                               }
+                               """;
+
+        var serializedString = JsonConvert.SerializeObject(testSubject, Formatting.Indented);
+
+        serializedString.Should().Be(expectedString);
+    }
+}
diff --git a/src/SLCore.UnitTests/Listener/FixSuggestion/ShowFixSuggestionParamsTests.cs b/src/SLCore.UnitTests/Listener/FixSuggestion/ShowFixSuggestionParamsTests.cs
new file mode 100644
index 0000000000..e8aff94c84
--- /dev/null
+++ b/src/SLCore.UnitTests/Listener/FixSuggestion/ShowFixSuggestionParamsTests.cs
@@ -0,0 +1,70 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using Newtonsoft.Json;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+using FileEditDto = SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models.FileEditDto;
+
+namespace SonarLint.VisualStudio.SLCore.UnitTests.Listener.FixSuggestion;
+
+[TestClass]
+public class ShowFixSuggestionParamsTests
+{
+    [TestMethod]
+    public void Serialize_AsExpected()
+    {
+        var listOfChanges = new List<ChangesDto>
+        {
+            new(new LineRangeDto(10, 10), "public void test()", "private void test()")
+        };
+        var fileEditDto = new FileEditDto(@"C:\Users\test\TestProject\AFile.cs", listOfChanges);
+        var fixSuggestionDto = new FixSuggestionDto("SUGGESTION_ID", "AN EXPLANATION", fileEditDto);
+        var testSubject = new ShowFixSuggestionParams("CONFIG_SCOPE_ID", "S1234", fixSuggestionDto);
+
+        const string expectedString = """
+                                      {
+                                        "configurationScopeId": "CONFIG_SCOPE_ID",
+                                        "issueKey": "S1234",
+                                        "fixSuggestion": {
+                                          "suggestionId": "SUGGESTION_ID",
+                                          "explanation": "AN EXPLANATION",
+                                          "fileEdit": {
+                                            "idePath": "C:\\Users\\test\\TestProject\\AFile.cs",
+                                            "changes": [
+                                              {
+                                                "beforeLineRange": {
+                                                  "startLine": 10,
+                                                  "endLine": 10
+                                                },
+                                                "before": "public void test()",
+                                                "after": "private void test()"
+                                              }
+                                            ]
+                                          }
+                                        }
+                                      }
+                                      """;
+
+        var serializedString = JsonConvert.SerializeObject(testSubject, Formatting.Indented);
+
+        serializedString.Should().Be(expectedString);
+    }
+}
diff --git a/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs b/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs
index b410c59204..179d0faa7c 100644
--- a/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs
+++ b/src/SLCore.UnitTests/SLCoreInstanceHandleTests.cs
@@ -44,7 +44,7 @@ public class SLCoreInstanceHandleTests
     private const string UserHome = "userHomeSl";
     
     private static readonly ClientConstantsDto ClientConstants = new(default, default, default);
-    private static readonly FeatureFlagsDto FeatureFlags = new(default, default, default, default, default, default, default, default);
+    private static readonly FeatureFlagsDto FeatureFlags = new(default, default, default, default, default, default, default, default, default);
     private static readonly TelemetryClientConstantAttributesDto TelemetryConstants = new(default, default, default, default, default);
 
     private static readonly SonarQubeConnectionConfigurationDto SonarQubeConnection1 = new("sq1", true, "http://localhost/");
diff --git a/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs b/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs
index cb417992de..0771e99e17 100644
--- a/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs
+++ b/src/SLCore.UnitTests/Service/Lifecycle/InitializeParamsTests.cs
@@ -18,7 +18,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Collections.Generic;
 using Newtonsoft.Json;
 using SonarLint.VisualStudio.SLCore.Common.Models;
 using SonarLint.VisualStudio.SLCore.Service.Connection.Models;
@@ -37,7 +36,7 @@ public void Serialize_AsExpected()
         var testSubject = new InitializeParams(
             new ClientConstantsDto("TESTname", "TESTagent", 11223344),
             new HttpConfigurationDto(new SslConfigurationDto()),
-            new FeatureFlagsDto(false, true, false, true, false, true, false, false),
+            new FeatureFlagsDto(false, true, false, true, false, true, false, false, false),
             "storageRoot",
             "workDir",
             ["myplugin1", "myplugin2"],
@@ -77,7 +76,8 @@ [new SonarCloudConnectionConfigurationDto("con2", false, "organization1")],
                                     "shouldManageServerSentEvents": false,
                                     "enableDataflowBugDetection": true,
                                     "shouldManageFullSynchronization": false,
-                                    "enableTelemetry": false
+                                    "enableTelemetry": false,
+                                    "canOpenFixSuggestion": false
                                   },
                                   "storageRoot": "storageRoot",
                                   "workDir": "workDir",
diff --git a/src/SLCore/Listener/Branch/IBranchListener.cs b/src/SLCore/Listener/Branch/IBranchListener.cs
index 9fda6881ef..1e335f0681 100644
--- a/src/SLCore/Listener/Branch/IBranchListener.cs
+++ b/src/SLCore/Listener/Branch/IBranchListener.cs
@@ -18,7 +18,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Threading.Tasks;
 using SonarLint.VisualStudio.SLCore.Core;
 
 namespace SonarLint.VisualStudio.SLCore.Listener.Branch;
@@ -38,4 +37,12 @@ public interface IBranchListener : ISLCoreListener
     /// <param name="parameters">Parameter's here for compability we discard it</param>
     /// <remarks>This will be implemented properly in the future when needed but features we support does not need branch awareness for now</remarks>
     Task DidChangeMatchedSonarProjectBranchAsync(object parameters);
+
+    /// <summary>
+    /// Used for checking whether a locally checked out branch matches a candidate branch name (not necessarily a Sonar branch).
+    /// For example, in "show fix suggestion" use-case, to match a local branch with a PR branch that originated a fix suggestion
+    /// </summary>
+    /// <param name="parameters">The remote branch details to match</param>
+    /// <returns>Is local branch matching the remote branch</returns>
+    Task<MatchProjectBranchResponse> MatchProjectBranchAsync(MatchProjectBranchParams parameters);
 }
diff --git a/src/SLCore/Listener/Branch/MatchProjectBranchParams.cs b/src/SLCore/Listener/Branch/MatchProjectBranchParams.cs
new file mode 100644
index 0000000000..eb41a08a37
--- /dev/null
+++ b/src/SLCore/Listener/Branch/MatchProjectBranchParams.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.Branch;
+
+public record MatchProjectBranchParams(string configurationScopeId, string serverBranchToMatch);
diff --git a/src/SLCore/Listener/Branch/MatchProjectBranchResponse.cs b/src/SLCore/Listener/Branch/MatchProjectBranchResponse.cs
new file mode 100644
index 0000000000..e3ab7e9fa3
--- /dev/null
+++ b/src/SLCore/Listener/Branch/MatchProjectBranchResponse.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.Branch;
+
+public record MatchProjectBranchResponse(bool isBranchMatched);
diff --git a/src/SLCore/Listener/FixSuggestion/IShowFixSuggestionListener.cs b/src/SLCore/Listener/FixSuggestion/IShowFixSuggestionListener.cs
new file mode 100644
index 0000000000..d9a8804ad4
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/IShowFixSuggestionListener.cs
@@ -0,0 +1,28 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.SLCore.Core;
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+
+public interface IShowFixSuggestionListener : ISLCoreListener
+{
+    void ShowFixSuggestion(ShowFixSuggestionParams parameters);
+}
diff --git a/src/SLCore/Listener/FixSuggestion/Models/ChangesDto.cs b/src/SLCore/Listener/FixSuggestion/Models/ChangesDto.cs
new file mode 100644
index 0000000000..ae58b02f17
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/Models/ChangesDto.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+public record ChangesDto(LineRangeDto beforeLineRange, string before, string after);
diff --git a/src/SLCore/Listener/FixSuggestion/Models/FileEditDto.cs b/src/SLCore/Listener/FixSuggestion/Models/FileEditDto.cs
new file mode 100644
index 0000000000..ba666ff98b
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/Models/FileEditDto.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+public record FileEditDto(string idePath, List<ChangesDto> changes);
diff --git a/src/SLCore/Listener/FixSuggestion/Models/FixSuggestionDto.cs b/src/SLCore/Listener/FixSuggestion/Models/FixSuggestionDto.cs
new file mode 100644
index 0000000000..329fa5fc9a
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/Models/FixSuggestionDto.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+public record FixSuggestionDto(string suggestionId, string explanation, FileEditDto fileEdit);
diff --git a/src/SLCore/Listener/FixSuggestion/Models/LineRangeDto.cs b/src/SLCore/Listener/FixSuggestion/Models/LineRangeDto.cs
new file mode 100644
index 0000000000..2c4927cd4a
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/Models/LineRangeDto.cs
@@ -0,0 +1,23 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+public record LineRangeDto(int startLine, int endLine);
diff --git a/src/SLCore/Listener/FixSuggestion/ShowFixSuggestionParams.cs b/src/SLCore/Listener/FixSuggestion/ShowFixSuggestionParams.cs
new file mode 100644
index 0000000000..f61e5d553f
--- /dev/null
+++ b/src/SLCore/Listener/FixSuggestion/ShowFixSuggestionParams.cs
@@ -0,0 +1,25 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.SLCore.Listener.FixSuggestion.Models;
+
+namespace SonarLint.VisualStudio.SLCore.Listener.FixSuggestion;
+
+public record ShowFixSuggestionParams(string configurationScopeId, string issueKey, FixSuggestionDto fixSuggestion);
diff --git a/src/SLCore/Service/Lifecycle/Models/FeatureFlagsDto.cs b/src/SLCore/Service/Lifecycle/Models/FeatureFlagsDto.cs
index 3391e33b5e..b289c850cc 100644
--- a/src/SLCore/Service/Lifecycle/Models/FeatureFlagsDto.cs
+++ b/src/SLCore/Service/Lifecycle/Models/FeatureFlagsDto.cs
@@ -28,5 +28,6 @@ public record FeatureFlagsDto(
         bool shouldManageServerSentEvents,
         bool enableDataflowBugDetection,
         bool shouldManageFullSynchronization,
-        bool enableTelemetry);
+        bool enableTelemetry,
+        bool canOpenFixSuggestion);
 }