diff --git a/arduino/cores/packagemanager/download.go b/arduino/cores/packagemanager/download.go
index a45241d9d4f..54d3fe3012a 100644
--- a/arduino/cores/packagemanager/download.go
+++ b/arduino/cores/packagemanager/download.go
@@ -43,8 +43,8 @@ func (platform *PlatformReference) String() string {
 
 // FindPlatform returns the Platform matching the PlatformReference or nil if not found.
 // The PlatformVersion field of the reference is ignored.
-func (pm *PackageManager) FindPlatform(ref *PlatformReference) *cores.Platform {
-	targetPackage, ok := pm.Packages[ref.Package]
+func (pme *Explorer) FindPlatform(ref *PlatformReference) *cores.Platform {
+	targetPackage, ok := pme.packages[ref.Package]
 	if !ok {
 		return nil
 	}
@@ -56,8 +56,8 @@ func (pm *PackageManager) FindPlatform(ref *PlatformReference) *cores.Platform {
 }
 
 // FindPlatformRelease returns the PlatformRelease matching the PlatformReference or nil if not found
-func (pm *PackageManager) FindPlatformRelease(ref *PlatformReference) *cores.PlatformRelease {
-	platform := pm.FindPlatform(ref)
+func (pme *Explorer) FindPlatformRelease(ref *PlatformReference) *cores.PlatformRelease {
+	platform := pme.FindPlatform(ref)
 	if platform == nil {
 		return nil
 	}
@@ -70,8 +70,8 @@ func (pm *PackageManager) FindPlatformRelease(ref *PlatformReference) *cores.Pla
 
 // FindPlatformReleaseDependencies takes a PlatformReference and returns a set of items to download and
 // a set of outputs for non existing platforms.
-func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReference) (*cores.PlatformRelease, []*cores.ToolRelease, error) {
-	targetPackage, exists := pm.Packages[item.Package]
+func (pme *Explorer) FindPlatformReleaseDependencies(item *PlatformReference) (*cores.PlatformRelease, []*cores.ToolRelease, error) {
+	targetPackage, exists := pme.packages[item.Package]
 	if !exists {
 		return nil, nil, fmt.Errorf(tr("package %s not found"), item.Package)
 	}
@@ -94,14 +94,14 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc
 	}
 
 	// replaces "latest" with latest version too
-	toolDeps, err := pm.Packages.GetPlatformReleaseToolDependencies(release)
+	toolDeps, err := pme.packages.GetPlatformReleaseToolDependencies(release)
 	if err != nil {
 		return nil, nil, fmt.Errorf(tr("getting tool dependencies for platform %[1]s: %[2]s"), release.String(), err)
 	}
 
 	// discovery dependencies differ from normal tool since we always want to use the latest
 	// available version for the platform package
-	discoveryDependencies, err := pm.Packages.GetPlatformReleaseDiscoveryDependencies(release)
+	discoveryDependencies, err := pme.packages.GetPlatformReleaseDiscoveryDependencies(release)
 	if err != nil {
 		return nil, nil, fmt.Errorf(tr("getting discovery dependencies for platform %[1]s: %[2]s"), release.String(), err)
 	}
@@ -109,7 +109,7 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc
 
 	// monitor dependencies differ from normal tool since we always want to use the latest
 	// available version for the platform package
-	monitorDependencies, err := pm.Packages.GetPlatformReleaseMonitorDependencies(release)
+	monitorDependencies, err := pme.packages.GetPlatformReleaseMonitorDependencies(release)
 	if err != nil {
 		return nil, nil, fmt.Errorf(tr("getting monitor dependencies for platform %[1]s: %[2]s"), release.String(), err)
 	}
@@ -120,14 +120,14 @@ func (pm *PackageManager) FindPlatformReleaseDependencies(item *PlatformReferenc
 
 // DownloadToolRelease downloads a ToolRelease. If the tool is already downloaded a nil Downloader
 // is returned. Uses the given downloader configuration for download, or the default config if nil.
-func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
+func (pme *Explorer) DownloadToolRelease(tool *cores.ToolRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
 	resource := tool.GetCompatibleFlavour()
 	if resource == nil {
 		return &arduino.FailedDownloadError{
 			Message: tr("Error downloading tool %s", tool),
 			Cause:   errors.New(tr("no versions available for the current OS"))}
 	}
-	if err := resource.Download(pm.DownloadDir, config, tool.String(), progressCB); err != nil {
+	if err := resource.Download(pme.DownloadDir, config, tool.String(), progressCB); err != nil {
 		return &arduino.FailedDownloadError{
 			Message: tr("Error downloading tool %s", tool),
 			Cause:   err}
@@ -137,9 +137,9 @@ func (pm *PackageManager) DownloadToolRelease(tool *cores.ToolRelease, config *d
 
 // DownloadPlatformRelease downloads a PlatformRelease. If the platform is already downloaded a
 // nil Downloader is returned.
-func (pm *PackageManager) DownloadPlatformRelease(platform *cores.PlatformRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
+func (pme *Explorer) DownloadPlatformRelease(platform *cores.PlatformRelease, config *downloader.Config, progressCB rpc.DownloadProgressCB) error {
 	if platform.Resource == nil {
 		return &arduino.PlatformNotFoundError{Platform: platform.String()}
 	}
-	return platform.Resource.Download(pm.DownloadDir, config, platform.String(), progressCB)
+	return platform.Resource.Download(pme.DownloadDir, config, platform.String(), progressCB)
 }
diff --git a/arduino/cores/packagemanager/identify.go b/arduino/cores/packagemanager/identify.go
index 6765ca66e21..b785bf02263 100644
--- a/arduino/cores/packagemanager/identify.go
+++ b/arduino/cores/packagemanager/identify.go
@@ -22,12 +22,12 @@ import (
 
 // IdentifyBoard returns a list of boards whose identification properties match the
 // provided ones.
-func (pm *PackageManager) IdentifyBoard(idProps *properties.Map) []*cores.Board {
+func (pme *Explorer) IdentifyBoard(idProps *properties.Map) []*cores.Board {
 	if idProps.Size() == 0 {
 		return []*cores.Board{}
 	}
 	foundBoards := []*cores.Board{}
-	for _, board := range pm.InstalledBoards() {
+	for _, board := range pme.InstalledBoards() {
 		if board.IsBoardMatchingIDProperties(idProps) {
 			foundBoards = append(foundBoards, board)
 		}
diff --git a/arduino/cores/packagemanager/install_uninstall.go b/arduino/cores/packagemanager/install_uninstall.go
index 001c4885700..4ab87361111 100644
--- a/arduino/cores/packagemanager/install_uninstall.go
+++ b/arduino/cores/packagemanager/install_uninstall.go
@@ -32,7 +32,7 @@ import (
 // DownloadAndInstallPlatformUpgrades runs a full installation process to upgrade the given platform.
 // This method takes care of downloading missing archives, upgrading platforms and tools, and
 // removing the previously installed platform/tools that are no longer needed after the upgrade.
-func (pm *PackageManager) DownloadAndInstallPlatformUpgrades(
+func (pme *Explorer) DownloadAndInstallPlatformUpgrades(
 	platformRef *PlatformReference,
 	downloadCB rpc.DownloadProgressCB,
 	taskCB rpc.TaskProgressCB,
@@ -43,11 +43,11 @@ func (pm *PackageManager) DownloadAndInstallPlatformUpgrades(
 	}
 
 	// Search the latest version for all specified platforms
-	platform := pm.FindPlatform(platformRef)
+	platform := pme.FindPlatform(platformRef)
 	if platform == nil {
 		return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
 	}
-	installed := pm.GetInstalledPlatformRelease(platform)
+	installed := pme.GetInstalledPlatformRelease(platform)
 	if installed == nil {
 		return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
 	}
@@ -57,11 +57,11 @@ func (pm *PackageManager) DownloadAndInstallPlatformUpgrades(
 	}
 	platformRef.PlatformVersion = latest.Version
 
-	platformRelease, tools, err := pm.FindPlatformReleaseDependencies(platformRef)
+	platformRelease, tools, err := pme.FindPlatformReleaseDependencies(platformRef)
 	if err != nil {
 		return &arduino.PlatformNotFoundError{Platform: platformRef.String()}
 	}
-	if err := pm.DownloadAndInstallPlatformAndTools(platformRelease, tools, downloadCB, taskCB, skipPostInstall); err != nil {
+	if err := pme.DownloadAndInstallPlatformAndTools(platformRelease, tools, downloadCB, taskCB, skipPostInstall); err != nil {
 		return err
 	}
 
@@ -71,11 +71,11 @@ func (pm *PackageManager) DownloadAndInstallPlatformUpgrades(
 // DownloadAndInstallPlatformAndTools runs a full installation process for the given platform and tools.
 // This method takes care of downloading missing archives, installing/upgrading platforms and tools, and
 // removing the previously installed platform/tools that are no longer needed after the upgrade.
-func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
+func (pme *Explorer) DownloadAndInstallPlatformAndTools(
 	platformRelease *cores.PlatformRelease, requiredTools []*cores.ToolRelease,
 	downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB,
 	skipPostInstall bool) error {
-	log := pm.log.WithField("platform", platformRelease)
+	log := pme.log.WithField("platform", platformRelease)
 
 	// Prerequisite checks before install
 	toolsToInstall := []*cores.ToolRelease{}
@@ -91,23 +91,23 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 	// Package download
 	taskCB(&rpc.TaskProgress{Name: tr("Downloading packages")})
 	for _, tool := range toolsToInstall {
-		if err := pm.DownloadToolRelease(tool, nil, downloadCB); err != nil {
+		if err := pme.DownloadToolRelease(tool, nil, downloadCB); err != nil {
 			return err
 		}
 	}
-	if err := pm.DownloadPlatformRelease(platformRelease, nil, downloadCB); err != nil {
+	if err := pme.DownloadPlatformRelease(platformRelease, nil, downloadCB); err != nil {
 		return err
 	}
 	taskCB(&rpc.TaskProgress{Completed: true})
 
 	// Install tools first
 	for _, tool := range toolsToInstall {
-		if err := pm.InstallTool(tool, taskCB); err != nil {
+		if err := pme.InstallTool(tool, taskCB); err != nil {
 			return err
 		}
 	}
 
-	installed := pm.GetInstalledPlatformRelease(platformRelease.Platform)
+	installed := pme.GetInstalledPlatformRelease(platformRelease.Platform)
 	installedTools := []*cores.ToolRelease{}
 	if installed == nil {
 		// No version of this platform is installed
@@ -127,21 +127,21 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 		// This must be done so tools used by the currently installed version are
 		// removed if not used also by the newly installed version.
 		var err error
-		_, installedTools, err = pm.FindPlatformReleaseDependencies(platformRef)
+		_, installedTools, err = pme.FindPlatformReleaseDependencies(platformRef)
 		if err != nil {
 			return &arduino.NotFoundError{Message: tr("Can't find dependencies for platform %s", platformRef), Cause: err}
 		}
 	}
 
 	// Install
-	if err := pm.InstallPlatform(platformRelease); err != nil {
+	if err := pme.InstallPlatform(platformRelease); err != nil {
 		log.WithError(err).Error("Cannot install platform")
 		return &arduino.FailedInstallError{Message: tr("Cannot install platform"), Cause: err}
 	}
 
 	// If upgrading remove previous release
 	if installed != nil {
-		uninstallErr := pm.UninstallPlatform(installed, taskCB)
+		uninstallErr := pme.UninstallPlatform(installed, taskCB)
 
 		// In case of error try to rollback
 		if uninstallErr != nil {
@@ -149,7 +149,7 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 			taskCB(&rpc.TaskProgress{Message: tr("Error upgrading platform: %s", uninstallErr)})
 
 			// Rollback
-			if err := pm.UninstallPlatform(platformRelease, taskCB); err != nil {
+			if err := pme.UninstallPlatform(platformRelease, taskCB); err != nil {
 				log.WithError(err).Error("Error rolling-back changes.")
 				taskCB(&rpc.TaskProgress{Message: tr("Error rolling-back changes: %s", err)})
 			}
@@ -160,8 +160,8 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 		// Uninstall unused tools
 		for _, tool := range installedTools {
 			taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s, tool is no more required", tool)})
-			if !pm.IsToolRequired(tool) {
-				pm.UninstallTool(tool, taskCB)
+			if !pme.IsToolRequired(tool) {
+				pme.UninstallTool(tool, taskCB)
 			}
 		}
 
@@ -171,7 +171,7 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 	if !skipPostInstall {
 		log.Info("Running post_install script")
 		taskCB(&rpc.TaskProgress{Message: tr("Configuring platform.")})
-		if err := pm.RunPostInstallScript(platformRelease); err != nil {
+		if err := pme.RunPostInstallScript(platformRelease); err != nil {
 			taskCB(&rpc.TaskProgress{Message: tr("WARNING cannot configure platform: %s", err)})
 		}
 	} else {
@@ -185,18 +185,18 @@ func (pm *PackageManager) DownloadAndInstallPlatformAndTools(
 }
 
 // InstallPlatform installs a specific release of a platform.
-func (pm *PackageManager) InstallPlatform(platformRelease *cores.PlatformRelease) error {
-	destDir := pm.PackagesDir.Join(
+func (pme *Explorer) InstallPlatform(platformRelease *cores.PlatformRelease) error {
+	destDir := pme.PackagesDir.Join(
 		platformRelease.Platform.Package.Name,
 		"hardware",
 		platformRelease.Platform.Architecture,
 		platformRelease.Version.String())
-	return pm.InstallPlatformInDirectory(platformRelease, destDir)
+	return pme.InstallPlatformInDirectory(platformRelease, destDir)
 }
 
 // InstallPlatformInDirectory installs a specific release of a platform in a specific directory.
-func (pm *PackageManager) InstallPlatformInDirectory(platformRelease *cores.PlatformRelease, destDir *paths.Path) error {
-	if err := platformRelease.Resource.Install(pm.DownloadDir, pm.tempDir, destDir); err != nil {
+func (pme *Explorer) InstallPlatformInDirectory(platformRelease *cores.PlatformRelease, destDir *paths.Path) error {
+	if err := platformRelease.Resource.Install(pme.DownloadDir, pme.tempDir, destDir); err != nil {
 		return errors.Errorf(tr("installing platform %[1]s: %[2]s"), platformRelease, err)
 	}
 	if d, err := destDir.Abs(); err == nil {
@@ -204,13 +204,13 @@ func (pm *PackageManager) InstallPlatformInDirectory(platformRelease *cores.Plat
 	} else {
 		return err
 	}
-	if err := pm.cacheInstalledJSON(platformRelease); err != nil {
+	if err := pme.cacheInstalledJSON(platformRelease); err != nil {
 		return errors.Errorf(tr("creating installed.json in %[1]s: %[2]s"), platformRelease.InstallDir, err)
 	}
 	return nil
 }
 
-func (pm *PackageManager) cacheInstalledJSON(platformRelease *cores.PlatformRelease) error {
+func (pme *Explorer) cacheInstalledJSON(platformRelease *cores.PlatformRelease) error {
 	index := packageindex.IndexFromPlatformRelease(platformRelease)
 	platformJSON, err := json.MarshalIndent(index, "", "  ")
 	if err != nil {
@@ -223,7 +223,7 @@ func (pm *PackageManager) cacheInstalledJSON(platformRelease *cores.PlatformRele
 
 // RunPostInstallScript runs the post_install.sh (or post_install.bat) script for the
 // specified platformRelease.
-func (pm *PackageManager) RunPostInstallScript(platformRelease *cores.PlatformRelease) error {
+func (pme *Explorer) RunPostInstallScript(platformRelease *cores.PlatformRelease) error {
 	if !platformRelease.IsInstalled() {
 		return errors.New(tr("platform not installed"))
 	}
@@ -233,7 +233,7 @@ func (pm *PackageManager) RunPostInstallScript(platformRelease *cores.PlatformRe
 	}
 	postInstall := platformRelease.InstallDir.Join(postInstallFilename)
 	if postInstall.Exist() && postInstall.IsNotDir() {
-		cmd, err := executils.NewProcessFromPath(pm.GetEnvVarsForSpawnedProcess(), postInstall)
+		cmd, err := executils.NewProcessFromPath(pme.GetEnvVarsForSpawnedProcess(), postInstall)
 		if err != nil {
 			return err
 		}
@@ -246,15 +246,15 @@ func (pm *PackageManager) RunPostInstallScript(platformRelease *cores.PlatformRe
 }
 
 // IsManagedPlatformRelease returns true if the PlatforRelease is managed by the PackageManager
-func (pm *PackageManager) IsManagedPlatformRelease(platformRelease *cores.PlatformRelease) bool {
-	if pm.PackagesDir == nil {
+func (pme *Explorer) IsManagedPlatformRelease(platformRelease *cores.PlatformRelease) bool {
+	if pme.PackagesDir == nil {
 		return false
 	}
 	installDir := platformRelease.InstallDir.Clone()
 	if installDir.FollowSymLink() != nil {
 		return false
 	}
-	packagesDir := pm.PackagesDir.Clone()
+	packagesDir := pme.PackagesDir.Clone()
 	if packagesDir.FollowSymLink() != nil {
 		return false
 	}
@@ -266,8 +266,8 @@ func (pm *PackageManager) IsManagedPlatformRelease(platformRelease *cores.Platfo
 }
 
 // UninstallPlatform remove a PlatformRelease.
-func (pm *PackageManager) UninstallPlatform(platformRelease *cores.PlatformRelease, taskCB rpc.TaskProgressCB) error {
-	log := pm.log.WithField("platform", platformRelease)
+func (pme *Explorer) UninstallPlatform(platformRelease *cores.PlatformRelease, taskCB rpc.TaskProgressCB) error {
+	log := pme.log.WithField("platform", platformRelease)
 
 	log.Info("Uninstalling platform")
 	taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s", platformRelease)})
@@ -279,7 +279,7 @@ func (pm *PackageManager) UninstallPlatform(platformRelease *cores.PlatformRelea
 	}
 
 	// Safety measure
-	if !pm.IsManagedPlatformRelease(platformRelease) {
+	if !pme.IsManagedPlatformRelease(platformRelease) {
 		err := fmt.Errorf(tr("%s is not managed by package manager"), platformRelease)
 		log.WithError(err).Error("Error uninstalling")
 		return &arduino.FailedUninstallError{Message: err.Error()}
@@ -299,8 +299,8 @@ func (pm *PackageManager) UninstallPlatform(platformRelease *cores.PlatformRelea
 }
 
 // InstallTool installs a specific release of a tool.
-func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
-	log := pm.log.WithField("Tool", toolRelease)
+func (pme *Explorer) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
+	log := pme.log.WithField("Tool", toolRelease)
 
 	if toolRelease.IsInstalled() {
 		log.Warn("Tool already installed")
@@ -315,12 +315,12 @@ func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc
 	if toolResource == nil {
 		return fmt.Errorf(tr("no compatible version of %s tools found for the current os"), toolRelease.Tool.Name)
 	}
-	destDir := pm.PackagesDir.Join(
+	destDir := pme.PackagesDir.Join(
 		toolRelease.Tool.Package.Name,
 		"tools",
 		toolRelease.Tool.Name,
 		toolRelease.Version.String())
-	err := toolResource.Install(pm.DownloadDir, pm.tempDir, destDir)
+	err := toolResource.Install(pme.DownloadDir, pme.tempDir, destDir)
 	if err != nil {
 		log.WithError(err).Warn("Cannot install tool")
 		return &arduino.FailedInstallError{Message: tr("Cannot install tool %s", toolRelease), Cause: err}
@@ -332,15 +332,15 @@ func (pm *PackageManager) InstallTool(toolRelease *cores.ToolRelease, taskCB rpc
 }
 
 // IsManagedToolRelease returns true if the ToolRelease is managed by the PackageManager
-func (pm *PackageManager) IsManagedToolRelease(toolRelease *cores.ToolRelease) bool {
-	if pm.PackagesDir == nil {
+func (pme *Explorer) IsManagedToolRelease(toolRelease *cores.ToolRelease) bool {
+	if pme.PackagesDir == nil {
 		return false
 	}
 	installDir := toolRelease.InstallDir.Clone()
 	if installDir.FollowSymLink() != nil {
 		return false
 	}
-	packagesDir := pm.PackagesDir.Clone()
+	packagesDir := pme.PackagesDir.Clone()
 	if packagesDir.FollowSymLink() != nil {
 		return false
 	}
@@ -352,8 +352,8 @@ func (pm *PackageManager) IsManagedToolRelease(toolRelease *cores.ToolRelease) b
 }
 
 // UninstallTool remove a ToolRelease.
-func (pm *PackageManager) UninstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
-	log := pm.log.WithField("Tool", toolRelease)
+func (pme *Explorer) UninstallTool(toolRelease *cores.ToolRelease, taskCB rpc.TaskProgressCB) error {
+	log := pme.log.WithField("Tool", toolRelease)
 	log.Info("Uninstalling tool")
 
 	if toolRelease.InstallDir == nil {
@@ -361,7 +361,7 @@ func (pm *PackageManager) UninstallTool(toolRelease *cores.ToolRelease, taskCB r
 	}
 
 	// Safety measure
-	if !pm.IsManagedToolRelease(toolRelease) {
+	if !pme.IsManagedToolRelease(toolRelease) {
 		err := &arduino.FailedUninstallError{Message: tr("tool %s is not managed by package manager", toolRelease)}
 		log.WithError(err).Error("Error uninstalling")
 		return err
@@ -382,11 +382,11 @@ func (pm *PackageManager) UninstallTool(toolRelease *cores.ToolRelease, taskCB r
 
 // IsToolRequired returns true if any of the installed platforms requires the toolRelease
 // passed as parameter
-func (pm *PackageManager) IsToolRequired(toolRelease *cores.ToolRelease) bool {
+func (pme *Explorer) IsToolRequired(toolRelease *cores.ToolRelease) bool {
 	// Search in all installed platforms
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, platform := range targetPackage.Platforms {
-			if platformRelease := pm.GetInstalledPlatformRelease(platform); platformRelease != nil {
+			if platformRelease := pme.GetInstalledPlatformRelease(platform); platformRelease != nil {
 				if platformRelease.RequiresToolRelease(toolRelease) {
 					return true
 				}
diff --git a/arduino/cores/packagemanager/loader.go b/arduino/cores/packagemanager/loader.go
index 7b95c488694..8d12a5f6377 100644
--- a/arduino/cores/packagemanager/loader.go
+++ b/arduino/cores/packagemanager/loader.go
@@ -34,7 +34,7 @@ import (
 )
 
 // LoadHardware read all plaforms from the configured paths
-func (pm *PackageManager) LoadHardware() []error {
+func (pm *Builder) LoadHardware() []error {
 	hardwareDirs := configuration.HardwareDirectories(configuration.Settings)
 	merr := pm.LoadHardwareFromDirectories(hardwareDirs)
 
@@ -45,7 +45,7 @@ func (pm *PackageManager) LoadHardware() []error {
 }
 
 // LoadHardwareFromDirectories load plaforms from a set of directories
-func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error {
+func (pm *Builder) LoadHardwareFromDirectories(hardwarePaths paths.PathList) []error {
 	var merr []error
 	for _, path := range hardwarePaths {
 		merr = append(merr, pm.LoadHardwareFromDirectory(path)...)
@@ -54,7 +54,7 @@ func (pm *PackageManager) LoadHardwareFromDirectories(hardwarePaths paths.PathLi
 }
 
 // LoadHardwareFromDirectory read a plaform from the path passed as parameter
-func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
+func (pm *Builder) LoadHardwareFromDirectory(path *paths.Path) []error {
 	var merr []error
 	pm.log.Infof("Loading hardware from: %s", path)
 	if err := path.ToAbs(); err != nil {
@@ -81,7 +81,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
 		if p, err := properties.LoadFromPath(globalPlatformTxt); err != nil {
 			pm.log.WithError(err).Errorf("Error loading properties.")
 		} else {
-			pm.CustomGlobalProperties.Merge(p)
+			pm.packagesCustomGlobalProperties.Merge(p)
 		}
 	}
 
@@ -121,7 +121,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
 			architectureParentPath = packagerPath
 		}
 
-		targetPackage := pm.Packages.GetOrCreatePackage(packager)
+		targetPackage := pm.packages.GetOrCreatePackage(packager)
 		merr = append(merr, pm.loadPlatforms(targetPackage, architectureParentPath)...)
 
 		// Check if we have tools to load, the directory structure is as follows:
@@ -133,7 +133,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
 		}
 		// If the Package does not contain Platforms or Tools we remove it since does not contain anything valuable
 		if len(targetPackage.Platforms) == 0 && len(targetPackage.Tools) == 0 {
-			delete(pm.Packages, packager)
+			delete(pm.packages, packager)
 		}
 	}
 
@@ -143,7 +143,7 @@ func (pm *PackageManager) LoadHardwareFromDirectory(path *paths.Path) []error {
 // loadPlatforms load plaftorms from the specified directory assuming that they belongs
 // to the targetPackage object passed as parameter.
 // A list of gRPC Status error is returned for each Platform failed to load.
-func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error {
+func (pm *Builder) loadPlatforms(targetPackage *cores.Package, packageDir *paths.Path) []error {
 	pm.log.Infof("Loading package %s from: %s", targetPackage.Name, packageDir)
 
 	var merr []error
@@ -175,7 +175,7 @@ func (pm *PackageManager) loadPlatforms(targetPackage *cores.Package, packageDir
 // loadPlatform loads a single platform and all its installed releases given a platformPath.
 // platformPath must be a directory.
 // Returns a gRPC Status error in case of failures.
-func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architecture string, platformPath *paths.Path) error {
+func (pm *Builder) loadPlatform(targetPackage *cores.Package, architecture string, platformPath *paths.Path) error {
 	// This is not a platform
 	if platformPath.IsNotDir() {
 		return errors.New(tr("path is not a platform directory: %s", platformPath))
@@ -284,7 +284,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, architectur
 	return nil
 }
 
-func (pm *PackageManager) loadPlatformRelease(platform *cores.PlatformRelease, path *paths.Path) error {
+func (pm *Builder) loadPlatformRelease(platform *cores.PlatformRelease, path *paths.Path) error {
 	platform.InstallDir = path
 
 	// Some useful paths
@@ -445,14 +445,14 @@ func convertLegacyNetworkPatternToPluggableDiscovery(props *properties.Map, newT
 	return res
 }
 
-func (pm *PackageManager) loadProgrammer(programmerProperties *properties.Map) *cores.Programmer {
+func (pm *Builder) loadProgrammer(programmerProperties *properties.Map) *cores.Programmer {
 	return &cores.Programmer{
 		Name:       programmerProperties.Get("name"),
 		Properties: programmerProperties,
 	}
 }
 
-func (pm *PackageManager) loadBoards(platform *cores.PlatformRelease) error {
+func (pm *Builder) loadBoards(platform *cores.PlatformRelease) error {
 	if platform.InstallDir == nil {
 		return fmt.Errorf(tr("platform not installed"))
 	}
@@ -596,7 +596,7 @@ func convertUploadToolsToPluggableDiscovery(props *properties.Map) {
 
 // LoadToolsFromPackageDir loads a set of tools from the given toolsPath. The tools will be loaded
 // in the given *Package.
-func (pm *PackageManager) LoadToolsFromPackageDir(targetPackage *cores.Package, toolsPath *paths.Path) []error {
+func (pm *Builder) LoadToolsFromPackageDir(targetPackage *cores.Package, toolsPath *paths.Path) []error {
 	pm.log.Infof("Loading tools from dir: %s", toolsPath)
 
 	var merr []error
@@ -617,7 +617,7 @@ func (pm *PackageManager) LoadToolsFromPackageDir(targetPackage *cores.Package,
 	return merr
 }
 
-func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *paths.Path) error {
+func (pm *Builder) loadToolReleasesFromTool(tool *cores.Tool, toolPath *paths.Path) error {
 	toolVersions, err := toolPath.ReadDir()
 	if err != nil {
 		return err
@@ -634,7 +634,7 @@ func (pm *PackageManager) loadToolReleasesFromTool(tool *cores.Tool, toolPath *p
 	return nil
 }
 
-func (pm *PackageManager) loadToolReleaseFromDirectory(tool *cores.Tool, version *semver.RelaxedVersion, toolReleasePath *paths.Path) error {
+func (pm *Builder) loadToolReleaseFromDirectory(tool *cores.Tool, version *semver.RelaxedVersion, toolReleasePath *paths.Path) error {
 	if absToolReleasePath, err := toolReleasePath.Abs(); err != nil {
 		return errors.New(tr("error opening %s", absToolReleasePath))
 	} else if !absToolReleasePath.IsDir() {
@@ -648,7 +648,7 @@ func (pm *PackageManager) loadToolReleaseFromDirectory(tool *cores.Tool, version
 }
 
 // LoadToolsFromBundleDirectories FIXMEDOC
-func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []error {
+func (pm *Builder) LoadToolsFromBundleDirectories(dirs paths.PathList) []error {
 	var merr []error
 	for _, dir := range dirs {
 		if err := pm.LoadToolsFromBundleDirectory(dir); err != nil {
@@ -659,7 +659,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectories(dirs paths.PathList) []
 }
 
 // LoadToolsFromBundleDirectory FIXMEDOC
-func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) error {
+func (pm *Builder) LoadToolsFromBundleDirectory(toolsPath *paths.Path) error {
 	pm.log.Infof("Loading tools from bundle dir: %s", toolsPath)
 
 	// We scan toolsPath content to find a "builtin_tools_versions.txt", if such file exists
@@ -706,7 +706,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er
 		}
 
 		for packager, toolsData := range all.FirstLevelOf() {
-			targetPackage := pm.Packages.GetOrCreatePackage(packager)
+			targetPackage := pm.packages.GetOrCreatePackage(packager)
 
 			for toolName, toolVersion := range toolsData.AsMap() {
 				tool := targetPackage.GetOrCreateTool(toolName)
@@ -718,7 +718,7 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er
 		}
 	} else {
 		// otherwise load the tools inside the unnamed package
-		unnamedPackage := pm.Packages.GetOrCreatePackage("")
+		unnamedPackage := pm.packages.GetOrCreatePackage("")
 		pm.LoadToolsFromPackageDir(unnamedPackage, toolsPath)
 	}
 	return nil
@@ -729,18 +729,18 @@ func (pm *PackageManager) LoadToolsFromBundleDirectory(toolsPath *paths.Path) er
 // * A PluggableDiscovery instance can't be created
 // * Tools required by the PlatformRelease cannot be found
 // * Command line to start PluggableDiscovery has malformed or mismatched quotes
-func (pm *PackageManager) LoadDiscoveries() []error {
+func (pme *Explorer) LoadDiscoveries() []error {
 	var merr []error
-	for _, platform := range pm.InstalledPlatformReleases() {
-		merr = append(merr, pm.loadDiscoveries(platform)...)
+	for _, platform := range pme.InstalledPlatformReleases() {
+		merr = append(merr, pme.loadDiscoveries(platform)...)
 	}
-	merr = append(merr, pm.loadBuiltinDiscoveries()...)
+	merr = append(merr, pme.loadBuiltinDiscoveries()...)
 	return merr
 }
 
 // loadDiscovery loads the discovery tool with id, if it cannot be found a non-nil status is returned
-func (pm *PackageManager) loadDiscovery(id string) error {
-	tool := pm.GetTool(id)
+func (pme *Explorer) loadDiscovery(id string) error {
+	tool := pme.GetTool(id)
 	if tool == nil {
 		return errors.New(tr("discovery %s not found", id))
 	}
@@ -750,22 +750,22 @@ func (pm *PackageManager) loadDiscovery(id string) error {
 	}
 	discoveryPath := toolRelease.InstallDir.Join(tool.Name).String()
 	d := discovery.New(id, discoveryPath)
-	pm.discoveryManager.Add(d)
+	pme.discoveryManager.Add(d)
 	return nil
 }
 
 // loadBuiltinDiscoveries loads the discovery tools that are part of the builtin package
-func (pm *PackageManager) loadBuiltinDiscoveries() []error {
+func (pme *Explorer) loadBuiltinDiscoveries() []error {
 	var merr []error
 	for _, id := range []string{"builtin:serial-discovery", "builtin:mdns-discovery"} {
-		if err := pm.loadDiscovery(id); err != nil {
+		if err := pme.loadDiscovery(id); err != nil {
 			merr = append(merr, err)
 		}
 	}
 	return merr
 }
 
-func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []error {
+func (pme *Explorer) loadDiscoveries(release *cores.PlatformRelease) []error {
 	var merr []error
 	discoveryProperties := release.Properties.SubTree("pluggable_discovery")
 
@@ -784,7 +784,7 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []erro
 	//
 	// If both indexed and unindexed properties are found the unindexed are ignored
 	for _, id := range discoveryProperties.ExtractSubIndexLists("required") {
-		if err := pm.loadDiscovery(id); err != nil {
+		if err := pme.loadDiscovery(id); err != nil {
 			merr = append(merr, err)
 		}
 	}
@@ -799,7 +799,7 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []erro
 	var tools []*cores.ToolRelease
 	if len(discoveryIDs) > 0 {
 		var err error
-		tools, err = pm.FindToolsRequiredFromPlatformRelease(release)
+		tools, err = pme.FindToolsRequiredFromPlatformRelease(release)
 		if err != nil {
 			merr = append(merr, err)
 		}
@@ -827,7 +827,7 @@ func (pm *PackageManager) loadDiscoveries(release *cores.PlatformRelease) []erro
 			merr = append(merr, err)
 		} else {
 			d := discovery.New(discoveryID, cmdArgs...)
-			pm.discoveryManager.Add(d)
+			pme.discoveryManager.Add(d)
 		}
 	}
 
diff --git a/arduino/cores/packagemanager/loader_test.go b/arduino/cores/packagemanager/loader_test.go
index 2666bf62dd8..de9f5efa1ee 100644
--- a/arduino/cores/packagemanager/loader_test.go
+++ b/arduino/cores/packagemanager/loader_test.go
@@ -111,8 +111,8 @@ func TestLoadDiscoveries(t *testing.T) {
 	fakePath := paths.New("fake-path")
 
 	createTestPackageManager := func() *PackageManager {
-		packageManager := NewPackageManager(fakePath, fakePath, fakePath, fakePath, "test")
-		pack := packageManager.Packages.GetOrCreatePackage("arduino")
+		pmb := NewBuilder(fakePath, fakePath, fakePath, fakePath, "test")
+		pack := pmb.packages.GetOrCreatePackage("arduino")
 		// ble-discovery tool
 		tool := pack.GetOrCreateTool("ble-discovery")
 		toolRelease := tool.GetOrCreateRelease(semver.ParseRelaxed("1.0.0"))
@@ -131,75 +131,91 @@ func TestLoadDiscoveries(t *testing.T) {
 		release := platform.GetOrCreateRelease(semver.MustParse("1.0.0"))
 		release.InstallDir = fakePath
 
-		return packageManager
+		return pmb.Build()
 	}
 
-	packageManager := createTestPackageManager()
-	release := packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
-	release.Properties = properties.NewFromHashmap(map[string]string{
-		"pluggable_discovery.required": "arduino:ble-discovery",
-	})
-
-	err := packageManager.LoadDiscoveries()
-	require.Len(t, err, 2)
-	require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
-	require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
-	discoveries := packageManager.DiscoveryManager().IDs()
-	require.Len(t, discoveries, 1)
-	require.Contains(t, discoveries, "arduino:ble-discovery")
-
-	packageManager = createTestPackageManager()
-	release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
-	release.Properties = properties.NewFromHashmap(map[string]string{
-		"pluggable_discovery.required.0": "arduino:ble-discovery",
-		"pluggable_discovery.required.1": "arduino:serial-discovery",
-	})
-
-	err = packageManager.LoadDiscoveries()
-	require.Len(t, err, 2)
-	require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
-	require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
-	discoveries = packageManager.DiscoveryManager().IDs()
-	require.Len(t, discoveries, 2)
-	require.Contains(t, discoveries, "arduino:ble-discovery")
-	require.Contains(t, discoveries, "arduino:serial-discovery")
-
-	packageManager = createTestPackageManager()
-	release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
-	release.Properties = properties.NewFromHashmap(map[string]string{
-		"pluggable_discovery.required.0":     "arduino:ble-discovery",
-		"pluggable_discovery.required.1":     "arduino:serial-discovery",
-		"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
-	})
-
-	err = packageManager.LoadDiscoveries()
-	require.Len(t, err, 2)
-	require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
-	require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
-	discoveries = packageManager.DiscoveryManager().IDs()
-	require.Len(t, discoveries, 3)
-	require.Contains(t, discoveries, "arduino:ble-discovery")
-	require.Contains(t, discoveries, "arduino:serial-discovery")
-	require.Contains(t, discoveries, "teensy")
-
-	packageManager = createTestPackageManager()
-	release = packageManager.Packages["arduino"].Platforms["avr"].Releases["1.0.0"]
-	release.Properties = properties.NewFromHashmap(map[string]string{
-		"pluggable_discovery.required":       "arduino:some-discovery",
-		"pluggable_discovery.required.0":     "arduino:ble-discovery",
-		"pluggable_discovery.required.1":     "arduino:serial-discovery",
-		"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
-	})
-
-	err = packageManager.LoadDiscoveries()
-	require.Len(t, err, 2)
-	require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
-	require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
-	discoveries = packageManager.DiscoveryManager().IDs()
-	require.Len(t, discoveries, 3)
-	require.Contains(t, discoveries, "arduino:ble-discovery")
-	require.Contains(t, discoveries, "arduino:serial-discovery")
-	require.Contains(t, discoveries, "teensy")
+	{
+		pm := createTestPackageManager()
+		release := pm.packages["arduino"].Platforms["avr"].Releases["1.0.0"]
+		release.Properties = properties.NewFromHashmap(map[string]string{
+			"pluggable_discovery.required": "arduino:ble-discovery",
+		})
+
+		pme, pmeRelease := pm.NewExplorer()
+		err := pme.LoadDiscoveries()
+		require.Len(t, err, 2)
+		require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
+		require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
+		discoveries := pme.DiscoveryManager().IDs()
+		require.Len(t, discoveries, 1)
+		require.Contains(t, discoveries, "arduino:ble-discovery")
+		pmeRelease()
+	}
+
+	{
+		pm := createTestPackageManager()
+		release := pm.packages["arduino"].Platforms["avr"].Releases["1.0.0"]
+		release.Properties = properties.NewFromHashmap(map[string]string{
+			"pluggable_discovery.required.0": "arduino:ble-discovery",
+			"pluggable_discovery.required.1": "arduino:serial-discovery",
+		})
+
+		pme, pmeRelease := pm.NewExplorer()
+		err := pme.LoadDiscoveries()
+		require.Len(t, err, 2)
+		require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
+		require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
+		discoveries := pme.DiscoveryManager().IDs()
+		require.Len(t, discoveries, 2)
+		require.Contains(t, discoveries, "arduino:ble-discovery")
+		require.Contains(t, discoveries, "arduino:serial-discovery")
+		pmeRelease()
+	}
+
+	{
+		pm := createTestPackageManager()
+		release := pm.packages["arduino"].Platforms["avr"].Releases["1.0.0"]
+		release.Properties = properties.NewFromHashmap(map[string]string{
+			"pluggable_discovery.required.0":     "arduino:ble-discovery",
+			"pluggable_discovery.required.1":     "arduino:serial-discovery",
+			"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
+		})
+
+		pme, pmeRelease := pm.NewExplorer()
+		err := pme.LoadDiscoveries()
+		require.Len(t, err, 2)
+		require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
+		require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
+		discoveries := pme.DiscoveryManager().IDs()
+		require.Len(t, discoveries, 3)
+		require.Contains(t, discoveries, "arduino:ble-discovery")
+		require.Contains(t, discoveries, "arduino:serial-discovery")
+		require.Contains(t, discoveries, "teensy")
+		pmeRelease()
+	}
+
+	{
+		pm := createTestPackageManager()
+		release := pm.packages["arduino"].Platforms["avr"].Releases["1.0.0"]
+		release.Properties = properties.NewFromHashmap(map[string]string{
+			"pluggable_discovery.required":       "arduino:some-discovery",
+			"pluggable_discovery.required.0":     "arduino:ble-discovery",
+			"pluggable_discovery.required.1":     "arduino:serial-discovery",
+			"pluggable_discovery.teensy.pattern": "\"{runtime.tools.teensy_ports.path}/hardware/tools/teensy_ports\" -J2",
+		})
+
+		pme, pmeRelease := pm.NewExplorer()
+		err := pme.LoadDiscoveries()
+		require.Len(t, err, 2)
+		require.Equal(t, err[0].Error(), "discovery builtin:serial-discovery not found")
+		require.Equal(t, err[1].Error(), "discovery builtin:mdns-discovery not found")
+		discoveries := pme.DiscoveryManager().IDs()
+		require.Len(t, discoveries, 3)
+		require.Contains(t, discoveries, "arduino:ble-discovery")
+		require.Contains(t, discoveries, "arduino:serial-discovery")
+		require.Contains(t, discoveries, "teensy")
+		pmeRelease()
+	}
 }
 
 func TestConvertUploadToolsToPluggableDiscovery(t *testing.T) {
diff --git a/arduino/cores/packagemanager/package_manager.go b/arduino/cores/packagemanager/package_manager.go
index 401c2407dfb..ad23629840d 100644
--- a/arduino/cores/packagemanager/package_manager.go
+++ b/arduino/cores/packagemanager/package_manager.go
@@ -20,6 +20,7 @@ import (
 	"net/url"
 	"path"
 	"strings"
+	"sync"
 
 	"github.com/arduino/arduino-cli/arduino/cores"
 	"github.com/arduino/arduino-cli/arduino/cores/packageindex"
@@ -38,67 +39,145 @@ import (
 // The manager also keeps track of the status of the Packages (their Platform Releases, actually)
 // installed in the system.
 type PackageManager struct {
-	log                    logrus.FieldLogger
-	Packages               cores.Packages
-	IndexDir               *paths.Path
-	PackagesDir            *paths.Path
-	DownloadDir            *paths.Path
-	tempDir                *paths.Path
-	CustomGlobalProperties *properties.Map
-	profile                *sketch.Profile
-	discoveryManager       *discoverymanager.DiscoveryManager
-	userAgent              string
-}
+	packagesLock                   sync.RWMutex // Protects packages and packagesCustomGlobalProperties
+	packages                       cores.Packages
+	packagesCustomGlobalProperties *properties.Map
+
+	log              logrus.FieldLogger
+	IndexDir         *paths.Path
+	PackagesDir      *paths.Path
+	DownloadDir      *paths.Path
+	tempDir          *paths.Path
+	profile          *sketch.Profile
+	discoveryManager *discoverymanager.DiscoveryManager
+	userAgent        string
+}
+
+// Builder is used to create a new PackageManager. The builder
+// has methods to load platforms and tools to actually build the PackageManager.
+// Once the PackageManager is built, it cannot be changed anymore.
+type Builder PackageManager
+
+// Explorer is used to query the PackageManager. When used it holds
+// a read-only lock on the PackageManager that must be released when the
+// job is completed.
+type Explorer PackageManager
 
 var tr = i18n.Tr
 
-// NewPackageManager returns a new instance of the PackageManager
-func NewPackageManager(indexDir, packagesDir, downloadDir, tempDir *paths.Path, userAgent string) *PackageManager {
-	return &PackageManager{
-		log:                    logrus.StandardLogger(),
-		Packages:               cores.NewPackages(),
-		IndexDir:               indexDir,
-		PackagesDir:            packagesDir,
-		DownloadDir:            downloadDir,
-		tempDir:                tempDir,
-		CustomGlobalProperties: properties.NewMap(),
-		discoveryManager:       discoverymanager.New(),
-		userAgent:              userAgent,
-	}
+// NewBuilder returns a new Builder
+func NewBuilder(indexDir, packagesDir, downloadDir, tempDir *paths.Path, userAgent string) *Builder {
+	return &Builder{
+		log:                            logrus.StandardLogger(),
+		packages:                       cores.NewPackages(),
+		IndexDir:                       indexDir,
+		PackagesDir:                    packagesDir,
+		DownloadDir:                    downloadDir,
+		tempDir:                        tempDir,
+		packagesCustomGlobalProperties: properties.NewMap(),
+		discoveryManager:               discoverymanager.New(),
+		userAgent:                      userAgent,
+	}
+}
+
+// BuildIntoExistingPackageManager will overwrite the given PackageManager instead
+// of building a new one.
+func (pmb *Builder) BuildIntoExistingPackageManager(target *PackageManager) {
+	target.packagesLock.Lock()
+	defer target.packagesLock.Unlock()
+	target.log = pmb.log
+	target.packages = pmb.packages
+	target.IndexDir = pmb.IndexDir
+	target.PackagesDir = pmb.PackagesDir
+	target.DownloadDir = pmb.DownloadDir
+	target.tempDir = pmb.tempDir
+	target.packagesCustomGlobalProperties = pmb.packagesCustomGlobalProperties
+	target.profile = pmb.profile
+	target.discoveryManager = pmb.discoveryManager
+	target.userAgent = pmb.userAgent
+}
+
+// Build builds a new PackageManager.
+func (pmb *Builder) Build() *PackageManager {
+	res := &PackageManager{}
+	pmb.BuildIntoExistingPackageManager(res)
+	return res
+}
+
+// NewBuilder creates a Builder with the same configuration
+// of this PackageManager. A "commit" function callback is returned: calling
+// this function will make the builder write the new configuration into this
+// PackageManager.
+func (pm *PackageManager) NewBuilder() (builder *Builder, commit func()) {
+	pmb := NewBuilder(pm.IndexDir, pm.PackagesDir, pm.DownloadDir, pm.tempDir, pm.userAgent)
+	return pmb, func() {
+		pmb.BuildIntoExistingPackageManager(pm)
+	}
+}
+
+// NewExplorer creates an Explorer for this PackageManager.
+// The Explorer will keep a read-lock on the underlying PackageManager,
+// the user must call the "release" callback function to release the lock
+// when the Explorer is no more needed.
+func (pm *PackageManager) NewExplorer() (explorer *Explorer, release func()) {
+	pm.packagesLock.RLock()
+	return &Explorer{
+		log:                            pm.log,
+		packages:                       pm.packages,
+		IndexDir:                       pm.IndexDir,
+		PackagesDir:                    pm.PackagesDir,
+		DownloadDir:                    pm.DownloadDir,
+		tempDir:                        pm.tempDir,
+		packagesCustomGlobalProperties: pm.packagesCustomGlobalProperties,
+		profile:                        pm.profile,
+		discoveryManager:               pm.discoveryManager,
+		userAgent:                      pm.userAgent,
+	}, pm.packagesLock.RUnlock
 }
 
 // GetProfile returns the active profile for this package manager, or nil if no profile is selected.
-func (pm *PackageManager) GetProfile() *sketch.Profile {
-	return pm.profile
+func (pme *Explorer) GetProfile() *sketch.Profile {
+	return pme.profile
 }
 
 // GetEnvVarsForSpawnedProcess produces a set of environment variables that
 // must be sent to all processes spawned from the arduino-cli.
-func (pm *PackageManager) GetEnvVarsForSpawnedProcess() []string {
-	if pm == nil {
+func (pme *Explorer) GetEnvVarsForSpawnedProcess() []string {
+	if pme == nil {
 		return nil
 	}
 	return []string{
-		"ARDUINO_USER_AGENT=" + pm.userAgent,
+		"ARDUINO_USER_AGENT=" + pme.userAgent,
 	}
 }
 
-// Clear resets the PackageManager to its initial state
-func (pm *PackageManager) Clear() {
-	pm.Packages = cores.NewPackages()
-	pm.CustomGlobalProperties = properties.NewMap()
-	pm.discoveryManager.Clear()
+// DiscoveryManager returns the DiscoveryManager in use by this PackageManager
+func (pme *Explorer) DiscoveryManager() *discoverymanager.DiscoveryManager {
+	return pme.discoveryManager
 }
 
-// DiscoveryManager returns the DiscoveryManager in use by this PackageManager
-func (pm *PackageManager) DiscoveryManager() *discoverymanager.DiscoveryManager {
-	return pm.discoveryManager
+// GetOrCreatePackage returns the specified Package or creates an empty one
+// filling all the cross-references
+func (pmb *Builder) GetOrCreatePackage(packager string) *cores.Package {
+	return pmb.packages.GetOrCreatePackage(packager)
+}
+
+// GetPackages returns the internal packages structure for direct usage.
+// Deprecated: do not access packages directly, but use specific Explorer methods when possible.
+func (pme *Explorer) GetPackages() cores.Packages {
+	return pme.packages
+}
+
+// GetCustomGlobalProperties returns the user defined custom global
+// properties for installed platforms.
+func (pme *Explorer) GetCustomGlobalProperties() *properties.Map {
+	return pme.packagesCustomGlobalProperties
 }
 
 // FindPlatformReleaseProvidingBoardsWithVidPid FIXMEDOC
-func (pm *PackageManager) FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid string) []*cores.PlatformRelease {
+func (pme *Explorer) FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid string) []*cores.PlatformRelease {
 	res := []*cores.PlatformRelease{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, targetPlatform := range targetPackage.Platforms {
 			platformRelease := targetPlatform.GetLatestRelease()
 			if platformRelease == nil {
@@ -116,11 +195,11 @@ func (pm *PackageManager) FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid
 }
 
 // FindBoardsWithVidPid FIXMEDOC
-func (pm *PackageManager) FindBoardsWithVidPid(vid, pid string) []*cores.Board {
+func (pme *Explorer) FindBoardsWithVidPid(vid, pid string) []*cores.Board {
 	res := []*cores.Board{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, targetPlatform := range targetPackage.Platforms {
-			if platform := pm.GetInstalledPlatformRelease(targetPlatform); platform != nil {
+			if platform := pme.GetInstalledPlatformRelease(targetPlatform); platform != nil {
 				for _, board := range platform.Boards {
 					if board.HasUsbID(vid, pid) {
 						res = append(res, board)
@@ -133,11 +212,11 @@ func (pm *PackageManager) FindBoardsWithVidPid(vid, pid string) []*cores.Board {
 }
 
 // FindBoardsWithID FIXMEDOC
-func (pm *PackageManager) FindBoardsWithID(id string) []*cores.Board {
+func (pme *Explorer) FindBoardsWithID(id string) []*cores.Board {
 	res := []*cores.Board{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, targetPlatform := range targetPackage.Platforms {
-			if platform := pm.GetInstalledPlatformRelease(targetPlatform); platform != nil {
+			if platform := pme.GetInstalledPlatformRelease(targetPlatform); platform != nil {
 				for _, board := range platform.Boards {
 					if board.BoardID == id {
 						res = append(res, board)
@@ -150,13 +229,13 @@ func (pm *PackageManager) FindBoardsWithID(id string) []*cores.Board {
 }
 
 // FindBoardWithFQBN returns the board identified by the fqbn, or an error
-func (pm *PackageManager) FindBoardWithFQBN(fqbnIn string) (*cores.Board, error) {
+func (pme *Explorer) FindBoardWithFQBN(fqbnIn string) (*cores.Board, error) {
 	fqbn, err := cores.ParseFQBN(fqbnIn)
 	if err != nil {
 		return nil, fmt.Errorf(tr("parsing fqbn: %s"), err)
 	}
 
-	_, _, board, _, _, err := pm.ResolveFQBN(fqbn)
+	_, _, board, _, _, err := pme.ResolveFQBN(fqbn)
 	return board, err
 }
 
@@ -179,12 +258,12 @@ func (pm *PackageManager) FindBoardWithFQBN(fqbnIn string) (*cores.Board, error)
 //
 // In case of error the partial results found in the meantime are
 // returned together with the error.
-func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
+func (pme *Explorer) ResolveFQBN(fqbn *cores.FQBN) (
 	*cores.Package, *cores.PlatformRelease, *cores.Board,
 	*properties.Map, *cores.PlatformRelease, error) {
 
 	// Find package
-	targetPackage := pm.Packages[fqbn.Package]
+	targetPackage := pme.packages[fqbn.Package]
 	if targetPackage == nil {
 		return nil, nil, nil, nil, nil,
 			fmt.Errorf(tr("unknown package %s"), fqbn.Package)
@@ -196,7 +275,7 @@ func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
 		return targetPackage, nil, nil, nil, nil,
 			fmt.Errorf(tr("unknown platform %s:%s"), targetPackage, fqbn.PlatformArch)
 	}
-	platformRelease := pm.GetInstalledPlatformRelease(platform)
+	platformRelease := pme.GetInstalledPlatformRelease(platform)
 	if platformRelease == nil {
 		return targetPackage, nil, nil, nil, nil,
 			fmt.Errorf(tr("platform %s is not installed"), platform)
@@ -221,7 +300,7 @@ func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
 	coreParts := strings.Split(buildProperties.Get("build.core"), ":")
 	if len(coreParts) > 1 {
 		referredPackage := coreParts[0]
-		buildPackage := pm.Packages[referredPackage]
+		buildPackage := pme.packages[referredPackage]
 		if buildPackage == nil {
 			return targetPackage, platformRelease, board, buildProperties, nil,
 				fmt.Errorf(tr("missing package %[1]s referenced by board %[2]s"), referredPackage, fqbn)
@@ -231,7 +310,7 @@ func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
 			return targetPackage, platformRelease, board, buildProperties, nil,
 				fmt.Errorf(tr("missing platform %[1]s:%[2]s referenced by board %[3]s"), referredPackage, fqbn.PlatformArch, fqbn)
 		}
-		buildPlatformRelease = pm.GetInstalledPlatformRelease(buildPlatform)
+		buildPlatformRelease = pme.GetInstalledPlatformRelease(buildPlatform)
 		if buildPlatformRelease == nil {
 			return targetPackage, platformRelease, board, buildProperties, nil,
 				fmt.Errorf(tr("missing platform release %[1]s:%[2]s referenced by board %[3]s"), referredPackage, fqbn.PlatformArch, fqbn)
@@ -243,12 +322,12 @@ func (pm *PackageManager) ResolveFQBN(fqbn *cores.FQBN) (
 }
 
 // LoadPackageIndex loads a package index by looking up the local cached file from the specified URL
-func (pm *PackageManager) LoadPackageIndex(URL *url.URL) error {
+func (pmb *Builder) LoadPackageIndex(URL *url.URL) error {
 	indexFileName := path.Base(URL.Path)
 	if strings.HasSuffix(indexFileName, ".tar.bz2") {
 		indexFileName = strings.TrimSuffix(indexFileName, ".tar.bz2") + ".json"
 	}
-	indexPath := pm.IndexDir.Join(indexFileName)
+	indexPath := pmb.IndexDir.Join(indexFileName)
 	index, err := packageindex.LoadIndex(indexPath)
 	if err != nil {
 		return fmt.Errorf(tr("loading json index file %[1]s: %[2]s"), indexPath, err)
@@ -258,27 +337,27 @@ func (pm *PackageManager) LoadPackageIndex(URL *url.URL) error {
 		p.URL = URL.String()
 	}
 
-	index.MergeIntoPackages(pm.Packages)
+	index.MergeIntoPackages(pmb.packages)
 	return nil
 }
 
 // LoadPackageIndexFromFile load a package index from the specified file
-func (pm *PackageManager) LoadPackageIndexFromFile(indexPath *paths.Path) (*packageindex.Index, error) {
+func (pmb *Builder) LoadPackageIndexFromFile(indexPath *paths.Path) (*packageindex.Index, error) {
 	index, err := packageindex.LoadIndex(indexPath)
 	if err != nil {
 		return nil, fmt.Errorf(tr("loading json index file %[1]s: %[2]s"), indexPath, err)
 	}
 
-	index.MergeIntoPackages(pm.Packages)
+	index.MergeIntoPackages(pmb.packages)
 	return index, nil
 }
 
 // Package looks for the Package with the given name, returning a structure
 // able to perform further operations on that given resource
-func (pm *PackageManager) Package(name string) *PackageActions {
+func (pme *Explorer) Package(name string) *PackageActions {
 	//TODO: perhaps these 2 structure should be merged? cores.Packages vs pkgmgr??
 	var err error
-	thePackage := pm.Packages[name]
+	thePackage := pme.packages[name]
 	if thePackage == nil {
 		err = fmt.Errorf(tr("package '%s' not found"), name)
 	}
@@ -379,25 +458,25 @@ func (tr *ToolReleaseActions) Get() (*cores.ToolRelease, error) {
 }
 
 // GetInstalledPlatformRelease returns the PlatformRelease installed (it is chosen)
-func (pm *PackageManager) GetInstalledPlatformRelease(platform *cores.Platform) *cores.PlatformRelease {
+func (pme *Explorer) GetInstalledPlatformRelease(platform *cores.Platform) *cores.PlatformRelease {
 	releases := platform.GetAllInstalled()
 	if len(releases) == 0 {
 		return nil
 	}
 
 	debug := func(msg string, pl *cores.PlatformRelease) {
-		pm.log.WithField("bundle", pl.IsIDEBundled).
+		pme.log.WithField("bundle", pl.IsIDEBundled).
 			WithField("version", pl.Version).
-			WithField("managed", pm.IsManagedPlatformRelease(pl)).
+			WithField("managed", pme.IsManagedPlatformRelease(pl)).
 			Debugf("%s: %s", msg, pl)
 	}
 
 	best := releases[0]
-	bestIsManaged := pm.IsManagedPlatformRelease(best)
+	bestIsManaged := pme.IsManagedPlatformRelease(best)
 	debug("current best", best)
 
 	for _, candidate := range releases[1:] {
-		candidateIsManaged := pm.IsManagedPlatformRelease(candidate)
+		candidateIsManaged := pme.IsManagedPlatformRelease(candidate)
 		debug("candidate", candidate)
 		// TODO: Disentangle this algorithm and make it more straightforward
 		if bestIsManaged == candidateIsManaged {
@@ -420,9 +499,9 @@ func (pm *PackageManager) GetInstalledPlatformRelease(platform *cores.Platform)
 }
 
 // GetAllInstalledToolsReleases FIXMEDOC
-func (pm *PackageManager) GetAllInstalledToolsReleases() []*cores.ToolRelease {
+func (pme *Explorer) GetAllInstalledToolsReleases() []*cores.ToolRelease {
 	tools := []*cores.ToolRelease{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, tool := range targetPackage.Tools {
 			for _, release := range tool.Releases {
 				if release.IsInstalled() {
@@ -436,9 +515,9 @@ func (pm *PackageManager) GetAllInstalledToolsReleases() []*cores.ToolRelease {
 
 // InstalledPlatformReleases returns all installed PlatformReleases. This function is
 // useful to range all PlatformReleases in for loops.
-func (pm *PackageManager) InstalledPlatformReleases() []*cores.PlatformRelease {
+func (pme *Explorer) InstalledPlatformReleases() []*cores.PlatformRelease {
 	platforms := []*cores.PlatformRelease{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, platform := range targetPackage.Platforms {
 			platforms = append(platforms, platform.GetAllInstalled()...)
 		}
@@ -448,9 +527,9 @@ func (pm *PackageManager) InstalledPlatformReleases() []*cores.PlatformRelease {
 
 // InstalledBoards returns all installed Boards. This function is useful to range
 // all Boards in for loops.
-func (pm *PackageManager) InstalledBoards() []*cores.Board {
+func (pme *Explorer) InstalledBoards() []*cores.Board {
 	boards := []*cores.Board{}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, platform := range targetPackage.Platforms {
 			for _, release := range platform.GetAllInstalled() {
 				for _, board := range release.Boards {
@@ -464,14 +543,14 @@ func (pm *PackageManager) InstalledBoards() []*cores.Board {
 
 // FindToolsRequiredFromPlatformRelease returns a list of ToolReleases needed by the specified PlatformRelease.
 // If a ToolRelease is not found return an error
-func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.PlatformRelease) ([]*cores.ToolRelease, error) {
-	pm.log.Infof("Searching tools required for platform %s", platform)
+func (pme *Explorer) FindToolsRequiredFromPlatformRelease(platform *cores.PlatformRelease) ([]*cores.ToolRelease, error) {
+	pme.log.Infof("Searching tools required for platform %s", platform)
 
 	// maps "PACKAGER:TOOL" => ToolRelease
 	foundTools := map[string]*cores.ToolRelease{}
 	// A Platform may not specify required tools (because it's a platform that comes from a
 	// user/hardware dir without a package_index.json) then add all available tools
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, tool := range targetPackage.Tools {
 			rel := tool.GetLatestInstalled()
 			if rel != nil {
@@ -483,8 +562,8 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
 	requiredTools := []*cores.ToolRelease{}
 	platform.ToolDependencies.Sort()
 	for _, toolDep := range platform.ToolDependencies {
-		pm.log.WithField("tool", toolDep).Infof("Required tool")
-		tool := pm.FindToolDependency(toolDep)
+		pme.log.WithField("tool", toolDep).Infof("Required tool")
+		tool := pme.FindToolDependency(toolDep)
 		if tool == nil {
 			return nil, fmt.Errorf(tr("tool release not found: %s"), toolDep)
 		}
@@ -494,8 +573,8 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
 
 	platform.DiscoveryDependencies.Sort()
 	for _, discoveryDep := range platform.DiscoveryDependencies {
-		pm.log.WithField("discovery", discoveryDep).Infof("Required discovery")
-		tool := pm.FindDiscoveryDependency(discoveryDep)
+		pme.log.WithField("discovery", discoveryDep).Infof("Required discovery")
+		tool := pme.FindDiscoveryDependency(discoveryDep)
 		if tool == nil {
 			return nil, fmt.Errorf(tr("discovery release not found: %s"), discoveryDep)
 		}
@@ -505,8 +584,8 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
 
 	platform.MonitorDependencies.Sort()
 	for _, monitorDep := range platform.MonitorDependencies {
-		pm.log.WithField("monitor", monitorDep).Infof("Required monitor")
-		tool := pm.FindMonitorDependency(monitorDep)
+		pme.log.WithField("monitor", monitorDep).Infof("Required monitor")
+		tool := pme.FindMonitorDependency(monitorDep)
 		if tool == nil {
 			return nil, fmt.Errorf(tr("monitor release not found: %s"), monitorDep)
 		}
@@ -521,12 +600,12 @@ func (pm *PackageManager) FindToolsRequiredFromPlatformRelease(platform *cores.P
 }
 
 // GetTool searches for tool in all packages and platforms.
-func (pm *PackageManager) GetTool(toolID string) *cores.Tool {
+func (pme *Explorer) GetTool(toolID string) *cores.Tool {
 	split := strings.Split(toolID, ":")
 	if len(split) != 2 {
 		return nil
 	}
-	if pack, ok := pm.Packages[split[0]]; !ok {
+	if pack, ok := pme.packages[split[0]]; !ok {
 		return nil
 	} else if tool, ok := pack.Tools[split[1]]; !ok {
 		return nil
@@ -536,8 +615,8 @@ func (pm *PackageManager) GetTool(toolID string) *cores.Tool {
 }
 
 // FindToolsRequiredForBoard FIXMEDOC
-func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.ToolRelease, error) {
-	pm.log.Infof("Searching tools required for board %s", board)
+func (pme *Explorer) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.ToolRelease, error) {
+	pme.log.Infof("Searching tools required for board %s", board)
 
 	// core := board.Properties["build.core"]
 	platform := board.PlatformRelease
@@ -547,7 +626,7 @@ func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*core
 
 	// a Platform may not specify required tools (because it's a platform that comes from a
 	// user/hardware dir without a package_index.json) then add all available tools
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.packages {
 		for _, tool := range targetPackage.Tools {
 			rel := tool.GetLatestInstalled()
 			if rel != nil {
@@ -560,8 +639,8 @@ func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*core
 	requiredTools := []*cores.ToolRelease{}
 	platform.ToolDependencies.Sort()
 	for _, toolDep := range platform.ToolDependencies {
-		pm.log.WithField("tool", toolDep).Infof("Required tool")
-		tool := pm.FindToolDependency(toolDep)
+		pme.log.WithField("tool", toolDep).Infof("Required tool")
+		tool := pme.FindToolDependency(toolDep)
 		if tool == nil {
 			return nil, fmt.Errorf(tr("tool release not found: %s"), toolDep)
 		}
@@ -577,8 +656,8 @@ func (pm *PackageManager) FindToolsRequiredForBoard(board *cores.Board) ([]*core
 
 // FindToolDependency returns the ToolRelease referenced by the ToolDependency or nil if
 // the referenced tool doesn't exists.
-func (pm *PackageManager) FindToolDependency(dep *cores.ToolDependency) *cores.ToolRelease {
-	toolRelease, err := pm.Package(dep.ToolPackager).Tool(dep.ToolName).Release(dep.ToolVersion).Get()
+func (pme *Explorer) FindToolDependency(dep *cores.ToolDependency) *cores.ToolRelease {
+	toolRelease, err := pme.Package(dep.ToolPackager).Tool(dep.ToolName).Release(dep.ToolVersion).Get()
 	if err != nil {
 		return nil
 	}
@@ -587,8 +666,8 @@ func (pm *PackageManager) FindToolDependency(dep *cores.ToolDependency) *cores.T
 
 // FindDiscoveryDependency returns the ToolRelease referenced by the DiscoveryDepenency or nil if
 // the referenced discovery doesn't exists.
-func (pm *PackageManager) FindDiscoveryDependency(discovery *cores.DiscoveryDependency) *cores.ToolRelease {
-	if pack := pm.Packages[discovery.Packager]; pack == nil {
+func (pme *Explorer) FindDiscoveryDependency(discovery *cores.DiscoveryDependency) *cores.ToolRelease {
+	if pack := pme.packages[discovery.Packager]; pack == nil {
 		return nil
 	} else if toolRelease := pack.Tools[discovery.Name]; toolRelease == nil {
 		return nil
@@ -599,8 +678,8 @@ func (pm *PackageManager) FindDiscoveryDependency(discovery *cores.DiscoveryDepe
 
 // FindMonitorDependency returns the ToolRelease referenced by the MonitorDepenency or nil if
 // the referenced monitor doesn't exists.
-func (pm *PackageManager) FindMonitorDependency(discovery *cores.MonitorDependency) *cores.ToolRelease {
-	if pack := pm.Packages[discovery.Packager]; pack == nil {
+func (pme *Explorer) FindMonitorDependency(discovery *cores.MonitorDependency) *cores.ToolRelease {
+	if pack := pme.packages[discovery.Packager]; pack == nil {
 		return nil
 	} else if toolRelease := pack.Tools[discovery.Name]; toolRelease == nil {
 		return nil
diff --git a/arduino/cores/packagemanager/package_manager_test.go b/arduino/cores/packagemanager/package_manager_test.go
index 9cb1509dca0..9dd746d5b12 100644
--- a/arduino/cores/packagemanager/package_manager_test.go
+++ b/arduino/cores/packagemanager/package_manager_test.go
@@ -37,15 +37,17 @@ var dataDir1 = paths.New("testdata", "data_dir_1")
 var extraHardware = paths.New("testdata", "extra_hardware")
 
 func TestFindBoardWithFQBN(t *testing.T) {
-	pm := packagemanager.NewPackageManager(customHardware, customHardware, customHardware, customHardware, "test")
-	pm.LoadHardwareFromDirectory(customHardware)
-
-	board, err := pm.FindBoardWithFQBN("arduino:avr:uno")
+	pmb := packagemanager.NewBuilder(customHardware, customHardware, customHardware, customHardware, "test")
+	pmb.LoadHardwareFromDirectory(customHardware)
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+	board, err := pme.FindBoardWithFQBN("arduino:avr:uno")
 	require.Nil(t, err)
 	require.NotNil(t, board)
 	require.Equal(t, board.Name(), "Arduino/Genuino Uno")
 
-	board, err = pm.FindBoardWithFQBN("arduino:avr:mega")
+	board, err = pme.FindBoardWithFQBN("arduino:avr:mega")
 	require.Nil(t, err)
 	require.NotNil(t, board)
 	require.Equal(t, board.Name(), "Arduino/Genuino Mega or Mega 2560")
@@ -53,18 +55,21 @@ func TestFindBoardWithFQBN(t *testing.T) {
 
 func TestResolveFQBN(t *testing.T) {
 	// Pass nil, since these paths are only used for installing
-	pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "test")
+	pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
 	// Hardware from main packages directory
-	pm.LoadHardwareFromDirectory(dataDir1.Join("packages"))
+	pmb.LoadHardwareFromDirectory(dataDir1.Join("packages"))
 	// This contains the arduino:avr core
-	pm.LoadHardwareFromDirectory(customHardware)
+	pmb.LoadHardwareFromDirectory(customHardware)
 	// This contains the referenced:avr core
-	pm.LoadHardwareFromDirectory(extraHardware)
+	pmb.LoadHardwareFromDirectory(extraHardware)
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
 
 	fqbn, err := cores.ParseFQBN("arduino:avr:uno")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err := pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err := pme.ResolveFQBN(fqbn)
 	require.Nil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -78,7 +83,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("arduino:avr:mega")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.Nil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -93,7 +98,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("referenced:avr:uno")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.Nil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -111,7 +116,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("referenced:samd:feather_m0")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.Nil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -128,7 +133,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_package")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.NotNil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -143,7 +148,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_platform")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.NotNil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -159,7 +164,7 @@ func TestResolveFQBN(t *testing.T) {
 	fqbn, err = cores.ParseFQBN("referenced:avr:dummy_invalid_core")
 	require.Nil(t, err)
 	require.NotNil(t, fqbn)
-	pkg, platformRelease, board, props, buildPlatformRelease, err = pm.ResolveFQBN(fqbn)
+	pkg, platformRelease, board, props, buildPlatformRelease, err = pme.ResolveFQBN(fqbn)
 	require.Nil(t, err)
 	require.Equal(t, pkg, platformRelease.Platform.Package)
 	require.NotNil(t, platformRelease)
@@ -174,10 +179,13 @@ func TestResolveFQBN(t *testing.T) {
 }
 
 func TestBoardOptionsFunctions(t *testing.T) {
-	pm := packagemanager.NewPackageManager(customHardware, customHardware, customHardware, customHardware, "test")
-	pm.LoadHardwareFromDirectory(customHardware)
+	pmb := packagemanager.NewBuilder(customHardware, customHardware, customHardware, customHardware, "test")
+	pmb.LoadHardwareFromDirectory(customHardware)
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
 
-	nano, err := pm.FindBoardWithFQBN("arduino:avr:nano")
+	nano, err := pme.FindBoardWithFQBN("arduino:avr:nano")
 	require.Nil(t, err)
 	require.NotNil(t, nano)
 	require.Equal(t, nano.Name(), "Arduino Nano")
@@ -193,7 +201,7 @@ func TestBoardOptionsFunctions(t *testing.T) {
 	expectedNanoCPUValues.Set("atmega168", "ATmega168")
 	require.EqualValues(t, expectedNanoCPUValues, nanoCPUValues)
 
-	esp8266, err := pm.FindBoardWithFQBN("esp8266:esp8266:generic")
+	esp8266, err := pme.FindBoardWithFQBN("esp8266:esp8266:generic")
 	require.Nil(t, err)
 	require.NotNil(t, esp8266)
 	require.Equal(t, esp8266.Name(), "Generic ESP8266 Module")
@@ -213,7 +221,7 @@ func TestBoardOptionsFunctions(t *testing.T) {
 func TestFindToolsRequiredForBoard(t *testing.T) {
 	os.Setenv("ARDUINO_DATA_DIR", dataDir1.String())
 	configuration.Settings = configuration.Init("")
-	pm := packagemanager.NewPackageManager(
+	pmb := packagemanager.NewBuilder(
 		dataDir1,
 		configuration.PackagesDir(configuration.Settings),
 		paths.New(configuration.Settings.GetString("directories.Downloads")),
@@ -224,7 +232,7 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
 	loadIndex := func(addr string) {
 		res, err := url.Parse(addr)
 		require.NoError(t, err)
-		require.NoError(t, pm.LoadPackageIndex(res))
+		require.NoError(t, pmb.LoadPackageIndex(res))
 	}
 	loadIndex("https://dl.espressif.com/dl/package_esp32_index.json")
 	loadIndex("http://arduino.esp8266.com/stable/package_esp8266com_index.json")
@@ -232,16 +240,20 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
 	// We ignore the errors returned since they might not be necessarily blocking
 	// but just warnings for the user, like in the case a board is not loaded
 	// because of malformed menus
-	pm.LoadHardware()
-	esp32, err := pm.FindBoardWithFQBN("esp32:esp32:esp32")
+	pmb.LoadHardware()
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+
+	esp32, err := pme.FindBoardWithFQBN("esp32:esp32:esp32")
 	require.NoError(t, err)
-	esptool231 := pm.FindToolDependency(&cores.ToolDependency{
+	esptool231 := pme.FindToolDependency(&cores.ToolDependency{
 		ToolPackager: "esp32",
 		ToolName:     "esptool",
 		ToolVersion:  semver.ParseRelaxed("2.3.1"),
 	})
 	require.NotNil(t, esptool231)
-	esptool0413 := pm.FindToolDependency(&cores.ToolDependency{
+	esptool0413 := pme.FindToolDependency(&cores.ToolDependency{
 		ToolPackager: "esp8266",
 		ToolName:     "esptool",
 		ToolVersion:  semver.ParseRelaxed("0.4.13"),
@@ -249,7 +261,7 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
 	require.NotNil(t, esptool0413)
 
 	testConflictingToolsInDifferentPackages := func() {
-		tools, err := pm.FindToolsRequiredForBoard(esp32)
+		tools, err := pme.FindToolsRequiredForBoard(esp32)
 		require.NoError(t, err)
 		require.Contains(t, tools, esptool231)
 		require.NotContains(t, tools, esptool0413)
@@ -269,22 +281,22 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
 	testConflictingToolsInDifferentPackages()
 	testConflictingToolsInDifferentPackages()
 
-	feather, err := pm.FindBoardWithFQBN("adafruit:samd:adafruit_feather_m0_express")
+	feather, err := pme.FindBoardWithFQBN("adafruit:samd:adafruit_feather_m0_express")
 	require.NoError(t, err)
 	require.NotNil(t, feather)
-	featherTools, err := pm.FindToolsRequiredForBoard(feather)
+	featherTools, err := pme.FindToolsRequiredForBoard(feather)
 	require.NoError(t, err)
 	require.NotNil(t, featherTools)
 
 	// Test when a package index requires two different version of the same tool
 	// See: https://github.com/arduino/arduino-cli/issues/166#issuecomment-528295989
-	bossac17 := pm.FindToolDependency(&cores.ToolDependency{
+	bossac17 := pme.FindToolDependency(&cores.ToolDependency{
 		ToolPackager: "arduino",
 		ToolName:     "bossac",
 		ToolVersion:  semver.ParseRelaxed("1.7.0"),
 	})
 	require.NotNil(t, bossac17)
-	bossac18 := pm.FindToolDependency(&cores.ToolDependency{
+	bossac18 := pme.FindToolDependency(&cores.ToolDependency{
 		ToolPackager: "arduino",
 		ToolName:     "bossac",
 		ToolVersion:  semver.ParseRelaxed("1.8.0-48-gb176eee"),
@@ -302,11 +314,14 @@ func TestFindToolsRequiredForBoard(t *testing.T) {
 }
 
 func TestIdentifyBoard(t *testing.T) {
-	pm := packagemanager.NewPackageManager(customHardware, customHardware, customHardware, customHardware, "test")
-	pm.LoadHardwareFromDirectory(customHardware)
+	pmb := packagemanager.NewBuilder(customHardware, customHardware, customHardware, customHardware, "test")
+	pmb.LoadHardwareFromDirectory(customHardware)
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
 
 	identify := func(vid, pid string) []*cores.Board {
-		return pm.IdentifyBoard(properties.NewFromHashmap(map[string]string{
+		return pme.IdentifyBoard(properties.NewFromHashmap(map[string]string{
 			"vid": vid, "pid": pid,
 		}))
 	}
@@ -326,25 +341,30 @@ func TestIdentifyBoard(t *testing.T) {
 
 func TestPackageManagerClear(t *testing.T) {
 	// Create a PackageManager and load the harware
-	packageManager := packagemanager.NewPackageManager(customHardware, customHardware, customHardware, customHardware, "test")
-	packageManager.LoadHardwareFromDirectory(customHardware)
+	pmb := packagemanager.NewBuilder(customHardware, customHardware, customHardware, customHardware, "test")
+	pmb.LoadHardwareFromDirectory(customHardware)
+	pm := pmb.Build()
+
+	// Creates another PackageManager but don't load the hardware
+	emptyPmb := packagemanager.NewBuilder(customHardware, customHardware, customHardware, customHardware, "test")
+	emptyPm := emptyPmb.Build()
 
-	// Check that the hardware is loaded
-	require.NotEmpty(t, packageManager.Packages)
+	// Verifies they're not equal
+	require.NotEqual(t, pm, emptyPm)
 
-	// Clear the package manager
-	packageManager.Clear()
+	// Clear the first PackageManager that contains loaded hardware
+	emptyPmb.BuildIntoExistingPackageManager(pm)
 
-	// Check that the hardware is cleared
-	require.Empty(t, packageManager.Packages)
+	// Verifies both PackageManagers are now equal
+	require.Equal(t, pm, emptyPm)
 }
 
 func TestFindToolsRequiredFromPlatformRelease(t *testing.T) {
 	// Create all the necessary data to load discoveries
 	fakePath := paths.New("fake-path")
 
-	pm := packagemanager.NewPackageManager(fakePath, fakePath, fakePath, fakePath, "test")
-	pack := pm.Packages.GetOrCreatePackage("arduino")
+	pmb := packagemanager.NewBuilder(fakePath, fakePath, fakePath, fakePath, "test")
+	pack := pmb.GetOrCreatePackage("arduino")
 
 	{
 		// some tool
@@ -437,15 +457,22 @@ func TestFindToolsRequiredFromPlatformRelease(t *testing.T) {
 	// We set this to fake the platform is installed
 	release.InstallDir = fakePath
 
-	tools, err := pm.FindToolsRequiredFromPlatformRelease(release)
+	pm := pmb.Build()
+	pme, pmeRelease := pm.NewExplorer()
+	defer pmeRelease()
+	tools, err := pme.FindToolsRequiredFromPlatformRelease(release)
 	require.NoError(t, err)
 	require.Len(t, tools, 6)
 }
 
 func TestFindPlatformReleaseDependencies(t *testing.T) {
-	pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "test")
-	pm.LoadPackageIndexFromFile(paths.New("testdata", "package_tooltest_index.json"))
-	pl, tools, err := pm.FindPlatformReleaseDependencies(&packagemanager.PlatformReference{Package: "test", PlatformArchitecture: "avr"})
+	pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
+	pmb.LoadPackageIndexFromFile(paths.New("testdata", "package_tooltest_index.json"))
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+
+	pl, tools, err := pme.FindPlatformReleaseDependencies(&packagemanager.PlatformReference{Package: "test", PlatformArchitecture: "avr"})
 	require.NoError(t, err)
 	require.NotNil(t, pl)
 	require.Len(t, tools, 3)
@@ -454,14 +481,18 @@ func TestFindPlatformReleaseDependencies(t *testing.T) {
 
 func TestLegacyPackageConversionToPluggableDiscovery(t *testing.T) {
 	// Pass nil, since these paths are only used for installing
-	pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "test")
+	pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
 	// Hardware from main packages directory
-	pm.LoadHardwareFromDirectory(dataDir1.Join("packages"))
+	pmb.LoadHardwareFromDirectory(dataDir1.Join("packages"))
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+
 	{
 		fqbn, err := cores.ParseFQBN("esp32:esp32:esp32")
 		require.NoError(t, err)
 		require.NotNil(t, fqbn)
-		_, platformRelease, board, _, _, err := pm.ResolveFQBN(fqbn)
+		_, platformRelease, board, _, _, err := pme.ResolveFQBN(fqbn)
 		require.NoError(t, err)
 
 		require.Equal(t, "esptool__pluggable_network", board.Properties.Get("upload.tool.network"))
@@ -484,7 +515,7 @@ func TestLegacyPackageConversionToPluggableDiscovery(t *testing.T) {
 		fqbn, err := cores.ParseFQBN("esp8266:esp8266:generic")
 		require.NoError(t, err)
 		require.NotNil(t, fqbn)
-		_, platformRelease, board, _, _, err := pm.ResolveFQBN(fqbn)
+		_, platformRelease, board, _, _, err := pme.ResolveFQBN(fqbn)
 		require.NoError(t, err)
 		require.Equal(t, "esptool__pluggable_network", board.Properties.Get("upload.tool.network"))
 		require.Equal(t, "generic", board.Properties.Get("upload_port.0.board"))
@@ -506,7 +537,7 @@ func TestLegacyPackageConversionToPluggableDiscovery(t *testing.T) {
 		fqbn, err := cores.ParseFQBN("arduino:avr:uno")
 		require.NoError(t, err)
 		require.NotNil(t, fqbn)
-		_, platformRelease, board, _, _, err := pm.ResolveFQBN(fqbn)
+		_, platformRelease, board, _, _, err := pme.ResolveFQBN(fqbn)
 		require.NoError(t, err)
 		require.Equal(t, "avrdude__pluggable_network", board.Properties.Get("upload.tool.network"))
 		require.Equal(t, "uno", board.Properties.Get("upload_port.4.board"))
diff --git a/arduino/cores/packagemanager/profiles.go b/arduino/cores/packagemanager/profiles.go
index a0be13ab946..eb4a58f9c65 100644
--- a/arduino/cores/packagemanager/profiles.go
+++ b/arduino/cores/packagemanager/profiles.go
@@ -32,15 +32,15 @@ import (
 
 // LoadHardwareForProfile load the hardware platforms for the given profile.
 // If installMissing is true then possibly missing tools and platforms will be downloaded and installed.
-func (pm *PackageManager) LoadHardwareForProfile(p *sketch.Profile, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) []error {
-	pm.profile = p
+func (pmb *Builder) LoadHardwareForProfile(p *sketch.Profile, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) []error {
+	pmb.profile = p
 
 	// Load required platforms
 	var merr []error
 	var platformReleases []*cores.PlatformRelease
 	indexURLs := map[string]*url.URL{}
 	for _, platformRef := range p.Platforms {
-		if platformRelease, err := pm.loadProfilePlatform(platformRef, installMissing, downloadCB, taskCB); err != nil {
+		if platformRelease, err := pmb.loadProfilePlatform(platformRef, installMissing, downloadCB, taskCB); err != nil {
 			merr = append(merr, fmt.Errorf("%s: %w", tr("loading required platform %s", platformRef), err))
 			logrus.WithField("platform", platformRef).WithError(err).Debugf("Error loading platform for profile")
 		} else {
@@ -56,7 +56,7 @@ func (pm *PackageManager) LoadHardwareForProfile(p *sketch.Profile, installMissi
 
 		for _, toolDep := range platformRelease.ToolDependencies {
 			indexURL := indexURLs[toolDep.ToolPackager]
-			if err := pm.loadProfileTool(toolDep, indexURL, installMissing, downloadCB, taskCB); err != nil {
+			if err := pmb.loadProfileTool(toolDep, indexURL, installMissing, downloadCB, taskCB); err != nil {
 				merr = append(merr, fmt.Errorf("%s: %w", tr("loading required tool %s", toolDep), err))
 				logrus.WithField("tool", toolDep).WithField("index_url", indexURL).WithError(err).Debugf("Error loading tool for profile")
 			} else {
@@ -68,8 +68,8 @@ func (pm *PackageManager) LoadHardwareForProfile(p *sketch.Profile, installMissi
 	return merr
 }
 
-func (pm *PackageManager) loadProfilePlatform(platformRef *sketch.ProfilePlatformReference, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*cores.PlatformRelease, error) {
-	targetPackage := pm.Packages.GetOrCreatePackage(platformRef.Packager)
+func (pmb *Builder) loadProfilePlatform(platformRef *sketch.ProfilePlatformReference, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*cores.PlatformRelease, error) {
+	targetPackage := pmb.packages.GetOrCreatePackage(platformRef.Packager)
 	platform := targetPackage.GetOrCreatePlatform(platformRef.Architecture)
 	release := platform.GetOrCreateRelease(platformRef.Version)
 
@@ -77,21 +77,21 @@ func (pm *PackageManager) loadProfilePlatform(platformRef *sketch.ProfilePlatfor
 	destDir := configuration.ProfilesCacheDir(configuration.Settings).Join(uid)
 	if !destDir.IsDir() && installMissing {
 		// Try installing the missing platform
-		if err := pm.installMissingProfilePlatform(platformRef, destDir, downloadCB, taskCB); err != nil {
+		if err := pmb.installMissingProfilePlatform(platformRef, destDir, downloadCB, taskCB); err != nil {
 			return nil, err
 		}
 	}
-	return release, pm.loadPlatformRelease(release, destDir)
+	return release, pmb.loadPlatformRelease(release, destDir)
 }
 
-func (pm *PackageManager) installMissingProfilePlatform(platformRef *sketch.ProfilePlatformReference, destDir *paths.Path, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+func (pmb *Builder) installMissingProfilePlatform(platformRef *sketch.ProfilePlatformReference, destDir *paths.Path, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
 	// Instantiate a temporary package manager only for platform installation
-	_ = pm.tempDir.MkdirAll()
-	tmp, err := paths.MkTempDir(pm.tempDir.String(), "")
+	_ = pmb.tempDir.MkdirAll()
+	tmp, err := paths.MkTempDir(pmb.tempDir.String(), "")
 	if err != nil {
 		return fmt.Errorf("installing missing platform: could not create temp dir %s", err)
 	}
-	tmpPm := NewPackageManager(tmp, tmp, pm.DownloadDir, tmp, pm.userAgent)
+	tmpPmb := NewBuilder(tmp, tmp, pmb.DownloadDir, tmp, pmb.userAgent)
 	defer tmp.RemoveAll()
 
 	// Download the main index and parse it
@@ -107,21 +107,25 @@ func (pm *PackageManager) installMissingProfilePlatform(platformRef *sketch.Prof
 			return &arduino.FailedDownloadError{Message: tr("Error downloading %s", indexURL), Cause: err}
 		}
 		indexResource := resources.IndexResource{URL: indexURL}
-		if err := indexResource.Download(tmpPm.IndexDir, downloadCB); err != nil {
+		if err := indexResource.Download(tmpPmb.IndexDir, downloadCB); err != nil {
 			taskCB(&rpc.TaskProgress{Name: tr("Error downloading %s", indexURL)})
 			return &arduino.FailedDownloadError{Message: tr("Error downloading %s", indexURL), Cause: err}
 		}
-		if err := tmpPm.LoadPackageIndex(indexURL); err != nil {
+		if err := tmpPmb.LoadPackageIndex(indexURL); err != nil {
 			taskCB(&rpc.TaskProgress{Name: tr("Error loading index %s", indexURL)})
 			return &arduino.FailedInstallError{Message: tr("Error loading index %s", indexURL), Cause: err}
 		}
 	}
 
 	// Download the platform
-	tmpTargetPackage := tmpPm.Packages.GetOrCreatePackage(platformRef.Packager)
+	tmpTargetPackage := tmpPmb.packages.GetOrCreatePackage(platformRef.Packager)
 	tmpPlatform := tmpTargetPackage.GetOrCreatePlatform(platformRef.Architecture)
 	tmpPlatformRelease := tmpPlatform.GetOrCreateRelease(platformRef.Version)
-	if err := tmpPm.DownloadPlatformRelease(tmpPlatformRelease, nil, downloadCB); err != nil {
+	tmpPm := tmpPmb.Build()
+	tmpPme, tmpRelease := tmpPm.NewExplorer()
+	defer tmpRelease()
+
+	if err := tmpPme.DownloadPlatformRelease(tmpPlatformRelease, nil, downloadCB); err != nil {
 		taskCB(&rpc.TaskProgress{Name: tr("Error downloading platform %s", tmpPlatformRelease)})
 		return &arduino.FailedInstallError{Message: tr("Error downloading platform %s", tmpPlatformRelease), Cause: err}
 	}
@@ -129,7 +133,7 @@ func (pm *PackageManager) installMissingProfilePlatform(platformRef *sketch.Prof
 
 	// Perform install
 	taskCB(&rpc.TaskProgress{Name: tr("Installing platform %s", tmpPlatformRelease)})
-	if err := tmpPm.InstallPlatformInDirectory(tmpPlatformRelease, destDir); err != nil {
+	if err := tmpPme.InstallPlatformInDirectory(tmpPlatformRelease, destDir); err != nil {
 		taskCB(&rpc.TaskProgress{Name: tr("Error installing platform %s", tmpPlatformRelease)})
 		return &arduino.FailedInstallError{Message: tr("Error installing platform %s", tmpPlatformRelease), Cause: err}
 	}
@@ -137,8 +141,8 @@ func (pm *PackageManager) installMissingProfilePlatform(platformRef *sketch.Prof
 	return nil
 }
 
-func (pm *PackageManager) loadProfileTool(toolRef *cores.ToolDependency, indexURL *url.URL, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
-	targetPackage := pm.Packages.GetOrCreatePackage(toolRef.ToolPackager)
+func (pmb *Builder) loadProfileTool(toolRef *cores.ToolDependency, indexURL *url.URL, installMissing bool, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+	targetPackage := pmb.packages.GetOrCreatePackage(toolRef.ToolPackager)
 	tool := targetPackage.GetOrCreateTool(toolRef.ToolName)
 
 	uid := toolRef.InternalUniqueIdentifier(indexURL)
@@ -150,15 +154,15 @@ func (pm *PackageManager) loadProfileTool(toolRef *cores.ToolDependency, indexUR
 		if toolRelease == nil {
 			return &arduino.InvalidVersionError{Cause: fmt.Errorf(tr("version %s not found", toolRef.ToolVersion))}
 		}
-		if err := pm.installMissingProfileTool(toolRelease, destDir, downloadCB, taskCB); err != nil {
+		if err := pmb.installMissingProfileTool(toolRelease, destDir, downloadCB, taskCB); err != nil {
 			return err
 		}
 	}
 
-	return pm.loadToolReleaseFromDirectory(tool, toolRef.ToolVersion, destDir)
+	return pmb.loadToolReleaseFromDirectory(tool, toolRef.ToolVersion, destDir)
 }
 
-func (pm *PackageManager) installMissingProfileTool(toolRelease *cores.ToolRelease, destDir *paths.Path, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+func (pmb *Builder) installMissingProfileTool(toolRelease *cores.ToolRelease, destDir *paths.Path, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
 	// Instantiate a temporary package manager only for platform installation
 	tmp, err := paths.MkTempDir(destDir.Parent().String(), "")
 	if err != nil {
@@ -172,7 +176,7 @@ func (pm *PackageManager) installMissingProfileTool(toolRelease *cores.ToolRelea
 		return &arduino.InvalidVersionError{Cause: fmt.Errorf(tr("version %s not available for this operating system", toolRelease))}
 	}
 	taskCB(&rpc.TaskProgress{Name: tr("Downloading tool %s", toolRelease)})
-	if err := toolResource.Download(pm.DownloadDir, nil, toolRelease.String(), downloadCB); err != nil {
+	if err := toolResource.Download(pmb.DownloadDir, nil, toolRelease.String(), downloadCB); err != nil {
 		taskCB(&rpc.TaskProgress{Name: tr("Error downloading tool %s", toolRelease)})
 		return &arduino.FailedInstallError{Message: tr("Error installing tool %s", toolRelease), Cause: err}
 	}
@@ -180,7 +184,7 @@ func (pm *PackageManager) installMissingProfileTool(toolRelease *cores.ToolRelea
 
 	// Install tool
 	taskCB(&rpc.TaskProgress{Name: tr("Installing tool %s", toolRelease)})
-	if err := toolResource.Install(pm.DownloadDir, tmp, destDir); err != nil {
+	if err := toolResource.Install(pmb.DownloadDir, tmp, destDir); err != nil {
 		taskCB(&rpc.TaskProgress{Name: tr("Error installing tool %s", toolRelease)})
 		return &arduino.FailedInstallError{Message: tr("Error installing tool %s", toolRelease), Cause: err}
 	}
diff --git a/arduino/cores/status.go b/arduino/cores/status.go
index dfcd826345a..72bc718c46a 100644
--- a/arduino/cores/status.go
+++ b/arduino/cores/status.go
@@ -48,7 +48,7 @@ type Package struct {
 	Packages   Packages             `json:"-"`
 }
 
-// GetOrCreatePackage returns the specified Package or create an empty one
+// GetOrCreatePackage returns the specified Package or creates an empty one
 // filling all the cross-references
 func (packages Packages) GetOrCreatePackage(packager string) *Package {
 	if targetPackage, ok := packages[packager]; ok {
diff --git a/cli/arguments/completion.go b/cli/arguments/completion.go
index 32ab99f407b..06e35e7d6c2 100644
--- a/cli/arguments/completion.go
+++ b/cli/arguments/completion.go
@@ -35,8 +35,15 @@ func GetInstalledBoards() []string {
 // It returns a list of protocols available based on the installed boards
 func GetInstalledProtocols() []string {
 	inst := instance.CreateAndInit()
-	pm := commands.GetPackageManager(inst.Id)
-	boards := pm.InstalledBoards()
+
+	// FIXME: We must not access PackageManager directly here but use one of the commands.* functions
+	pme, release := commands.GetPackageManagerExplorer(&rpc.BoardListAllRequest{Instance: inst})
+	if pme == nil {
+		return nil // should never happen...
+	}
+	defer release()
+
+	boards := pme.InstalledBoards()
 
 	installedProtocols := make(map[string]struct{})
 	for _, board := range boards {
@@ -63,19 +70,26 @@ func GetInstalledProtocols() []string {
 // It returns a list of programmers available based on the installed boards
 func GetInstalledProgrammers() []string {
 	inst := instance.CreateAndInit()
-	pm := commands.GetPackageManager(inst.Id)
 
 	// we need the list of the available fqbn in order to get the list of the programmers
-	list, _ := board.ListAll(context.Background(), &rpc.BoardListAllRequest{
+	listAllReq := &rpc.BoardListAllRequest{
 		Instance:            inst,
 		SearchArgs:          nil,
 		IncludeHiddenBoards: false,
-	})
+	}
+	list, _ := board.ListAll(context.Background(), listAllReq)
+
+	// FIXME: We must not access PackageManager directly here but use one of the commands.* functions
+	pme, release := commands.GetPackageManagerExplorer(listAllReq)
+	if pme == nil {
+		return nil // should never happen...
+	}
+	defer release()
 
 	installedProgrammers := make(map[string]string)
 	for _, board := range list.Boards {
 		fqbn, _ := cores.ParseFQBN(board.Fqbn)
-		_, boardPlatform, _, _, _, _ := pm.ResolveFQBN(fqbn)
+		_, boardPlatform, _, _, _, _ := pme.ResolveFQBN(fqbn)
 		for programmerID, programmer := range boardPlatform.Programmers {
 			installedProgrammers[programmerID] = programmer.Name
 		}
diff --git a/cli/arguments/port.go b/cli/arguments/port.go
index 1e054e713b4..1f065fde2f2 100644
--- a/cli/arguments/port.go
+++ b/cli/arguments/port.go
@@ -101,11 +101,14 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
 	}
 	logrus.WithField("port", address).Tracef("Upload port")
 
-	pm := commands.GetPackageManager(instance.Id)
-	if pm == nil {
-		return nil, errors.New("invalid instance")
+	// FIXME: We must not access PackageManager directly here but use one of the commands.* functions
+	pme, release := commands.GetPackageManagerExplorer(&rpc.BoardListAllRequest{Instance: instance})
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
 	}
-	dm := pm.DiscoveryManager()
+	defer release()
+
+	dm := pme.DiscoveryManager()
 	watcher, err := dm.Watch()
 	if err != nil {
 		return nil, err
diff --git a/cli/board/list.go b/cli/board/list.go
index fe82973847a..2e5fd510814 100644
--- a/cli/board/list.go
+++ b/cli/board/list.go
@@ -78,7 +78,7 @@ func runListCommand(cmd *cobra.Command, args []string) {
 }
 
 func watchList(cmd *cobra.Command, inst *rpc.Instance) {
-	eventsChan, closeCB, err := board.Watch(inst.Id)
+	eventsChan, closeCB, err := board.Watch(&rpc.BoardListWatchRequest{Instance: inst})
 	if err != nil {
 		feedback.Errorf(tr("Error detecting boards: %v"), err)
 		os.Exit(errorcodes.ErrNetwork)
diff --git a/cli/compile/compile.go b/cli/compile/compile.go
index d6aa2a8880f..7af9e157f8a 100644
--- a/cli/compile/compile.go
+++ b/cli/compile/compile.go
@@ -345,11 +345,13 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
 				panic(tr("Platform ID is not correct"))
 			}
 
-			pm := commands.GetPackageManager(inst.GetId())
-			platform := pm.FindPlatform(&packagemanager.PlatformReference{
+			// FIXME: Here we should not access PackageManager...
+			pme, release := commands.GetPackageManagerExplorer(compileRequest)
+			platform := pme.FindPlatform(&packagemanager.PlatformReference{
 				Package:              split[0],
 				PlatformArchitecture: split[1],
 			})
+			release()
 
 			if profileArg.String() == "" {
 				if platform != nil {
diff --git a/cli/lib/upgrade.go b/cli/lib/upgrade.go
index 11f071b8550..9cd35b29b48 100644
--- a/cli/lib/upgrade.go
+++ b/cli/lib/upgrade.go
@@ -16,6 +16,7 @@
 package lib
 
 import (
+	"context"
 	"os"
 
 	"github.com/arduino/arduino-cli/cli/errorcodes"
@@ -23,6 +24,7 @@ import (
 	"github.com/arduino/arduino-cli/cli/instance"
 	"github.com/arduino/arduino-cli/cli/output"
 	"github.com/arduino/arduino-cli/commands/lib"
+	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
@@ -45,19 +47,27 @@ func runUpgradeCommand(cmd *cobra.Command, args []string) {
 	instance := instance.CreateAndInit()
 	logrus.Info("Executing `arduino-cli lib upgrade`")
 
+	var upgradeErr error
 	if len(args) == 0 {
-		err := lib.LibraryUpgradeAll(instance.Id, output.ProgressBar(), output.TaskProgress())
-		if err != nil {
-			feedback.Errorf(tr("Error upgrading libraries: %v"), err)
-			os.Exit(errorcodes.ErrGeneric)
-		}
+		req := &rpc.LibraryUpgradeAllRequest{Instance: instance}
+		upgradeErr = lib.LibraryUpgradeAll(req, output.ProgressBar(), output.TaskProgress())
 	} else {
-		err := lib.LibraryUpgrade(instance.Id, args, output.ProgressBar(), output.TaskProgress())
-		if err != nil {
-			feedback.Errorf(tr("Error upgrading libraries: %v"), err)
-			os.Exit(errorcodes.ErrGeneric)
+		for _, libName := range args {
+			req := &rpc.LibraryUpgradeRequest{
+				Instance: instance,
+				Name:     libName,
+			}
+			upgradeErr = lib.LibraryUpgrade(context.Background(), req, output.ProgressBar(), output.TaskProgress())
+			if upgradeErr != nil {
+				break
+			}
 		}
 	}
 
+	if upgradeErr != nil {
+		feedback.Errorf("%s: %v", tr("Error upgrading libraries"), upgradeErr)
+		os.Exit(errorcodes.ErrGeneric)
+	}
+
 	logrus.Info("Done")
 }
diff --git a/cli/upload/upload.go b/cli/upload/upload.go
index e2404330741..f9713a1037a 100644
--- a/cli/upload/upload.go
+++ b/cli/upload/upload.go
@@ -121,11 +121,13 @@ func runUploadCommand(command *cobra.Command, args []string) {
 				panic(tr("Platform ID is not correct"))
 			}
 
-			pm := commands.GetPackageManager(instance.GetId())
-			platform := pm.FindPlatform(&packagemanager.PlatformReference{
+			// FIXME: Here we must not access package manager...
+			pme, release := commands.GetPackageManagerExplorer(&rpc.UploadRequest{Instance: instance})
+			platform := pme.FindPlatform(&packagemanager.PlatformReference{
 				Package:              split[0],
 				PlatformArchitecture: split[1],
 			})
+			release()
 
 			if platform != nil {
 				feedback.Errorf(tr("Try running %s", fmt.Sprintf("`%s core install %s`", globals.VersionInfo.Application, platformErr.Platform)))
diff --git a/commands/board/attach.go b/commands/board/attach.go
index aa3f4f5626c..33ca154d1a2 100644
--- a/commands/board/attach.go
+++ b/commands/board/attach.go
@@ -37,10 +37,11 @@ var tr = i18n.Tr
 
 // Attach FIXMEDOC
 func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB rpc.TaskProgressCB) (*rpc.BoardAttachResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 	var sketchPath *paths.Path
 	if req.GetSketchPath() != "" {
 		sketchPath = paths.New(req.GetSketchPath())
@@ -66,7 +67,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB rpc.TaskPro
 			return nil, &arduino.InvalidArgumentError{Message: tr("Invalid Device URL format"), Cause: err}
 		}
 
-		var findBoardFunc func(*packagemanager.PackageManager, *discovery.Monitor, *url.URL) *cores.Board
+		var findBoardFunc func(*packagemanager.Explorer, *discovery.Monitor, *url.URL) *cores.Board
 		switch deviceURI.Scheme {
 		case "serial", "tty":
 			findBoardFunc = findSerialConnectedBoard
@@ -87,7 +88,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB rpc.TaskPro
 		time.Sleep(duration)
 
 		// TODO: Handle the case when no board is found.
-		board := findBoardFunc(pm, monitor, deviceURI)
+		board := findBoardFunc(pme, monitor, deviceURI)
 		if board == nil {
 			return nil, &arduino.InvalidArgumentError{Message: tr("No supported board found at %s", deviceURI)}
 		}
@@ -113,7 +114,7 @@ func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB rpc.TaskPro
 // FIXME: Those should probably go in a "BoardManager" pkg or something
 // findSerialConnectedBoard find the board which is connected to the specified URI via serial port, using a monitor and a set of Boards
 // for the matching.
-func findSerialConnectedBoard(pm *packagemanager.PackageManager, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
+func findSerialConnectedBoard(pme *packagemanager.Explorer, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
 	found := false
 	// to support both cases:
 	// serial:///dev/ttyACM2 parsing gives: deviceURI.Host = ""      and deviceURI.Path = /dev/ttyACM2
@@ -131,7 +132,7 @@ func findSerialConnectedBoard(pm *packagemanager.PackageManager, monitor *discov
 		return nil
 	}
 
-	boards := pm.FindBoardsWithVidPid(serialDevice.VendorID, serialDevice.ProductID)
+	boards := pme.FindBoardsWithVidPid(serialDevice.VendorID, serialDevice.ProductID)
 	if len(boards) == 0 {
 		return nil
 	}
@@ -141,7 +142,7 @@ func findSerialConnectedBoard(pm *packagemanager.PackageManager, monitor *discov
 
 // findNetworkConnectedBoard find the board which is connected to the specified URI on the network, using a monitor and a set of Boards
 // for the matching.
-func findNetworkConnectedBoard(pm *packagemanager.PackageManager, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
+func findNetworkConnectedBoard(pme *packagemanager.Explorer, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
 	found := false
 
 	var networkDevice discovery.NetworkDevice
@@ -158,7 +159,7 @@ func findNetworkConnectedBoard(pm *packagemanager.PackageManager, monitor *disco
 		return nil
 	}
 
-	boards := pm.FindBoardsWithID(networkDevice.Name)
+	boards := pme.FindBoardsWithID(networkDevice.Name)
 	if len(boards) == 0 {
 		return nil
 	}
diff --git a/commands/board/details.go b/commands/board/details.go
index 220736dc7dd..09cd3ec88c1 100644
--- a/commands/board/details.go
+++ b/commands/board/details.go
@@ -27,17 +27,18 @@ import (
 // Details returns all details for a board including tools and HW identifiers.
 // This command basically gather al the information and translates it into the required grpc struct properties
 func Details(ctx context.Context, req *rpc.BoardDetailsRequest) (*rpc.BoardDetailsResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	fqbn, err := cores.ParseFQBN(req.GetFqbn())
 	if err != nil {
 		return nil, &arduino.InvalidFQBNError{Cause: err}
 	}
 
-	boardPackage, boardPlatform, board, boardProperties, boardRefPlatform, err := pm.ResolveFQBN(fqbn)
+	boardPackage, boardPlatform, board, boardProperties, boardRefPlatform, err := pme.ResolveFQBN(fqbn)
 	if err != nil {
 		return nil, &arduino.UnknownFQBNError{Cause: err}
 	}
@@ -110,7 +111,7 @@ func Details(ctx context.Context, req *rpc.BoardDetailsRequest) (*rpc.BoardDetai
 
 	details.ToolsDependencies = []*rpc.ToolsDependencies{}
 	for _, tool := range boardPlatform.ToolDependencies {
-		toolRelease := pm.FindToolDependency(tool)
+		toolRelease := pme.FindToolDependency(tool)
 		var systems []*rpc.Systems
 		if toolRelease != nil {
 			for _, f := range toolRelease.Flavors {
diff --git a/commands/board/list.go b/commands/board/list.go
index fe9b4afeb09..1a81a187f85 100644
--- a/commands/board/list.go
+++ b/commands/board/list.go
@@ -118,12 +118,12 @@ func identifyViaCloudAPI(port *discovery.Port) ([]*rpc.BoardListItem, error) {
 }
 
 // identify returns a list of boards checking first the installed platforms or the Cloud API
-func identify(pm *packagemanager.PackageManager, port *discovery.Port) ([]*rpc.BoardListItem, error) {
+func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardListItem, error) {
 	boards := []*rpc.BoardListItem{}
 
 	// first query installed cores through the Package Manager
 	logrus.Debug("Querying installed cores for board identification...")
-	for _, board := range pm.IdentifyBoard(port.Properties) {
+	for _, board := range pme.IdentifyBoard(port.Properties) {
 		// We need the Platform maintaner for sorting so we set it here
 		platform := &rpc.Platform{
 			Maintainer: board.PlatformRelease.Platform.Package.Maintainer,
@@ -178,18 +178,19 @@ func identify(pm *packagemanager.PackageManager, port *discovery.Port) ([]*rpc.B
 // In case of errors partial results from discoveries that didn't fail
 // are returned.
 func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, discoveryStartErrors []error, e error) {
-	pm := commands.GetPackageManager(req.GetInstance().Id)
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
-	dm := pm.DiscoveryManager()
+	dm := pme.DiscoveryManager()
 	discoveryStartErrors = dm.Start()
 	time.Sleep(time.Duration(req.GetTimeout()) * time.Millisecond)
 
 	retVal := []*rpc.DetectedPort{}
 	for _, port := range dm.List() {
-		boards, err := identify(pm, port)
+		boards, err := identify(pme, port)
 		if err != nil {
 			return nil, discoveryStartErrors, err
 		}
@@ -207,9 +208,13 @@ func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, discoveryStartError
 
 // Watch returns a channel that receives boards connection and disconnection events.
 // It also returns a callback function that must be used to stop and dispose the watch.
-func Watch(instanceID int32) (<-chan *rpc.BoardListWatchResponse, func(), error) {
-	pm := commands.GetPackageManager(instanceID)
-	dm := pm.DiscoveryManager()
+func Watch(req *rpc.BoardListWatchRequest) (<-chan *rpc.BoardListWatchResponse, func(), error) {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
+	dm := pme.DiscoveryManager()
 
 	watcher, err := dm.Watch()
 	if err != nil {
@@ -232,7 +237,7 @@ func Watch(instanceID int32) (<-chan *rpc.BoardListWatchResponse, func(), error)
 
 			boardsError := ""
 			if event.Type == "add" {
-				boards, err := identify(pm, event.Port)
+				boards, err := identify(pme, event.Port)
 				if err != nil {
 					boardsError = err.Error()
 				}
diff --git a/commands/board/list_test.go b/commands/board/list_test.go
index c20b467ca0e..3d3314f9404 100644
--- a/commands/board/list_test.go
+++ b/commands/board/list_test.go
@@ -119,10 +119,10 @@ func TestBoardIdentifySorting(t *testing.T) {
 	defer paths.TempDir().Join("test").RemoveAll()
 
 	// We don't really care about the paths in this case
-	pm := packagemanager.NewPackageManager(dataDir, dataDir, dataDir, dataDir, "test")
+	pmb := packagemanager.NewBuilder(dataDir, dataDir, dataDir, dataDir, "test")
 
 	// Create some boards with identical VID:PID combination
-	pack := pm.Packages.GetOrCreatePackage("packager")
+	pack := pmb.GetOrCreatePackage("packager")
 	pack.Maintainer = "NotArduino"
 	platform := pack.GetOrCreatePlatform("platform")
 	platformRelease := platform.GetOrCreateRelease(semver.MustParse("0.0.0"))
@@ -135,7 +135,7 @@ func TestBoardIdentifySorting(t *testing.T) {
 	board.Properties.Set("upload_port.pid", "0x0000")
 
 	// Create some Arduino boards with same VID:PID combination as boards created previously
-	pack = pm.Packages.GetOrCreatePackage("arduino")
+	pack = pmb.GetOrCreatePackage("arduino")
 	pack.Maintainer = "Arduino"
 	platform = pack.GetOrCreatePlatform("avr")
 	platformRelease = platform.GetOrCreateRelease(semver.MustParse("0.0.0"))
@@ -150,7 +150,12 @@ func TestBoardIdentifySorting(t *testing.T) {
 	idPrefs := properties.NewMap()
 	idPrefs.Set("vid", "0x0000")
 	idPrefs.Set("pid", "0x0000")
-	res, err := identify(pm, &discovery.Port{Properties: idPrefs})
+
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+
+	res, err := identify(pme, &discovery.Port{Properties: idPrefs})
 	require.NoError(t, err)
 	require.NotNil(t, res)
 	require.Len(t, res, 4)
diff --git a/commands/board/listall.go b/commands/board/listall.go
index 4143c51f844..d18784f9581 100644
--- a/commands/board/listall.go
+++ b/commands/board/listall.go
@@ -27,17 +27,18 @@ import (
 
 // ListAll FIXMEDOC
 func ListAll(ctx context.Context, req *rpc.BoardListAllRequest) (*rpc.BoardListAllResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	searchArgs := strings.Join(req.GetSearchArgs(), " ")
 
 	list := &rpc.BoardListAllResponse{Boards: []*rpc.BoardListItem{}}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.GetPackages() {
 		for _, platform := range targetPackage.Platforms {
-			installedPlatformRelease := pm.GetInstalledPlatformRelease(platform)
+			installedPlatformRelease := pme.GetInstalledPlatformRelease(platform)
 			// We only want to list boards for installed platforms
 			if installedPlatformRelease == nil {
 				continue
diff --git a/commands/board/search.go b/commands/board/search.go
index 658e71f3105..570c58ac510 100644
--- a/commands/board/search.go
+++ b/commands/board/search.go
@@ -31,16 +31,17 @@ import (
 // installed. Note that platforms that are not installed don't include boards' FQBNs.
 // If no search argument is used all boards are returned.
 func Search(ctx context.Context, req *rpc.BoardSearchRequest) (*rpc.BoardSearchResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	res := &rpc.BoardSearchResponse{Boards: []*rpc.BoardListItem{}}
-	for _, targetPackage := range pm.Packages {
+	for _, targetPackage := range pme.GetPackages() {
 		for _, platform := range targetPackage.Platforms {
 			latestPlatformRelease := platform.GetLatestRelease()
-			installedPlatformRelease := pm.GetInstalledPlatformRelease(platform)
+			installedPlatformRelease := pme.GetInstalledPlatformRelease(platform)
 
 			if latestPlatformRelease == nil && installedPlatformRelease == nil {
 				continue
diff --git a/commands/compile/compile.go b/commands/compile/compile.go
index db92107b059..6a2af24b7f4 100644
--- a/commands/compile/compile.go
+++ b/commands/compile/compile.go
@@ -57,11 +57,13 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
 		exportBinaries = reqExportBinaries.Value
 	}
 
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	defer release()
+
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
@@ -89,11 +91,11 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
 		return nil, &arduino.InvalidFQBNError{Cause: err}
 	}
 
-	targetPlatform := pm.FindPlatform(&packagemanager.PlatformReference{
+	targetPlatform := pme.FindPlatform(&packagemanager.PlatformReference{
 		Package:              fqbn.Package,
 		PlatformArchitecture: fqbn.PlatformArch,
 	})
-	if targetPlatform == nil || pm.GetInstalledPlatformRelease(targetPlatform) == nil {
+	if targetPlatform == nil || pme.GetInstalledPlatformRelease(targetPlatform) == nil {
 		return nil, &arduino.PlatformNotFoundError{
 			Platform: fmt.Sprintf("%s:%s", fqbn.Package, fqbn.PlatformArch),
 			Cause:    fmt.Errorf(tr("platform not installed")),
@@ -110,8 +112,8 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
 	}
 
 	builderCtx := &types.Context{}
-	builderCtx.PackageManager = pm
-	if pm.GetProfile() != nil {
+	builderCtx.PackageManager = pme
+	if pme.GetProfile() != nil {
 		builderCtx.LibrariesManager = lm
 	}
 	builderCtx.UseCachedLibrariesResolution = req.GetSkipLibrariesDiscovery()
diff --git a/commands/core/download.go b/commands/core/download.go
index 4da671ed837..2a7e37bd536 100644
--- a/commands/core/download.go
+++ b/commands/core/download.go
@@ -29,10 +29,11 @@ var tr = i18n.Tr
 
 // PlatformDownload FIXMEDOC
 func PlatformDownload(ctx context.Context, req *rpc.PlatformDownloadRequest, downloadCB rpc.DownloadProgressCB) (*rpc.PlatformDownloadResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	version, err := commands.ParseVersion(req)
 	if err != nil {
@@ -44,17 +45,17 @@ func PlatformDownload(ctx context.Context, req *rpc.PlatformDownloadRequest, dow
 		PlatformArchitecture: req.Architecture,
 		PlatformVersion:      version,
 	}
-	platform, tools, err := pm.FindPlatformReleaseDependencies(ref)
+	platform, tools, err := pme.FindPlatformReleaseDependencies(ref)
 	if err != nil {
 		return nil, &arduino.PlatformNotFoundError{Platform: ref.String(), Cause: err}
 	}
 
-	if err := pm.DownloadPlatformRelease(platform, nil, downloadCB); err != nil {
+	if err := pme.DownloadPlatformRelease(platform, nil, downloadCB); err != nil {
 		return nil, err
 	}
 
 	for _, tool := range tools {
-		if err := pm.DownloadToolRelease(tool, nil, downloadCB); err != nil {
+		if err := pme.DownloadToolRelease(tool, nil, downloadCB); err != nil {
 			return nil, err
 		}
 	}
diff --git a/commands/core/install.go b/commands/core/install.go
index 21c9f0c9c46..7eb0383aa09 100644
--- a/commands/core/install.go
+++ b/commands/core/install.go
@@ -26,50 +26,55 @@ import (
 )
 
 // PlatformInstall FIXMEDOC
-func PlatformInstall(ctx context.Context, req *rpc.PlatformInstallRequest,
-	downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*rpc.PlatformInstallResponse, error) {
+func PlatformInstall(ctx context.Context, req *rpc.PlatformInstallRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*rpc.PlatformInstallResponse, error) {
+	install := func() error {
+		pme, release := commands.GetPackageManagerExplorer(req)
+		if pme == nil {
+			return &arduino.InvalidInstanceError{}
+		}
+		defer release()
 
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
-		return nil, &arduino.InvalidInstanceError{}
-	}
+		version, err := commands.ParseVersion(req)
+		if err != nil {
+			return &arduino.InvalidVersionError{Cause: err}
+		}
 
-	version, err := commands.ParseVersion(req)
-	if err != nil {
-		return nil, &arduino.InvalidVersionError{Cause: err}
-	}
+		ref := &packagemanager.PlatformReference{
+			Package:              req.PlatformPackage,
+			PlatformArchitecture: req.Architecture,
+			PlatformVersion:      version,
+		}
+		platformRelease, tools, err := pme.FindPlatformReleaseDependencies(ref)
+		if err != nil {
+			return &arduino.PlatformNotFoundError{Platform: ref.String(), Cause: err}
+		}
 
-	ref := &packagemanager.PlatformReference{
-		Package:              req.PlatformPackage,
-		PlatformArchitecture: req.Architecture,
-		PlatformVersion:      version,
-	}
-	platformRelease, tools, err := pm.FindPlatformReleaseDependencies(ref)
-	if err != nil {
-		return nil, &arduino.PlatformNotFoundError{Platform: ref.String(), Cause: err}
-	}
+		// Prerequisite checks before install
+		if platformRelease.IsInstalled() {
+			taskCB(&rpc.TaskProgress{Name: tr("Platform %s already installed", platformRelease), Completed: true})
+			return nil
+		}
 
-	// Prerequisite checks before install
-	if platformRelease.IsInstalled() {
-		taskCB(&rpc.TaskProgress{Name: tr("Platform %s already installed", platformRelease), Completed: true})
-		return &rpc.PlatformInstallResponse{}, nil
-	}
+		if req.GetNoOverwrite() {
+			if installed := pme.GetInstalledPlatformRelease(platformRelease.Platform); installed != nil {
+				return fmt.Errorf("%s: %s",
+					tr("Platform %s already installed", installed),
+					tr("could not overwrite"))
+			}
+		}
 
-	if req.GetNoOverwrite() {
-		if installed := pm.GetInstalledPlatformRelease(platformRelease.Platform); installed != nil {
-			return nil, fmt.Errorf("%s: %s",
-				tr("Platform %s already installed", installed),
-				tr("could not overwrite"))
+		if err := pme.DownloadAndInstallPlatformAndTools(platformRelease, tools, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
+			return err
 		}
+
+		return nil
 	}
 
-	if err := pm.DownloadAndInstallPlatformAndTools(platformRelease, tools, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
+	if err := install(); err != nil {
 		return nil, err
 	}
-
 	if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
 		return nil, err
 	}
-
 	return &rpc.PlatformInstallResponse{}, nil
 }
diff --git a/commands/core/list.go b/commands/core/list.go
index 7ceb2819ece..b263058759a 100644
--- a/commands/core/list.go
+++ b/commands/core/list.go
@@ -28,15 +28,16 @@ import (
 // GetPlatforms returns a list of installed platforms, optionally filtered by
 // those requiring an update.
 func GetPlatforms(req *rpc.PlatformListRequest) ([]*rpc.Platform, error) {
-	packageManager := commands.GetPackageManager(req.GetInstance().Id)
-	if packageManager == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	res := []*rpc.Platform{}
-	for _, targetPackage := range packageManager.Packages {
+	for _, targetPackage := range pme.GetPackages() {
 		for _, platform := range targetPackage.Platforms {
-			platformRelease := packageManager.GetInstalledPlatformRelease(platform)
+			platformRelease := pme.GetInstalledPlatformRelease(platform)
 
 			// The All flags adds to the list of installed platforms the installable platforms (from the indexes)
 			// If both All and UpdatableOnly are set All takes precedence
diff --git a/commands/core/search.go b/commands/core/search.go
index 1db229bf57c..48ba605d8a4 100644
--- a/commands/core/search.go
+++ b/commands/core/search.go
@@ -31,18 +31,19 @@ import (
 func PlatformSearch(req *rpc.PlatformSearchRequest) (*rpc.PlatformSearchResponse, error) {
 	searchArgs := strings.TrimSpace(req.SearchArgs)
 	allVersions := req.AllVersions
-	pm := commands.GetPackageManager(req.Instance.Id)
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	res := []*cores.PlatformRelease{}
 	if isUsb, _ := regexp.MatchString("[0-9a-f]{4}:[0-9a-f]{4}", searchArgs); isUsb {
 		vid, pid := searchArgs[:4], searchArgs[5:]
-		res = pm.FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid)
+		res = pme.FindPlatformReleaseProvidingBoardsWithVidPid(vid, pid)
 	} else {
 
-		for _, targetPackage := range pm.Packages {
+		for _, targetPackage := range pme.GetPackages() {
 			for _, platform := range targetPackage.Platforms {
 				// discard invalid platforms
 				// Users can install platforms manually in the Sketchbook hardware folder,
diff --git a/commands/core/uninstall.go b/commands/core/uninstall.go
index b5127e3cd37..165b1fc16ea 100644
--- a/commands/core/uninstall.go
+++ b/commands/core/uninstall.go
@@ -26,46 +26,54 @@ import (
 
 // PlatformUninstall FIXMEDOC
 func PlatformUninstall(ctx context.Context, req *rpc.PlatformUninstallRequest, taskCB rpc.TaskProgressCB) (*rpc.PlatformUninstallResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
-		return nil, &arduino.InvalidInstanceError{}
+	if err := platformUninstall(ctx, req, taskCB); err != nil {
+		return nil, err
+	}
+	if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
+		return nil, err
+	}
+	return &rpc.PlatformUninstallResponse{}, nil
+}
+
+// platformUninstall is the implementation of platform unistaller
+func platformUninstall(ctx context.Context, req *rpc.PlatformUninstallRequest, taskCB rpc.TaskProgressCB) error {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
 	ref := &packagemanager.PlatformReference{
 		Package:              req.PlatformPackage,
 		PlatformArchitecture: req.Architecture,
 	}
 	if ref.PlatformVersion == nil {
-		platform := pm.FindPlatform(ref)
+		platform := pme.FindPlatform(ref)
 		if platform == nil {
-			return nil, &arduino.PlatformNotFoundError{Platform: ref.String()}
+			return &arduino.PlatformNotFoundError{Platform: ref.String()}
 		}
-		platformRelease := pm.GetInstalledPlatformRelease(platform)
+		platformRelease := pme.GetInstalledPlatformRelease(platform)
 		if platformRelease == nil {
-			return nil, &arduino.PlatformNotFoundError{Platform: ref.String()}
+			return &arduino.PlatformNotFoundError{Platform: ref.String()}
 		}
 		ref.PlatformVersion = platformRelease.Version
 	}
 
-	platform, tools, err := pm.FindPlatformReleaseDependencies(ref)
+	platform, tools, err := pme.FindPlatformReleaseDependencies(ref)
 	if err != nil {
-		return nil, &arduino.NotFoundError{Message: tr("Can't find dependencies for platform %s", ref), Cause: err}
+		return &arduino.NotFoundError{Message: tr("Can't find dependencies for platform %s", ref), Cause: err}
 	}
 
-	if err := pm.UninstallPlatform(platform, taskCB); err != nil {
-		return nil, err
+	if err := pme.UninstallPlatform(platform, taskCB); err != nil {
+		return err
 	}
 
 	for _, tool := range tools {
-		if !pm.IsToolRequired(tool) {
+		if !pme.IsToolRequired(tool) {
 			taskCB(&rpc.TaskProgress{Name: tr("Uninstalling %s, tool is no more required", tool)})
-			pm.UninstallTool(tool, taskCB)
+			pme.UninstallTool(tool, taskCB)
 		}
 	}
 
-	if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
-		return nil, err
-	}
-
-	return &rpc.PlatformUninstallResponse{}, nil
+	return nil
 }
diff --git a/commands/core/upgrade.go b/commands/core/upgrade.go
index 6f55ab2367e..cee01487603 100644
--- a/commands/core/upgrade.go
+++ b/commands/core/upgrade.go
@@ -25,26 +25,31 @@ import (
 )
 
 // PlatformUpgrade FIXMEDOC
-func PlatformUpgrade(ctx context.Context, req *rpc.PlatformUpgradeRequest,
-	downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*rpc.PlatformUpgradeResponse, error) {
-
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
-		return nil, &arduino.InvalidInstanceError{}
+func PlatformUpgrade(ctx context.Context, req *rpc.PlatformUpgradeRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (*rpc.PlatformUpgradeResponse, error) {
+	upgrade := func() error {
+		pme, release := commands.GetPackageManagerExplorer(req)
+		if pme == nil {
+			return &arduino.InvalidInstanceError{}
+		}
+		defer release()
+
+		// Extract all PlatformReference to platforms that have updates
+		ref := &packagemanager.PlatformReference{
+			Package:              req.PlatformPackage,
+			PlatformArchitecture: req.Architecture,
+		}
+		if err := pme.DownloadAndInstallPlatformUpgrades(ref, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
+			return err
+		}
+
+		return nil
 	}
 
-	// Extract all PlatformReference to platforms that have updates
-	ref := &packagemanager.PlatformReference{
-		Package:              req.PlatformPackage,
-		PlatformArchitecture: req.Architecture,
-	}
-	if err := pm.DownloadAndInstallPlatformUpgrades(ref, downloadCB, taskCB, req.GetSkipPostInstall()); err != nil {
+	if err := upgrade(); err != nil {
 		return nil, err
 	}
-
 	if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
 		return nil, err
 	}
-
 	return &rpc.PlatformUpgradeResponse{}, nil
 }
diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go
index 96ec5daed6e..98a41468f4e 100644
--- a/commands/daemon/daemon.go
+++ b/commands/daemon/daemon.go
@@ -107,7 +107,7 @@ func (s *ArduinoCoreServerImpl) BoardListWatch(stream rpc.ArduinoCoreService_Boa
 		return err
 	}
 
-	eventsChan, closeWatcher, err := board.Watch(msg.Instance.Id)
+	eventsChan, closeWatcher, err := board.Watch(msg)
 	if err != nil {
 		return convertErrorToRPCStatus(err)
 	}
@@ -423,6 +423,19 @@ func (s *ArduinoCoreServerImpl) LibraryInstall(req *rpc.LibraryInstallRequest, s
 	return stream.Send(&rpc.LibraryInstallResponse{})
 }
 
+// LibraryUpgrade FIXMEDOC
+func (s *ArduinoCoreServerImpl) LibraryUpgrade(req *rpc.LibraryUpgradeRequest, stream rpc.ArduinoCoreService_LibraryUpgradeServer) error {
+	err := lib.LibraryUpgrade(
+		stream.Context(), req,
+		func(p *rpc.DownloadProgress) { stream.Send(&rpc.LibraryUpgradeResponse{Progress: p}) },
+		func(p *rpc.TaskProgress) { stream.Send(&rpc.LibraryUpgradeResponse{TaskProgress: p}) },
+	)
+	if err != nil {
+		return convertErrorToRPCStatus(err)
+	}
+	return stream.Send(&rpc.LibraryUpgradeResponse{})
+}
+
 // LibraryUninstall FIXMEDOC
 func (s *ArduinoCoreServerImpl) LibraryUninstall(req *rpc.LibraryUninstallRequest, stream rpc.ArduinoCoreService_LibraryUninstallServer) error {
 	err := lib.LibraryUninstall(stream.Context(), req,
@@ -436,7 +449,7 @@ func (s *ArduinoCoreServerImpl) LibraryUninstall(req *rpc.LibraryUninstallReques
 
 // LibraryUpgradeAll FIXMEDOC
 func (s *ArduinoCoreServerImpl) LibraryUpgradeAll(req *rpc.LibraryUpgradeAllRequest, stream rpc.ArduinoCoreService_LibraryUpgradeAllServer) error {
-	err := lib.LibraryUpgradeAll(req.GetInstance().GetId(),
+	err := lib.LibraryUpgradeAll(req,
 		func(p *rpc.DownloadProgress) { stream.Send(&rpc.LibraryUpgradeAllResponse{Progress: p}) },
 		func(p *rpc.TaskProgress) { stream.Send(&rpc.LibraryUpgradeAllResponse{TaskProgress: p}) },
 	)
@@ -470,7 +483,7 @@ func (s *ArduinoCoreServerImpl) ArchiveSketch(ctx context.Context, req *rpc.Arch
 	return resp, convertErrorToRPCStatus(err)
 }
 
-//ZipLibraryInstall FIXMEDOC
+// ZipLibraryInstall FIXMEDOC
 func (s *ArduinoCoreServerImpl) ZipLibraryInstall(req *rpc.ZipLibraryInstallRequest, stream rpc.ArduinoCoreService_ZipLibraryInstallServer) error {
 	err := lib.ZipLibraryInstall(
 		stream.Context(), req,
@@ -482,7 +495,7 @@ func (s *ArduinoCoreServerImpl) ZipLibraryInstall(req *rpc.ZipLibraryInstallRequ
 	return stream.Send(&rpc.ZipLibraryInstallResponse{})
 }
 
-//GitLibraryInstall FIXMEDOC
+// GitLibraryInstall FIXMEDOC
 func (s *ArduinoCoreServerImpl) GitLibraryInstall(req *rpc.GitLibraryInstallRequest, stream rpc.ArduinoCoreService_GitLibraryInstallServer) error {
 	err := lib.GitLibraryInstall(
 		stream.Context(), req,
diff --git a/commands/debug/debug.go b/commands/debug/debug.go
index 28731a7869f..c3a22e57982 100644
--- a/commands/debug/debug.go
+++ b/commands/debug/debug.go
@@ -45,8 +45,13 @@ var tr = i18n.Tr
 func Debug(ctx context.Context, req *dbg.DebugConfigRequest, inStream io.Reader, out io.Writer, interrupt <-chan os.Signal) (*dbg.DebugResponse, error) {
 
 	// Get debugging command line to run debugger
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	commandLine, err := getCommandLine(req, pm)
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
+
+	commandLine, err := getCommandLine(req, pme)
 	if err != nil {
 		return nil, err
 	}
@@ -62,7 +67,7 @@ func Debug(ctx context.Context, req *dbg.DebugConfigRequest, inStream io.Reader,
 	}
 	entry.Debug("Executing debugger")
 
-	cmd, err := executils.NewProcess(pm.GetEnvVarsForSpawnedProcess(), commandLine...)
+	cmd, err := executils.NewProcess(pme.GetEnvVarsForSpawnedProcess(), commandLine...)
 	if err != nil {
 		return nil, &arduino.FailedDebugError{Message: tr("Cannot execute debug tool"), Cause: err}
 	}
@@ -112,8 +117,8 @@ func Debug(ctx context.Context, req *dbg.DebugConfigRequest, inStream io.Reader,
 }
 
 // getCommandLine compose a debug command represented by a core recipe
-func getCommandLine(req *dbg.DebugConfigRequest, pm *packagemanager.PackageManager) ([]string, error) {
-	debugInfo, err := getDebugProperties(req, pm)
+func getCommandLine(req *dbg.DebugConfigRequest, pme *packagemanager.Explorer) ([]string, error) {
+	debugInfo, err := getDebugProperties(req, pme)
 	if err != nil {
 		return nil, err
 	}
diff --git a/commands/debug/debug_info.go b/commands/debug/debug_info.go
index e6a6a474296..c09a6776636 100644
--- a/commands/debug/debug_info.go
+++ b/commands/debug/debug_info.go
@@ -32,11 +32,15 @@ import (
 
 // GetDebugConfig returns metadata to start debugging with the specified board
 func GetDebugConfig(ctx context.Context, req *debug.DebugConfigRequest) (*debug.GetDebugConfigResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	return getDebugProperties(req, pm)
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
+	return getDebugProperties(req, pme)
 }
 
-func getDebugProperties(req *debug.DebugConfigRequest, pm *packagemanager.PackageManager) (*debug.GetDebugConfigResponse, error) {
+func getDebugProperties(req *debug.DebugConfigRequest, pme *packagemanager.Explorer) (*debug.GetDebugConfigResponse, error) {
 	// TODO: make a generic function to extract sketch from request
 	// and remove duplication in commands/compile.go
 	if req.GetSketchPath() == "" {
@@ -62,7 +66,7 @@ func getDebugProperties(req *debug.DebugConfigRequest, pm *packagemanager.Packag
 	}
 
 	// Find target board and board properties
-	_, platformRelease, board, boardProperties, referencedPlatformRelease, err := pm.ResolveFQBN(fqbn)
+	_, platformRelease, board, boardProperties, referencedPlatformRelease, err := pme.ResolveFQBN(fqbn)
 	if err != nil {
 		return nil, &arduino.UnknownFQBNError{Cause: err}
 	}
@@ -91,10 +95,10 @@ func getDebugProperties(req *debug.DebugConfigRequest, pm *packagemanager.Packag
 		}
 	}
 
-	for _, tool := range pm.GetAllInstalledToolsReleases() {
+	for _, tool := range pme.GetAllInstalledToolsReleases() {
 		toolProperties.Merge(tool.RuntimeProperties())
 	}
-	if requiredTools, err := pm.FindToolsRequiredForBoard(board); err == nil {
+	if requiredTools, err := pme.FindToolsRequiredForBoard(board); err == nil {
 		for _, requiredTool := range requiredTools {
 			logrus.WithField("tool", requiredTool).Info("Tool required for debug")
 			toolProperties.Merge(requiredTool.RuntimeProperties())
diff --git a/commands/debug/debug_test.go b/commands/debug/debug_test.go
index b495e4338be..5d9f91c8756 100644
--- a/commands/debug/debug_test.go
+++ b/commands/debug/debug_test.go
@@ -36,9 +36,9 @@ func TestGetCommandLine(t *testing.T) {
 	sketchPath := paths.New("testdata", sketch)
 	require.NoError(t, sketchPath.ToAbs())
 
-	pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "test")
-	pm.LoadHardwareFromDirectory(customHardware)
-	pm.LoadHardwareFromDirectory(dataDir)
+	pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
+	pmb.LoadHardwareFromDirectory(customHardware)
+	pmb.LoadHardwareFromDirectory(dataDir)
 
 	// Windows tools have .exe extension
 	var toolExtension = ""
@@ -61,7 +61,10 @@ func TestGetCommandLine(t *testing.T) {
 		fmt.Sprintf(" --file \"%s/arduino-test/samd/variants/arduino_zero/openocd_scripts/arduino_zero.cfg\"", customHardware) +
 		fmt.Sprintf(" -c \"gdb_port pipe\" -c \"telnet_port 0\" %s/build/arduino-test.samd.arduino_zero_edbg/hello.ino.elf", sketchPath)
 
-	command, err := getCommandLine(req, pm)
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+	command, err := getCommandLine(req, pme)
 	require.Nil(t, err)
 	commandToTest := strings.Join(command[:], " ")
 	require.Equal(t, filepath.FromSlash(goldCommand), filepath.FromSlash(commandToTest))
@@ -83,7 +86,7 @@ func TestGetCommandLine(t *testing.T) {
 		fmt.Sprintf(" --file \"%s/arduino-test/samd/variants/mkr1000/openocd_scripts/arduino_zero.cfg\"", customHardware) +
 		fmt.Sprintf(" -c \"gdb_port pipe\" -c \"telnet_port 0\" %s/build/arduino-test.samd.mkr1000/hello.ino.elf", sketchPath)
 
-	command2, err := getCommandLine(req2, pm)
+	command2, err := getCommandLine(req2, pme)
 	assert.Nil(t, err)
 	commandToTest2 := strings.Join(command2[:], " ")
 	assert.Equal(t, filepath.FromSlash(goldCommand2), filepath.FromSlash(commandToTest2))
diff --git a/commands/instances.go b/commands/instances.go
index 05b6f99f5db..bf4580059ad 100644
--- a/commands/instances.go
+++ b/commands/instances.go
@@ -21,6 +21,7 @@ import (
 	"net/url"
 	"os"
 	"strings"
+	"sync"
 
 	"github.com/arduino/arduino-cli/arduino"
 	"github.com/arduino/arduino-cli/arduino/cores"
@@ -45,62 +46,102 @@ import (
 
 var tr = i18n.Tr
 
-// this map contains all the running Arduino Core Services instances
-// referenced by an int32 handle
-var instances = map[int32]*CoreInstance{}
-var instancesCount int32 = 1
-
 // CoreInstance is an instance of the Arduino Core Services. The user can
 // instantiate as many as needed by providing a different configuration
 // for each one.
 type CoreInstance struct {
-	PackageManager *packagemanager.PackageManager
-	lm             *librariesmanager.LibrariesManager
+	pm *packagemanager.PackageManager
+	lm *librariesmanager.LibrariesManager
+}
+
+// coreInstancesContainer has methods to add an remove instances atomically.
+type coreInstancesContainer struct {
+	instances      map[int32]*CoreInstance
+	instancesCount int32
+	instancesMux   sync.Mutex
 }
 
-// InstanceContainer FIXMEDOC
-type InstanceContainer interface {
-	GetInstance() *rpc.Instance
+// instances contains all the running Arduino Core Services instances
+var instances = &coreInstancesContainer{
+	instances:      map[int32]*CoreInstance{},
+	instancesCount: 1,
 }
 
 // GetInstance returns a CoreInstance for the given ID, or nil if ID
 // doesn't exist
-func GetInstance(id int32) *CoreInstance {
-	return instances[id]
+func (c *coreInstancesContainer) GetInstance(id int32) *CoreInstance {
+	c.instancesMux.Lock()
+	defer c.instancesMux.Unlock()
+	return c.instances[id]
+}
+
+// AddAndAssignID saves the CoreInstance and assigns a unique ID to
+// retrieve it later
+func (c *coreInstancesContainer) AddAndAssignID(i *CoreInstance) int32 {
+	c.instancesMux.Lock()
+	defer c.instancesMux.Unlock()
+	id := c.instancesCount
+	c.instances[id] = i
+	c.instancesCount++
+	return id
+}
+
+// RemoveID removes the CoreInstance referenced by id. Returns true
+// if the operation is successful, or false if the CoreInstance does
+// not exist
+func (c *coreInstancesContainer) RemoveID(id int32) bool {
+	c.instancesMux.Lock()
+	defer c.instancesMux.Unlock()
+	if _, ok := c.instances[id]; !ok {
+		return false
+	}
+	delete(c.instances, id)
+	return true
 }
 
-// GetPackageManager returns a PackageManager for the given ID, or nil if
-// ID doesn't exist
-func GetPackageManager(id int32) *packagemanager.PackageManager {
-	i, ok := instances[id]
-	if !ok {
+// GetPackageManager returns a PackageManager. If the package manager is not found
+// (because the instance is invalid or has been destroyed), nil is returned.
+// Deprecated: use GetPackageManagerExplorer instead.
+func GetPackageManager(instance rpc.InstanceCommand) *packagemanager.PackageManager {
+	i := instances.GetInstance(instance.GetInstance().GetId())
+	if i == nil {
 		return nil
 	}
-	return i.PackageManager
+	return i.pm
 }
 
-// GetLibraryManager returns the library manager for the given instance ID
-func GetLibraryManager(instanceID int32) *librariesmanager.LibrariesManager {
-	i, ok := instances[instanceID]
-	if !ok {
+// GetPackageManagerExplorer returns a new package manager Explorer. The
+// explorer holds a read lock on the underlying PackageManager and it should
+// be released by calling the returned "release" function.
+func GetPackageManagerExplorer(req rpc.InstanceCommand) (explorer *packagemanager.Explorer, release func()) {
+	pm := GetPackageManager(req)
+	if pm == nil {
+		return nil, nil
+	}
+	return pm.NewExplorer()
+}
+
+// GetLibraryManager returns the library manager for the given instance.
+func GetLibraryManager(req rpc.InstanceCommand) *librariesmanager.LibrariesManager {
+	i := instances.GetInstance(req.GetInstance().GetId())
+	if i == nil {
 		return nil
 	}
 	return i.lm
 }
 
-func (instance *CoreInstance) installToolIfMissing(tool *cores.ToolRelease, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) (bool, error) {
-	if tool.IsInstalled() {
-		return false, nil
-	}
+func installTool(pm *packagemanager.PackageManager, tool *cores.ToolRelease, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+	pme, release := pm.NewExplorer()
+	defer release()
 	taskCB(&rpc.TaskProgress{Name: tr("Downloading missing tool %s", tool)})
-	if err := instance.PackageManager.DownloadToolRelease(tool, nil, downloadCB); err != nil {
-		return false, fmt.Errorf(tr("downloading %[1]s tool: %[2]s"), tool, err)
+	if err := pme.DownloadToolRelease(tool, nil, downloadCB); err != nil {
+		return fmt.Errorf(tr("downloading %[1]s tool: %[2]s"), tool, err)
 	}
 	taskCB(&rpc.TaskProgress{Completed: true})
-	if err := instance.PackageManager.InstallTool(tool, taskCB); err != nil {
-		return false, fmt.Errorf(tr("installing %[1]s tool: %[2]s"), tool, err)
+	if err := pme.InstallTool(tool, taskCB); err != nil {
+		return fmt.Errorf(tr("installing %[1]s tool: %[2]s"), tool, err)
 	}
-	return true, nil
+	return nil
 }
 
 // Create a new CoreInstance ready to be initialized, supporting directories are also created.
@@ -131,22 +172,20 @@ func Create(req *rpc.CreateRequest, extraUserAgent ...string) (*rpc.CreateRespon
 	for _, ua := range extraUserAgent {
 		userAgent += " " + ua
 	}
-	instance.PackageManager = packagemanager.NewPackageManager(
+	instance.pm = packagemanager.NewBuilder(
 		dataDir,
 		configuration.PackagesDir(configuration.Settings),
 		downloadsDir,
 		dataDir.Join("tmp"),
 		userAgent,
-	)
+	).Build()
 	instance.lm = librariesmanager.NewLibraryManager(
 		dataDir,
 		downloadsDir,
 	)
 
 	// Save instance
-	instanceID := instancesCount
-	instances[instanceID] = instance
-	instancesCount++
+	instanceID := instances.AddAndAssignID(instance)
 
 	return &rpc.CreateResponse{
 		Instance: &rpc.Instance{Id: instanceID},
@@ -166,7 +205,7 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
 	if reqInst == nil {
 		return &arduino.InvalidInstanceError{}
 	}
-	instance := instances[reqInst.GetId()]
+	instance := instances.GetInstance(reqInst.GetId())
 	if instance == nil {
 		return &arduino.InvalidInstanceError{}
 	}
@@ -201,14 +240,6 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
 		})
 	}
 
-	// We need to clear the PackageManager currently in use by this instance
-	// in case this is not the first Init on this instances, that might happen
-	// after reinitializing an instance after installing or uninstalling a core.
-	// If this is not done the information of the uninstall core is kept in memory,
-	// even if it should not.
-	pm := instance.PackageManager
-	pm.Clear()
-
 	// Try to extract profile if specified
 	var profile *sketch.Profile
 	if req.GetProfile() != "" {
@@ -231,111 +262,121 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
 		})
 	}
 
-	loadBuiltinTools := func() []error {
-		builtinPackage := pm.Packages.GetOrCreatePackage("builtin")
-		return pm.LoadToolsFromPackageDir(builtinPackage, pm.PackagesDir.Join("builtin", "tools"))
-	}
+	{
+		// We need to rebuild the PackageManager currently in use by this instance
+		// in case this is not the first Init on this instances, that might happen
+		// after reinitializing an instance after installing or uninstalling a core.
+		// If this is not done the information of the uninstall core is kept in memory,
+		// even if it should not.
+		pmb, commitPackageManager := instance.pm.NewBuilder()
 
-	// Load Platforms
-	if profile == nil {
-		for _, err := range pm.LoadHardware() {
-			s := &arduino.PlatformLoadingError{Cause: err}
-			responseError(s.ToRPCStatus())
-		}
-	} else {
-		// Load platforms from profile
-		errs := pm.LoadHardwareForProfile(
-			profile, true, downloadCallback, taskCallback,
-		)
-		for _, err := range errs {
-			s := &arduino.PlatformLoadingError{Cause: err}
-			responseError(s.ToRPCStatus())
+		loadBuiltinTools := func() []error {
+			builtinPackage := pmb.GetOrCreatePackage("builtin")
+			return pmb.LoadToolsFromPackageDir(builtinPackage, pmb.PackagesDir.Join("builtin", "tools"))
 		}
 
-		// Load "builtin" tools
-		_ = loadBuiltinTools()
-	}
+		// Load Platforms
+		if profile == nil {
+			for _, err := range pmb.LoadHardware() {
+				s := &arduino.PlatformLoadingError{Cause: err}
+				responseError(s.ToRPCStatus())
+			}
+		} else {
+			// Load platforms from profile
+			errs := pmb.LoadHardwareForProfile(
+				profile, true, downloadCallback, taskCallback,
+			)
+			for _, err := range errs {
+				s := &arduino.PlatformLoadingError{Cause: err}
+				responseError(s.ToRPCStatus())
+			}
 
-	// Load packages index
-	urls := []string{globals.DefaultIndexURL}
-	if profile == nil {
-		urls = append(urls, configuration.Settings.GetStringSlice("board_manager.additional_urls")...)
-	}
-	for _, u := range urls {
-		URL, err := utils.URLParse(u)
-		if err != nil {
-			s := status.Newf(codes.InvalidArgument, tr("Invalid additional URL: %v"), err)
-			responseError(s)
-			continue
+			// Load "builtin" tools
+			_ = loadBuiltinTools()
 		}
 
-		if URL.Scheme == "file" {
-			_, err := pm.LoadPackageIndexFromFile(paths.New(URL.Path))
+		// Load packages index
+		urls := []string{globals.DefaultIndexURL}
+		if profile == nil {
+			urls = append(urls, configuration.Settings.GetStringSlice("board_manager.additional_urls")...)
+		}
+		for _, u := range urls {
+			URL, err := utils.URLParse(u)
 			if err != nil {
+				s := status.Newf(codes.InvalidArgument, tr("Invalid additional URL: %v"), err)
+				responseError(s)
+				continue
+			}
+
+			if URL.Scheme == "file" {
+				_, err := pmb.LoadPackageIndexFromFile(paths.New(URL.Path))
+				if err != nil {
+					s := status.Newf(codes.FailedPrecondition, tr("Loading index file: %v"), err)
+					responseError(s)
+				}
+				continue
+			}
+
+			if err := pmb.LoadPackageIndex(URL); err != nil {
 				s := status.Newf(codes.FailedPrecondition, tr("Loading index file: %v"), err)
 				responseError(s)
 			}
-			continue
 		}
 
-		if err := pm.LoadPackageIndex(URL); err != nil {
-			s := status.Newf(codes.FailedPrecondition, tr("Loading index file: %v"), err)
-			responseError(s)
+		// We load hardware before verifying builtin tools are installed
+		// otherwise we wouldn't find them and reinstall them each time
+		// and they would never get reloaded.
+
+		builtinToolsToInstall := []*cores.ToolRelease{}
+		for name, tool := range pmb.GetOrCreatePackage("builtin").Tools {
+			latest := tool.LatestRelease()
+			if latest == nil {
+				s := status.Newf(codes.Internal, tr("can't find latest release of tool %s", name))
+				responseError(s)
+			} else if !latest.IsInstalled() {
+				builtinToolsToInstall = append(builtinToolsToInstall, latest)
+			}
 		}
-	}
 
-	// We load hardware before verifying builtin tools are installed
-	// otherwise we wouldn't find them and reinstall them each time
-	// and they would never get reloaded.
+		// Install builtin tools if necessary
+		if len(builtinToolsToInstall) > 0 {
+			for _, toolRelease := range builtinToolsToInstall {
+				if err := installTool(pmb.Build(), toolRelease, downloadCallback, taskCallback); err != nil {
+					s := status.Newf(codes.Internal, err.Error())
+					responseError(s)
+				}
+			}
 
-	builtinToolReleases := []*cores.ToolRelease{}
-	for name, tool := range pm.Packages.GetOrCreatePackage("builtin").Tools {
-		latestRelease := tool.LatestRelease()
-		if latestRelease == nil {
-			s := status.Newf(codes.Internal, tr("can't find latest release of tool %s", name))
-			responseError(s)
-			continue
+			// We installed at least one builtin tool after loading hardware
+			// so we must reload again otherwise we would never found them.
+			for _, err := range loadBuiltinTools() {
+				s := &arduino.PlatformLoadingError{Cause: err}
+				responseError(s.ToRPCStatus())
+			}
 		}
-		builtinToolReleases = append(builtinToolReleases, latestRelease)
-	}
 
-	// Install tools if necessary
-	toolsHaveBeenInstalled := false
-	for _, toolRelease := range builtinToolReleases {
-		installed, err := instance.installToolIfMissing(toolRelease, downloadCallback, taskCallback)
-		if err != nil {
-			s := status.Newf(codes.Internal, err.Error())
-			responseError(s)
-			continue
-		}
-		toolsHaveBeenInstalled = toolsHaveBeenInstalled || installed
+		commitPackageManager()
 	}
 
-	if toolsHaveBeenInstalled {
-		// We installed at least one new tool after loading hardware
-		// so we must reload again otherwise we would never found them.
-		for _, err := range loadBuiltinTools() {
-			s := &arduino.PlatformLoadingError{Cause: err}
-			responseError(s.ToRPCStatus())
-		}
-	}
+	pme, release := instance.pm.NewExplorer()
+	defer release()
 
-	for _, err := range pm.LoadDiscoveries() {
+	for _, err := range pme.LoadDiscoveries() {
 		s := &arduino.PlatformLoadingError{Cause: err}
 		responseError(s.ToRPCStatus())
 	}
 
 	// Create library manager and add libraries directories
 	lm := librariesmanager.NewLibraryManager(
-		pm.IndexDir,
-		pm.DownloadDir,
+		pme.IndexDir,
+		pme.DownloadDir,
 	)
 	instance.lm = lm
 
 	// Load libraries
-	for _, pack := range pm.Packages {
+	for _, pack := range pme.GetPackages() {
 		for _, platform := range pack.Platforms {
-			if platformRelease := pm.GetInstalledPlatformRelease(platform); platformRelease != nil {
+			if platformRelease := pme.GetInstalledPlatformRelease(platform); platformRelease != nil {
 				lm.AddPlatformReleaseLibrariesDir(platformRelease, libraries.PlatformBuiltIn)
 			}
 		}
@@ -412,19 +453,16 @@ func Init(req *rpc.InitRequest, responseCallback func(r *rpc.InitResponse)) erro
 
 // Destroy FIXMEDOC
 func Destroy(ctx context.Context, req *rpc.DestroyRequest) (*rpc.DestroyResponse, error) {
-	id := req.GetInstance().GetId()
-	if _, ok := instances[id]; !ok {
+	if ok := instances.RemoveID(req.GetInstance().GetId()); !ok {
 		return nil, &arduino.InvalidInstanceError{}
 	}
-
-	delete(instances, id)
 	return &rpc.DestroyResponse{}, nil
 }
 
 // UpdateLibrariesIndex updates the library_index.json
 func UpdateLibrariesIndex(ctx context.Context, req *rpc.UpdateLibrariesIndexRequest, downloadCB rpc.DownloadProgressCB) error {
 	logrus.Info("Updating libraries index")
-	lm := GetLibraryManager(req.GetInstance().GetId())
+	lm := GetLibraryManager(req)
 	if lm == nil {
 		return &arduino.InvalidInstanceError{}
 	}
@@ -453,9 +491,7 @@ func UpdateLibrariesIndex(ctx context.Context, req *rpc.UpdateLibrariesIndexRequ
 
 // UpdateIndex FIXMEDOC
 func UpdateIndex(ctx context.Context, req *rpc.UpdateIndexRequest, downloadCB rpc.DownloadProgressCB) (*rpc.UpdateIndexResponse, error) {
-	id := req.GetInstance().GetId()
-	_, ok := instances[id]
-	if !ok {
+	if instances.GetInstance(req.GetInstance().GetId()) == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
 
diff --git a/commands/lib/download.go b/commands/lib/download.go
index f845d4e73f0..1a384993b50 100644
--- a/commands/lib/download.go
+++ b/commands/lib/download.go
@@ -34,7 +34,7 @@ var tr = i18n.Tr
 func LibraryDownload(ctx context.Context, req *rpc.LibraryDownloadRequest, downloadCB rpc.DownloadProgressCB) (*rpc.LibraryDownloadResponse, error) {
 	logrus.Info("Executing `arduino-cli lib download`")
 
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
diff --git a/commands/lib/install.go b/commands/lib/install.go
index 8411e762cbe..880fb6f2e9b 100644
--- a/commands/lib/install.go
+++ b/commands/lib/install.go
@@ -31,7 +31,7 @@ import (
 // LibraryInstall FIXMEDOC
 func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
 
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return &arduino.InvalidInstanceError{}
 	}
@@ -148,9 +148,9 @@ func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *libraries
 	return nil
 }
 
-//ZipLibraryInstall FIXMEDOC
+// ZipLibraryInstall FIXMEDOC
 func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallRequest, taskCB rpc.TaskProgressCB) error {
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if err := lm.InstallZipLib(ctx, req.Path, req.Overwrite); err != nil {
 		return &arduino.FailedLibraryInstallError{Cause: err}
 	}
@@ -158,9 +158,9 @@ func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallRequest, t
 	return nil
 }
 
-//GitLibraryInstall FIXMEDOC
+// GitLibraryInstall FIXMEDOC
 func GitLibraryInstall(ctx context.Context, req *rpc.GitLibraryInstallRequest, taskCB rpc.TaskProgressCB) error {
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if err := lm.InstallGitLib(req.Url, req.Overwrite); err != nil {
 		return &arduino.FailedLibraryInstallError{Cause: err}
 	}
diff --git a/commands/lib/list.go b/commands/lib/list.go
index 216a692cb77..e22a4c191d9 100644
--- a/commands/lib/list.go
+++ b/commands/lib/list.go
@@ -35,12 +35,13 @@ type installedLib struct {
 
 // LibraryList FIXMEDOC
 func LibraryList(ctx context.Context, req *rpc.LibraryListRequest) (*rpc.LibraryListResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
@@ -54,7 +55,7 @@ func LibraryList(ctx context.Context, req *rpc.LibraryListRequest) (*rpc.Library
 		if err != nil {
 			return nil, &arduino.InvalidFQBNError{Cause: err}
 		}
-		_, boardPlatform, _, _, refBoardPlatform, err := pm.ResolveFQBN(fqbn)
+		_, boardPlatform, _, _, refBoardPlatform, err := pme.ResolveFQBN(fqbn)
 		if err != nil {
 			return nil, &arduino.UnknownFQBNError{Cause: err}
 		}
diff --git a/commands/lib/resolve_deps.go b/commands/lib/resolve_deps.go
index 241b2fcfe38..dc18591a0c5 100644
--- a/commands/lib/resolve_deps.go
+++ b/commands/lib/resolve_deps.go
@@ -27,7 +27,7 @@ import (
 
 // LibraryResolveDependencies FIXMEDOC
 func LibraryResolveDependencies(ctx context.Context, req *rpc.LibraryResolveDependenciesRequest) (*rpc.LibraryResolveDependenciesResponse, error) {
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
diff --git a/commands/lib/search.go b/commands/lib/search.go
index 591e5b9c9fd..f59a3ade5ae 100644
--- a/commands/lib/search.go
+++ b/commands/lib/search.go
@@ -29,7 +29,7 @@ import (
 
 // LibrarySearch FIXMEDOC
 func LibrarySearch(ctx context.Context, req *rpc.LibrarySearchRequest) (*rpc.LibrarySearchResponse, error) {
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
diff --git a/commands/lib/uninstall.go b/commands/lib/uninstall.go
index f3d80ccb361..c92e1da62bd 100644
--- a/commands/lib/uninstall.go
+++ b/commands/lib/uninstall.go
@@ -25,7 +25,7 @@ import (
 
 // LibraryUninstall FIXMEDOC
 func LibraryUninstall(ctx context.Context, req *rpc.LibraryUninstallRequest, taskCB rpc.TaskProgressCB) error {
-	lm := commands.GetLibraryManager(req.GetInstance().GetId())
+	lm := commands.GetLibraryManager(req)
 	ref, err := createLibIndexReference(lm, req)
 	if err != nil {
 		return &arduino.InvalidLibraryError{Cause: err}
diff --git a/commands/lib/upgrade.go b/commands/lib/upgrade.go
index ddfea91d97c..eeb911c46a0 100644
--- a/commands/lib/upgrade.go
+++ b/commands/lib/upgrade.go
@@ -16,6 +16,7 @@
 package lib
 
 import (
+	"context"
 	"errors"
 
 	"github.com/arduino/arduino-cli/arduino"
@@ -25,8 +26,8 @@ import (
 )
 
 // LibraryUpgradeAll upgrades all the available libraries
-func LibraryUpgradeAll(instanceID int32, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
-	lm := commands.GetLibraryManager(instanceID)
+func LibraryUpgradeAll(req *rpc.LibraryUpgradeAllRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+	lm := commands.GetLibraryManager(req)
 	if lm == nil {
 		return &arduino.InvalidInstanceError{}
 	}
@@ -35,25 +36,22 @@ func LibraryUpgradeAll(instanceID int32, downloadCB rpc.DownloadProgressCB, task
 		return err
 	}
 
-	if err := commands.Init(&rpc.InitRequest{Instance: &rpc.Instance{Id: instanceID}}, nil); err != nil {
+	if err := commands.Init(&rpc.InitRequest{Instance: req.GetInstance()}, nil); err != nil {
 		return err
 	}
 
 	return nil
 }
 
-// LibraryUpgrade upgrades only the given libraries
-func LibraryUpgrade(instanceID int32, libraryNames []string, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
-	lm := commands.GetLibraryManager(instanceID)
-	if lm == nil {
-		return &arduino.InvalidInstanceError{}
-	}
+// LibraryUpgrade upgrades a library
+func LibraryUpgrade(ctx context.Context, req *rpc.LibraryUpgradeRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
+	lm := commands.GetLibraryManager(req)
 
 	// get the libs to upgrade
-	libs := filterByName(listLibraries(lm, true, true), libraryNames)
+	lib := filterByName(listLibraries(lm, true, true), req.GetName())
 
 	// do it
-	return upgrade(lm, libs, downloadCB, taskCB)
+	return upgrade(lm, []*installedLib{lib}, downloadCB, taskCB)
 }
 
 func upgrade(lm *librariesmanager.LibrariesManager, libs []*installedLib, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error {
@@ -76,20 +74,11 @@ func upgrade(lm *librariesmanager.LibrariesManager, libs []*installedLib, downlo
 	return nil
 }
 
-func filterByName(libs []*installedLib, names []string) []*installedLib {
-	// put the names in a map to ease lookup
-	queryMap := make(map[string]struct{})
-	for _, name := range names {
-		queryMap[name] = struct{}{}
-	}
-
-	ret := []*installedLib{}
+func filterByName(libs []*installedLib, name string) *installedLib {
 	for _, lib := range libs {
-		// skip if library name wasn't in the query
-		if _, found := queryMap[lib.Library.RealName]; found {
-			ret = append(ret, lib)
+		if lib.Library.RealName == name {
+			return lib
 		}
 	}
-
-	return ret
+	return nil
 }
diff --git a/commands/monitor/monitor.go b/commands/monitor/monitor.go
index 6690621ffab..7b2a253e247 100644
--- a/commands/monitor/monitor.go
+++ b/commands/monitor/monitor.go
@@ -61,12 +61,13 @@ func (p *PortProxy) Close() error {
 // Monitor opens a communication port. It returns a PortProxy to communicate with the port and a PortDescriptor
 // that describes the available configuration settings.
 func Monitor(ctx context.Context, req *rpc.MonitorRequest) (*PortProxy, *pluggableMonitor.PortDescriptor, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
-	m, err := findMonitorForProtocolAndBoard(pm, req.GetPort().GetProtocol(), req.GetFqbn())
+	m, err := findMonitorForProtocolAndBoard(pme, req.GetPort().GetProtocol(), req.GetFqbn())
 	if err != nil {
 		return nil, nil, err
 	}
@@ -105,7 +106,7 @@ func Monitor(ctx context.Context, req *rpc.MonitorRequest) (*PortProxy, *pluggab
 	}, descriptor, nil
 }
 
-func findMonitorForProtocolAndBoard(pm *packagemanager.PackageManager, protocol, fqbn string) (*pluggableMonitor.PluggableMonitor, error) {
+func findMonitorForProtocolAndBoard(pme *packagemanager.Explorer, protocol, fqbn string) (*pluggableMonitor.PluggableMonitor, error) {
 	if protocol == "" {
 		return nil, &arduino.MissingPortProtocolError{}
 	}
@@ -119,7 +120,7 @@ func findMonitorForProtocolAndBoard(pm *packagemanager.PackageManager, protocol,
 			return nil, &arduino.InvalidFQBNError{Cause: err}
 		}
 
-		_, boardPlatform, _, boardProperties, _, err := pm.ResolveFQBN(fqbn)
+		_, boardPlatform, _, boardProperties, _, err := pme.ResolveFQBN(fqbn)
 		if err != nil {
 			return nil, &arduino.UnknownFQBNError{Cause: err}
 		}
@@ -140,7 +141,7 @@ func findMonitorForProtocolAndBoard(pm *packagemanager.PackageManager, protocol,
 
 	if monitorDepOrRecipe == nil {
 		// Otherwise look in all package for a suitable monitor
-		for _, platformRel := range pm.InstalledPlatformReleases() {
+		for _, platformRel := range pme.InstalledPlatformReleases() {
 			if mon, ok := platformRel.Monitors[protocol]; ok {
 				monitorDepOrRecipe = mon
 				break
@@ -153,7 +154,7 @@ func findMonitorForProtocolAndBoard(pm *packagemanager.PackageManager, protocol,
 	}
 
 	// If it is a monitor dependency, resolve tool and create a monitor client
-	tool := pm.FindMonitorDependency(monitorDepOrRecipe)
+	tool := pme.FindMonitorDependency(monitorDepOrRecipe)
 	if tool == nil {
 		return nil, &arduino.MonitorNotFoundError{Monitor: monitorDepOrRecipe.String()}
 	}
diff --git a/commands/monitor/settings.go b/commands/monitor/settings.go
index 77f1effad75..261f0cbc03e 100644
--- a/commands/monitor/settings.go
+++ b/commands/monitor/settings.go
@@ -26,12 +26,13 @@ import (
 
 // EnumerateMonitorPortSettings returns a description of the configuration settings of a monitor port
 func EnumerateMonitorPortSettings(ctx context.Context, req *rpc.EnumerateMonitorPortSettingsRequest) (*rpc.EnumerateMonitorPortSettingsResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
+	defer release()
 
-	m, err := findMonitorForProtocolAndBoard(pm, req.GetPortProtocol(), req.GetFqbn())
+	m, err := findMonitorForProtocolAndBoard(pme, req.GetPortProtocol(), req.GetFqbn())
 	if err != nil {
 		return nil, err
 	}
diff --git a/commands/upload/burnbootloader.go b/commands/upload/burnbootloader.go
index 8866bbdb837..f47e22fd239 100644
--- a/commands/upload/burnbootloader.go
+++ b/commands/upload/burnbootloader.go
@@ -19,6 +19,7 @@ import (
 	"context"
 	"io"
 
+	"github.com/arduino/arduino-cli/arduino"
 	"github.com/arduino/arduino-cli/commands"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	"github.com/sirupsen/logrus"
@@ -32,10 +33,14 @@ func BurnBootloader(ctx context.Context, req *rpc.BurnBootloaderRequest, outStre
 		WithField("programmer", req.GetProgrammer()).
 		Trace("BurnBootloader started", req.GetFqbn())
 
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
 
 	err := runProgramAction(
-		pm,
+		pme,
 		nil, // sketch
 		"",  // importFile
 		"",  // importDir
diff --git a/commands/upload/programmers_list.go b/commands/upload/programmers_list.go
index a804aec21e5..07433fca138 100644
--- a/commands/upload/programmers_list.go
+++ b/commands/upload/programmers_list.go
@@ -26,7 +26,11 @@ import (
 
 // ListProgrammersAvailableForUpload FIXMEDOC
 func ListProgrammersAvailableForUpload(ctx context.Context, req *rpc.ListProgrammersAvailableForUploadRequest) (*rpc.ListProgrammersAvailableForUploadResponse, error) {
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
 
 	fqbnIn := req.GetFqbn()
 	if fqbnIn == "" {
@@ -38,7 +42,7 @@ func ListProgrammersAvailableForUpload(ctx context.Context, req *rpc.ListProgram
 	}
 
 	// Find target platforms
-	_, platform, _, _, refPlatform, err := pm.ResolveFQBN(fqbn)
+	_, platform, _, _, refPlatform, err := pme.ResolveFQBN(fqbn)
 	if err != nil {
 		return nil, &arduino.UnknownFQBNError{Cause: err}
 	}
diff --git a/commands/upload/upload.go b/commands/upload/upload.go
index cfd85c406ce..87488a84337 100644
--- a/commands/upload/upload.go
+++ b/commands/upload/upload.go
@@ -47,8 +47,10 @@ func SupportedUserFields(ctx context.Context, req *rpc.SupportedUserFieldsReques
 		return nil, &arduino.MissingPortProtocolError{}
 	}
 
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
-	if pm == nil {
+	pme, release := commands.GetPackageManagerExplorer(req)
+	defer release()
+
+	if pme == nil {
 		return nil, &arduino.InvalidInstanceError{}
 	}
 
@@ -57,7 +59,7 @@ func SupportedUserFields(ctx context.Context, req *rpc.SupportedUserFieldsReques
 		return nil, &arduino.InvalidFQBNError{Cause: err}
 	}
 
-	_, platformRelease, _, boardProperties, _, err := pm.ResolveFQBN(fqbn)
+	_, platformRelease, _, boardProperties, _, err := pme.ResolveFQBN(fqbn)
 	if platformRelease == nil {
 		return nil, &arduino.PlatformNotFoundError{
 			Platform: fmt.Sprintf("%s:%s", fqbn.Package, fqbn.PlatformArch),
@@ -132,10 +134,14 @@ func Upload(ctx context.Context, req *rpc.UploadRequest, outStream io.Writer, er
 		return nil, &arduino.CantOpenSketchError{Cause: err}
 	}
 
-	pm := commands.GetPackageManager(req.GetInstance().GetId())
+	pme, release := commands.GetPackageManagerExplorer(req)
+	if pme == nil {
+		return nil, &arduino.InvalidInstanceError{}
+	}
+	defer release()
 
 	if err := runProgramAction(
-		pm,
+		pme,
 		sk,
 		req.GetImportFile(),
 		req.GetImportDir(),
@@ -178,7 +184,7 @@ func UsingProgrammer(ctx context.Context, req *rpc.UploadUsingProgrammerRequest,
 	return &rpc.UploadUsingProgrammerResponse{}, err
 }
 
-func runProgramAction(pm *packagemanager.PackageManager,
+func runProgramAction(pme *packagemanager.Explorer,
 	sk *sketch.Sketch,
 	importFile, importDir, fqbnIn string, port *rpc.Port,
 	programmerID string,
@@ -199,7 +205,7 @@ func runProgramAction(pm *packagemanager.PackageManager,
 	logrus.WithField("fqbn", fqbn).Tracef("Detected FQBN")
 
 	// Find target board and board properties
-	_, boardPlatform, board, boardProperties, buildPlatform, err := pm.ResolveFQBN(fqbn)
+	_, boardPlatform, board, boardProperties, buildPlatform, err := pme.ResolveFQBN(fqbn)
 	if boardPlatform == nil {
 		return &arduino.PlatformNotFoundError{
 			Platform: fmt.Sprintf("%s:%s", fqbn.Package, fqbn.PlatformArch),
@@ -264,8 +270,8 @@ func runProgramAction(pm *packagemanager.PackageManager,
 			Value:    uploadToolID}
 	} else if len(split) == 2 {
 		uploadToolID = split[1]
-		uploadToolPlatform = pm.GetInstalledPlatformRelease(
-			pm.FindPlatform(&packagemanager.PlatformReference{
+		uploadToolPlatform = pme.GetInstalledPlatformRelease(
+			pme.FindPlatform(&packagemanager.PlatformReference{
 				Package:              split[0],
 				PlatformArchitecture: boardPlatform.Platform.Architecture,
 			}),
@@ -286,10 +292,10 @@ func runProgramAction(pm *packagemanager.PackageManager,
 		uploadProperties.Merge(programmer.Properties)
 	}
 
-	for _, tool := range pm.GetAllInstalledToolsReleases() {
+	for _, tool := range pme.GetAllInstalledToolsReleases() {
 		uploadProperties.Merge(tool.RuntimeProperties())
 	}
-	if requiredTools, err := pm.FindToolsRequiredForBoard(board); err == nil {
+	if requiredTools, err := pme.FindToolsRequiredForBoard(board); err == nil {
 		for _, requiredTool := range requiredTools {
 			logrus.WithField("tool", requiredTool).Info("Tool required for upload")
 			if requiredTool.IsInstalled() {
@@ -450,7 +456,7 @@ func runProgramAction(pm *packagemanager.PackageManager,
 	}
 
 	// Run recipes for upload
-	toolEnv := pm.GetEnvVarsForSpawnedProcess()
+	toolEnv := pme.GetEnvVarsForSpawnedProcess()
 	if burnBootloader {
 		if err := runTool("erase.pattern", uploadProperties, outStream, errStream, verbose, dryRun, toolEnv); err != nil {
 			return &arduino.FailedUploadError{Message: tr("Failed chip erase"), Cause: err}
diff --git a/commands/upload/upload_test.go b/commands/upload/upload_test.go
index 1debccb2b8d..5ddd4898373 100644
--- a/commands/upload/upload_test.go
+++ b/commands/upload/upload_test.go
@@ -127,8 +127,8 @@ func TestDetermineBuildPathAndSketchName(t *testing.T) {
 }
 
 func TestUploadPropertiesComposition(t *testing.T) {
-	pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "test")
-	errs := pm.LoadHardwareFromDirectory(paths.New("testdata", "hardware"))
+	pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
+	errs := pmb.LoadHardwareFromDirectory(paths.New("testdata", "hardware"))
 	require.Len(t, errs, 0)
 	buildPath1 := paths.New("testdata", "build_path_1")
 	logrus.SetLevel(logrus.TraceLevel)
@@ -177,11 +177,15 @@ func TestUploadPropertiesComposition(t *testing.T) {
 			"BURN conf-board1 conf-two-general conf-two-bootloader $$VERBOSE-VERIFY$$ prog4protocol-bootloader port -bspeed -F0xFF " + cwd + "/testdata/hardware/alice/avr/bootloaders/niceboot/niceboot.hex\n"},
 	}
 
+	pm := pmb.Build()
+	pme, release := pm.NewExplorer()
+	defer release()
+
 	testRunner := func(t *testing.T, test test, verboseVerify bool) {
 		outStream := &bytes.Buffer{}
 		errStream := &bytes.Buffer{}
 		err := runProgramAction(
-			pm,
+			pme,
 			nil,                     // sketch
 			"",                      // importFile
 			test.importDir.String(), // importDir
diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md
index 80f7f28264e..37eaddfa47d 100644
--- a/docs/UPGRADING.md
+++ b/docs/UPGRADING.md
@@ -2,6 +2,270 @@
 
 Here you can find a list of migration guides to handle breaking changes between releases of the CLI.
 
+## 0.27.0
+
+### Breaking changes in golang API `github.com/arduino/arduino-cli/arduino/cores/packagemanager.PackageManager`
+
+The `PackageManager` API has been heavily refactored to correctly handle multitasking and concurrency. Many fields in
+the PackageManager object are now private. All the `PackageManager` methods have been moved into other objects. In
+particular:
+
+- the methods that query the `PackageManager` without changing its internal state, have been moved into the new
+  `Explorer` object
+- the methods that change the `PackageManager` internal state, have been moved into the new `Builder` object.
+
+The `Builder` object must be used to create a new `PackageManager`. Previously the function `NewPackageManager` was used
+to get a clean `PackageManager` object and then use the `LoadHardware*` methods to build it. Now the function
+`NewBuilder` must be used to create a `Builder`, run the `LoadHardware*` methods to load platforms, and finally call the
+`Builder.Build()` method to obtain the final `PackageManager`.
+
+Previously we did:
+
+```go
+pm := packagemanager.NewPackageManager(...)
+err = pm.LoadHardware()
+err = pm.LoadHardwareFromDirectories(...)
+err = pm.LoadHardwareFromDirectory(...)
+err = pm.LoadToolsFromPackageDir(...)
+err = pm.LoadToolsFromBundleDirectories(...)
+err = pm.LoadToolsFromBundleDirectory(...)
+pack = pm.GetOrCreatePackage("packagername")
+// ...use `pack` to tweak or load more hardware...
+err = pm.LoadPackageIndex(...)
+err = pm.LoadPackageIndexFromFile(...)
+err = pm.LoadHardwareForProfile(...)
+
+// ...use `pm` to implement business logic...
+```
+
+Now we must do:
+
+```go
+var pm *packagemanager.PackageManager
+
+{
+    pmb := packagemanager.Newbuilder(...)
+    err = pmb.LoadHardware()
+    err = pmb.LoadHardwareFromDirectories(...)
+    err = pmb.LoadHardwareFromDirectory(...)
+    err = pmb.LoadToolsFromPackageDir(...)
+    err = pmb.LoadToolsFromBundleDirectories(...)
+    err = pmb.LoadToolsFromBundleDirectory(...)
+    pack = pmb.GetOrCreatePackage("packagername")
+    // ...use `pack` to tweak or load more hardware...
+    err = pmb.LoadPackageIndex(...)
+    err = pmb.LoadPackageIndexFromFile(...)
+    err = pmb.LoadHardwareForProfile(...)
+    pm = pmb.Build()
+}
+
+// ...use `pm` to implement business logic...
+```
+
+It's not mandatory but highly recommended, to drop the `Builder` object once it has built the `PackageManager` (that's
+why in the example the `pmb` builder is created in a limited scope between braces).
+
+To query the `PackagerManager` now it is required to obtain an `Explorer` object through the
+`PackageManager.NewExplorer()` method.
+
+Previously we did:
+
+```go
+func DoStuff(pm *packagemanager.PackageManager, ...) {
+    // ...implement business logic through PackageManager methods...
+    ... := pm.Packages
+    ... := pm.CustomGlobalProperties
+    ... := pm.FindPlatform(...)
+    ... := pm.FindPlatformRelease(...)
+    ... := pm.FindPlatformReleaseDependencies(...)
+    ... := pm.DownloadToolRelease(...)
+    ... := pm.DownloadPlatformRelease(...)
+    ... := pm.IdentifyBoard(...)
+    ... := pm.DownloadAndInstallPlatformUpgrades(...)
+    ... := pm.DownloadAndInstallPlatformAndTools(...)
+    ... := pm.InstallPlatform(...)
+    ... := pm.InstallPlatformInDirectory(...)
+    ... := pm.RunPostInstallScript(...)
+    ... := pm.IsManagedPlatformRelease(...)
+    ... := pm.UninstallPlatform(...)
+    ... := pm.InstallTool(...)
+    ... := pm.IsManagedToolRelease(...)
+    ... := pm.UninstallTool(...)
+    ... := pm.IsToolRequired(...)
+    ... := pm.LoadDiscoveries(...)
+    ... := pm.GetProfile(...)
+    ... := pm.GetEnvVarsForSpawnedProcess(...)
+    ... := pm.DiscoveryManager(...)
+    ... := pm.FindPlatformReleaseProvidingBoardsWithVidPid(...)
+    ... := pm.FindBoardsWithVidPid(...)
+    ... := pm.FindBoardsWithID(...)
+    ... := pm.FindBoardWithFQBN(...)
+    ... := pm.ResolveFQBN(...)
+    ... := pm.Package(...)
+    ... := pm.GetInstalledPlatformRelease(...)
+    ... := pm.GetAllInstalledToolsReleases(...)
+    ... := pm.InstalledPlatformReleases(...)
+    ... := pm.InstalledBoards(...)
+    ... := pm.FindToolsRequiredFromPlatformRelease(...)
+    ... := pm.GetTool(...)
+    ... := pm.FindToolsRequiredForBoard(...)
+    ... := pm.FindToolDependency(...)
+    ... := pm.FindDiscoveryDependency(...)
+    ... := pm.FindMonitorDependency(...)
+}
+```
+
+Now we must obtain the `Explorer` object to access the same methods, moreover, we must call the `release` callback
+function once we complete the task:
+
+```go
+func DoStuff(pm *packagemanager.PackageManager, ...) {
+    pme, release := pm.NewExplorer()
+    defer release()
+
+    ... := pme.GetPackages()
+    ... := pme.GetCustomGlobalProperties()
+    ... := pme.FindPlatform(...)
+    ... := pme.FindPlatformRelease(...)
+    ... := pme.FindPlatformReleaseDependencies(...)
+    ... := pme.DownloadToolRelease(...)
+    ... := pme.DownloadPlatformRelease(...)
+    ... := pme.IdentifyBoard(...)
+    ... := pme.DownloadAndInstallPlatformUpgrades(...)
+    ... := pme.DownloadAndInstallPlatformAndTools(...)
+    ... := pme.InstallPlatform(...)
+    ... := pme.InstallPlatformInDirectory(...)
+    ... := pme.RunPostInstallScript(...)
+    ... := pme.IsManagedPlatformRelease(...)
+    ... := pme.UninstallPlatform(...)
+    ... := pme.InstallTool(...)
+    ... := pme.IsManagedToolRelease(...)
+    ... := pme.UninstallTool(...)
+    ... := pme.IsToolRequired(...)
+    ... := pme.LoadDiscoveries(...)
+    ... := pme.GetProfile(...)
+    ... := pme.GetEnvVarsForSpawnedProcess(...)
+    ... := pme.DiscoveryManager(...)
+    ... := pme.FindPlatformReleaseProvidingBoardsWithVidPid(...)
+    ... := pme.FindBoardsWithVidPid(...)
+    ... := pme.FindBoardsWithID(...)
+    ... := pme.FindBoardWithFQBN(...)
+    ... := pme.ResolveFQBN(...)
+    ... := pme.Package(...)
+    ... := pme.GetInstalledPlatformRelease(...)
+    ... := pme.GetAllInstalledToolsReleases(...)
+    ... := pme.InstalledPlatformReleases(...)
+    ... := pme.InstalledBoards(...)
+    ... := pme.FindToolsRequiredFromPlatformRelease(...)
+    ... := pme.GetTool(...)
+    ... := pme.FindToolsRequiredForBoard(...)
+    ... := pme.FindToolDependency(...)
+    ... := pme.FindDiscoveryDependency(...)
+    ... := pme.FindMonitorDependency(...)
+}
+```
+
+The `Explorer` object keeps a read-lock on the underlying `PackageManager` that must be released once the task is done
+by calling the `release` callback function. This ensures that no other task will change the status of the
+`PackageManager` while the current task is in progress.
+
+The `PackageManager.Clean()` method has been removed and replaced by the methods:
+
+- `PackageManager.NewBuilder() (*Builder, commit func())`
+- `Builder.BuildIntoExistingPackageManager(target *PackageManager)`
+
+Previously, to update a `PackageManager` instance we did:
+
+```go
+func Reload(pm *packagemanager.PackageManager) {
+    pm.Clear()
+    ... = pm.LoadHardware(...)
+    // ...other pm.Load* calls...
+}
+```
+
+now we have two options:
+
+```go
+func Reload(pm *packagemanager.PackageManager) {
+    // Create a new builder and build a package manager
+    pmb := packagemanager.NewBuilder(.../* config params */)
+    ... = pmb.LoadHardware(...)
+    // ...other pmb.Load* calls...
+
+    // apply the changes to the original pm
+    pmb.BuildIntoExistingPackageManager(pm)
+}
+```
+
+in this case, we create a new `Builder` with the given config params and once the package manager is built we apply the
+changes atomically with `BuildIntoExistingPackageManager`. This procedure may be even more simplified with:
+
+```go
+func Reload(pm *packagemanager.PackageManager) {
+    // Create a new builder using the same config params
+    // as the original package manager
+    pmb, commit := pm.NewBuilder()
+
+    // build the new package manager
+    ... = pmb.LoadHardware(...)
+    // ...other pmb.Load* calls...
+
+    // apply the changes to the original pm
+    commit()
+}
+```
+
+In this case, we don't even need to bother to provide the configuration parameters because they are taken from the
+previous `PackageManager` instance.
+
+### Some gRPC-mapped methods now accepts the gRPC request instead of the instance ID as parameter
+
+The following methods in subpackages of `github.com/arduino/arduino-cli/commands/*`:
+
+```go
+func Watch(instanceID int32) (<-chan *rpc.BoardListWatchResponse, func(), error) { ... }
+func LibraryUpgradeAll(instanceID int32, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
+func LibraryUpgrade(instanceID int32, libraryNames []string, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
+```
+
+have been changed to:
+
+```go
+func Watch(req *rpc.BoardListWatchRequest) (<-chan *rpc.BoardListWatchResponse, func(), error) { ... }
+func LibraryUpgradeAll(req *rpc.LibraryUpgradeAllRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
+func LibraryUpgrade(ctx context.Context, req *rpc.LibraryUpgradeRequest, downloadCB rpc.DownloadProgressCB, taskCB rpc.TaskProgressCB) error { ... }
+```
+
+The following methods in package `github.com/arduino/arduino-cli/commands`
+
+```go
+func GetInstance(id int32) *CoreInstance { ... }
+func GetPackageManager(id int32) *packagemanager.PackageManager { ... }
+func GetLibraryManager(instanceID int32) *librariesmanager.LibrariesManager { ... }
+```
+
+have been changed to:
+
+```go
+func GetPackageManager(instance rpc.InstanceCommand) *packagemanager.PackageManager { ... } // Deprecated
+func GetPackageManagerExplorer(req rpc.InstanceCommand) (explorer *packagemanager.Explorer, release func()) { ... }
+func GetLibraryManager(req rpc.InstanceCommand) *librariesmanager.LibrariesManager { ... }
+```
+
+Old code passing the `instanceID` inside the gRPC request must be changed to pass directly the whole gRPC request, for
+example:
+
+```go
+	eventsChan, closeWatcher, err := board.Watch(req.Instance.Id)
+```
+
+must be changed to:
+
+```go
+	eventsChan, closeWatcher, err := board.Watch(req)
+```
+
 ## 0.26.0
 
 ### `github.com/arduino/arduino-cli/commands.DownloadToolRelease`, and `InstallToolRelease` functions have been removed
diff --git a/legacy/builder/builder_utils/utils.go b/legacy/builder/builder_utils/utils.go
index 27ee64d7e6e..e2a651a98a8 100644
--- a/legacy/builder/builder_utils/utils.go
+++ b/legacy/builder/builder_utils/utils.go
@@ -181,6 +181,7 @@ func compileFileWithRecipe(ctx *types.Context, sourcePath *paths.Path, source *p
 	if err != nil {
 		return nil, errors.WithStack(err)
 	}
+
 	command, err := PrepareCommandForRecipe(properties, recipe, false, ctx.PackageManager.GetEnvVarsForSpawnedProcess())
 	if err != nil {
 		return nil, errors.WithStack(err)
diff --git a/legacy/builder/container_setup.go b/legacy/builder/container_setup.go
index 1d9e829fd7c..bc6398117a6 100644
--- a/legacy/builder/container_setup.go
+++ b/legacy/builder/container_setup.go
@@ -35,7 +35,6 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(ctx *types.Context)
 		&PlatformKeysRewriteLoader{},
 		&RewriteHardwareKeys{},
 		&TargetBoardResolver{},
-		&ToolsLoader{},
 		&LibrariesLoader{},
 	}
 
diff --git a/legacy/builder/hardware_loader.go b/legacy/builder/hardware_loader.go
index 9ea44e606a0..c1cfcbba1f7 100644
--- a/legacy/builder/hardware_loader.go
+++ b/legacy/builder/hardware_loader.go
@@ -26,8 +26,8 @@ func (s *HardwareLoader) Run(ctx *types.Context) error {
 	if ctx.PackageManager == nil {
 		// This should happen only on legacy arduino-builder.
 		// Hopefully this piece will be removed once the legacy package will be cleanedup.
-		pm := packagemanager.NewPackageManager(nil, nil, nil, nil, "arduino-builder")
-		errs := pm.LoadHardwareFromDirectories(ctx.HardwareDirs)
+		pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "arduino-builder")
+		errs := pmb.LoadHardwareFromDirectories(ctx.HardwareDirs)
 		if ctx.Verbose {
 			// With the refactoring of the initialization step of the CLI we changed how
 			// errors are returned when loading platforms and libraries, that meant returning a list of
@@ -39,8 +39,22 @@ func (s *HardwareLoader) Run(ctx *types.Context) error {
 				ctx.Info(tr("Error loading hardware platform: %[1]s", err.Error()))
 			}
 		}
-		ctx.PackageManager = pm
+
+		if !ctx.CanUseCachedTools {
+			if ctx.BuiltInToolsDirs != nil {
+				pmb.LoadToolsFromBundleDirectories(ctx.BuiltInToolsDirs)
+			}
+
+			ctx.CanUseCachedTools = true
+		}
+
+		pm := pmb.Build()
+		pme, _ /* never release... */ := pm.NewExplorer()
+
+		ctx.AllTools = pme.GetAllInstalledToolsReleases()
+		ctx.PackageManager = pme
 	}
-	ctx.Hardware = ctx.PackageManager.Packages
+
+	ctx.Hardware = ctx.PackageManager.GetPackages()
 	return nil
 }
diff --git a/legacy/builder/setup_build_properties.go b/legacy/builder/setup_build_properties.go
index 029ebb5860e..8b8e2cd799c 100644
--- a/legacy/builder/setup_build_properties.go
+++ b/legacy/builder/setup_build_properties.go
@@ -124,7 +124,7 @@ func (s *SetupBuildProperties) Run(ctx *types.Context) error {
 	buildProperties.Set("extra.time.zone", strconv.Itoa(timeutils.TimezoneOffsetNoDST(now)))
 	buildProperties.Set("extra.time.dst", strconv.Itoa(timeutils.DaylightSavingsOffset(now)))
 
-	buildProperties.Merge(ctx.PackageManager.CustomGlobalProperties)
+	buildProperties.Merge(ctx.PackageManager.GetCustomGlobalProperties())
 
 	keychainProp := buildProperties.ContainsKey("build.keys.keychain")
 	signProp := buildProperties.ContainsKey("build.keys.sign_key")
diff --git a/legacy/builder/target_board_resolver.go b/legacy/builder/target_board_resolver.go
index 3a6393b2fd6..fa5e34b7db6 100644
--- a/legacy/builder/target_board_resolver.go
+++ b/legacy/builder/target_board_resolver.go
@@ -50,11 +50,17 @@ func (s *TargetBoardResolver) Run(ctx *types.Context) error {
 			targetBoard.String(), "'build.board'", defaultBuildBoard))
 	}
 
+	requiredTools, err := ctx.PackageManager.FindToolsRequiredForBoard(targetBoard)
+	if err != nil {
+		return err
+	}
+
 	ctx.BuildCore = core
 	ctx.TargetBoard = targetBoard
 	ctx.TargetBoardBuildProperties = buildProperties
 	ctx.TargetPlatform = targetPlatform
 	ctx.TargetPackage = targetPackage
 	ctx.ActualPlatform = actualPlatform
+	ctx.RequiredTools = requiredTools
 	return nil
 }
diff --git a/legacy/builder/test/setup_build_properties_test.go b/legacy/builder/test/setup_build_properties_test.go
index e9b9a800c51..44d64eeba3a 100644
--- a/legacy/builder/test/setup_build_properties_test.go
+++ b/legacy/builder/test/setup_build_properties_test.go
@@ -43,7 +43,6 @@ func TestSetupBuildProperties(t *testing.T) {
 		&builder.AddAdditionalEntriesToContext{},
 		&builder.HardwareLoader{},
 		&builder.TargetBoardResolver{},
-		&builder.ToolsLoader{},
 		&builder.SketchLoader{},
 		&builder.SetupBuildProperties{},
 	}
@@ -111,7 +110,6 @@ func TestSetupBuildPropertiesWithSomeCustomOverrides(t *testing.T) {
 		&builder.AddAdditionalEntriesToContext{},
 		&builder.HardwareLoader{},
 		&builder.TargetBoardResolver{},
-		&builder.ToolsLoader{},
 		&builder.SketchLoader{},
 		&builder.SetupBuildProperties{},
 		&builder.SetCustomBuildProperties{},
@@ -150,7 +148,6 @@ func TestSetupBuildPropertiesUserHardware(t *testing.T) {
 		&builder.AddAdditionalEntriesToContext{},
 		&builder.HardwareLoader{},
 		&builder.TargetBoardResolver{},
-		&builder.ToolsLoader{},
 		&builder.SketchLoader{},
 		&builder.SetupBuildProperties{},
 	}
diff --git a/legacy/builder/test/tools_loader_test.go b/legacy/builder/test/tools_loader_test.go
index 8711bdf24bf..9d631822df4 100644
--- a/legacy/builder/test/tools_loader_test.go
+++ b/legacy/builder/test/tools_loader_test.go
@@ -68,7 +68,6 @@ func TestLoadTools(t *testing.T) {
 	}
 
 	NoError(t, (&builder.HardwareLoader{}).Run(ctx))
-	NoError(t, (&builder.ToolsLoader{}).Run(ctx))
 
 	tools := ctx.AllTools
 	require.Equal(t, 9, len(tools))
@@ -111,7 +110,6 @@ func TestLoadToolsWithBoardManagerFolderStructure(t *testing.T) {
 	}
 
 	NoError(t, (&builder.HardwareLoader{}).Run(ctx))
-	NoError(t, (&builder.ToolsLoader{}).Run(ctx))
 
 	tools := ctx.AllTools
 	require.Equal(t, 3, len(tools))
@@ -138,7 +136,6 @@ func TestLoadLotsOfTools(t *testing.T) {
 	}
 
 	NoError(t, (&builder.HardwareLoader{}).Run(ctx))
-	NoError(t, (&builder.ToolsLoader{}).Run(ctx))
 
 	tools := ctx.AllTools
 	require.Equal(t, 12, len(tools))
diff --git a/legacy/builder/tools_loader.go b/legacy/builder/tools_loader.go
deleted file mode 100644
index 20a90618007..00000000000
--- a/legacy/builder/tools_loader.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// This file is part of arduino-cli.
-//
-// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-//
-// This software is released under the GNU General Public License version 3,
-// which covers the main part of arduino-cli.
-// The terms of this license can be found at:
-// https://www.gnu.org/licenses/gpl-3.0.en.html
-//
-// You can be released from the requirements of the above licenses by purchasing
-// a commercial license. Buying such a license is mandatory if you want to
-// modify or otherwise use the software for commercial activities involving the
-// Arduino software without disclosing the source code of your own applications.
-// To purchase a commercial license, send an email to license@arduino.cc.
-
-package builder
-
-import (
-	"github.com/arduino/arduino-cli/legacy/builder/types"
-	"github.com/arduino/go-paths-helper"
-)
-
-type ToolsLoader struct{}
-
-func (s *ToolsLoader) Run(ctx *types.Context) error {
-	if ctx.CanUseCachedTools {
-		return nil
-	}
-
-	builtinFolders := paths.NewPathList()
-	if ctx.BuiltInToolsDirs != nil {
-		builtinFolders = ctx.BuiltInToolsDirs
-	}
-
-	pm := ctx.PackageManager
-	pm.LoadToolsFromBundleDirectories(builtinFolders)
-
-	ctx.CanUseCachedTools = true
-	ctx.AllTools = pm.GetAllInstalledToolsReleases()
-
-	if ctx.TargetBoard != nil {
-		requiredTools, err := pm.FindToolsRequiredForBoard(ctx.TargetBoard)
-		if err != nil {
-			return err
-		}
-		ctx.RequiredTools = requiredTools
-	}
-
-	return nil
-}
diff --git a/legacy/builder/types/context.go b/legacy/builder/types/context.go
index b311c9ae088..16b8d9c8acc 100644
--- a/legacy/builder/types/context.go
+++ b/legacy/builder/types/context.go
@@ -82,7 +82,7 @@ type Context struct {
 	BuildOptionsJson         string
 	BuildOptionsJsonPrevious string
 
-	PackageManager             *packagemanager.PackageManager
+	PackageManager             *packagemanager.Explorer
 	Hardware                   cores.Packages
 	AllTools                   []*cores.ToolRelease
 	RequiredTools              []*cores.ToolRelease
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.pb.go b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
index 87a0e839335..10a865f913b 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
@@ -1582,7 +1582,7 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
 	0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x72, 0x63, 0x68,
 	0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x32, 0xad, 0x27, 0x0a, 0x12, 0x41, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x43, 0x6f, 0x72,
+	0x65, 0x32, 0xa8, 0x28, 0x0a, 0x12, 0x41, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x43, 0x6f, 0x72,
 	0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61,
 	0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
@@ -1823,86 +1823,93 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
 	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
 	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
-	0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72,
+	0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61,
+	0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a,
+	0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61,
+	0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+	0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
+	0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
 	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49,
 	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e,
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69,
 	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12,
-	0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55,
+	0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
 	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a,
-	0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41,
-	0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c,
-	0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67,
-	0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
-	0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73,
-	0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73,
-	0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65,
-	0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41,
+	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a,
+	0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44,
+	0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+	0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52,
+	0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69,
+	0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12,
+	0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
 	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e,
-	0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
-	0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f,
-	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
-	0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01,
-	0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
-	0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3f,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
-	0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74,
-	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75,
+	0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75,
 	0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72,
-	0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d,
-	0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f,
-	0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x33,
+	0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65,
+	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
+	0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74,
+	0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74,
+	0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x48, 0x5a, 0x46,
+	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72,
+	0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c,
+	0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1971,44 +1978,46 @@ var file_cc_arduino_cli_commands_v1_commands_proto_goTypes = []interface{}{
 	(*PlatformListRequest)(nil),                       // 49: cc.arduino.cli.commands.v1.PlatformListRequest
 	(*LibraryDownloadRequest)(nil),                    // 50: cc.arduino.cli.commands.v1.LibraryDownloadRequest
 	(*LibraryInstallRequest)(nil),                     // 51: cc.arduino.cli.commands.v1.LibraryInstallRequest
-	(*ZipLibraryInstallRequest)(nil),                  // 52: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
-	(*GitLibraryInstallRequest)(nil),                  // 53: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
-	(*LibraryUninstallRequest)(nil),                   // 54: cc.arduino.cli.commands.v1.LibraryUninstallRequest
-	(*LibraryUpgradeAllRequest)(nil),                  // 55: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
-	(*LibraryResolveDependenciesRequest)(nil),         // 56: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
-	(*LibrarySearchRequest)(nil),                      // 57: cc.arduino.cli.commands.v1.LibrarySearchRequest
-	(*LibraryListRequest)(nil),                        // 58: cc.arduino.cli.commands.v1.LibraryListRequest
-	(*MonitorRequest)(nil),                            // 59: cc.arduino.cli.commands.v1.MonitorRequest
-	(*EnumerateMonitorPortSettingsRequest)(nil),       // 60: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
-	(*BoardDetailsResponse)(nil),                      // 61: cc.arduino.cli.commands.v1.BoardDetailsResponse
-	(*BoardAttachResponse)(nil),                       // 62: cc.arduino.cli.commands.v1.BoardAttachResponse
-	(*BoardListResponse)(nil),                         // 63: cc.arduino.cli.commands.v1.BoardListResponse
-	(*BoardListAllResponse)(nil),                      // 64: cc.arduino.cli.commands.v1.BoardListAllResponse
-	(*BoardSearchResponse)(nil),                       // 65: cc.arduino.cli.commands.v1.BoardSearchResponse
-	(*BoardListWatchResponse)(nil),                    // 66: cc.arduino.cli.commands.v1.BoardListWatchResponse
-	(*CompileResponse)(nil),                           // 67: cc.arduino.cli.commands.v1.CompileResponse
-	(*PlatformInstallResponse)(nil),                   // 68: cc.arduino.cli.commands.v1.PlatformInstallResponse
-	(*PlatformDownloadResponse)(nil),                  // 69: cc.arduino.cli.commands.v1.PlatformDownloadResponse
-	(*PlatformUninstallResponse)(nil),                 // 70: cc.arduino.cli.commands.v1.PlatformUninstallResponse
-	(*PlatformUpgradeResponse)(nil),                   // 71: cc.arduino.cli.commands.v1.PlatformUpgradeResponse
-	(*UploadResponse)(nil),                            // 72: cc.arduino.cli.commands.v1.UploadResponse
-	(*UploadUsingProgrammerResponse)(nil),             // 73: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
-	(*SupportedUserFieldsResponse)(nil),               // 74: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
-	(*ListProgrammersAvailableForUploadResponse)(nil), // 75: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
-	(*BurnBootloaderResponse)(nil),                    // 76: cc.arduino.cli.commands.v1.BurnBootloaderResponse
-	(*PlatformSearchResponse)(nil),                    // 77: cc.arduino.cli.commands.v1.PlatformSearchResponse
-	(*PlatformListResponse)(nil),                      // 78: cc.arduino.cli.commands.v1.PlatformListResponse
-	(*LibraryDownloadResponse)(nil),                   // 79: cc.arduino.cli.commands.v1.LibraryDownloadResponse
-	(*LibraryInstallResponse)(nil),                    // 80: cc.arduino.cli.commands.v1.LibraryInstallResponse
-	(*ZipLibraryInstallResponse)(nil),                 // 81: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
-	(*GitLibraryInstallResponse)(nil),                 // 82: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
-	(*LibraryUninstallResponse)(nil),                  // 83: cc.arduino.cli.commands.v1.LibraryUninstallResponse
-	(*LibraryUpgradeAllResponse)(nil),                 // 84: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
-	(*LibraryResolveDependenciesResponse)(nil),        // 85: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
-	(*LibrarySearchResponse)(nil),                     // 86: cc.arduino.cli.commands.v1.LibrarySearchResponse
-	(*LibraryListResponse)(nil),                       // 87: cc.arduino.cli.commands.v1.LibraryListResponse
-	(*MonitorResponse)(nil),                           // 88: cc.arduino.cli.commands.v1.MonitorResponse
-	(*EnumerateMonitorPortSettingsResponse)(nil),      // 89: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
+	(*LibraryUpgradeRequest)(nil),                     // 52: cc.arduino.cli.commands.v1.LibraryUpgradeRequest
+	(*ZipLibraryInstallRequest)(nil),                  // 53: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
+	(*GitLibraryInstallRequest)(nil),                  // 54: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
+	(*LibraryUninstallRequest)(nil),                   // 55: cc.arduino.cli.commands.v1.LibraryUninstallRequest
+	(*LibraryUpgradeAllRequest)(nil),                  // 56: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
+	(*LibraryResolveDependenciesRequest)(nil),         // 57: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
+	(*LibrarySearchRequest)(nil),                      // 58: cc.arduino.cli.commands.v1.LibrarySearchRequest
+	(*LibraryListRequest)(nil),                        // 59: cc.arduino.cli.commands.v1.LibraryListRequest
+	(*MonitorRequest)(nil),                            // 60: cc.arduino.cli.commands.v1.MonitorRequest
+	(*EnumerateMonitorPortSettingsRequest)(nil),       // 61: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
+	(*BoardDetailsResponse)(nil),                      // 62: cc.arduino.cli.commands.v1.BoardDetailsResponse
+	(*BoardAttachResponse)(nil),                       // 63: cc.arduino.cli.commands.v1.BoardAttachResponse
+	(*BoardListResponse)(nil),                         // 64: cc.arduino.cli.commands.v1.BoardListResponse
+	(*BoardListAllResponse)(nil),                      // 65: cc.arduino.cli.commands.v1.BoardListAllResponse
+	(*BoardSearchResponse)(nil),                       // 66: cc.arduino.cli.commands.v1.BoardSearchResponse
+	(*BoardListWatchResponse)(nil),                    // 67: cc.arduino.cli.commands.v1.BoardListWatchResponse
+	(*CompileResponse)(nil),                           // 68: cc.arduino.cli.commands.v1.CompileResponse
+	(*PlatformInstallResponse)(nil),                   // 69: cc.arduino.cli.commands.v1.PlatformInstallResponse
+	(*PlatformDownloadResponse)(nil),                  // 70: cc.arduino.cli.commands.v1.PlatformDownloadResponse
+	(*PlatformUninstallResponse)(nil),                 // 71: cc.arduino.cli.commands.v1.PlatformUninstallResponse
+	(*PlatformUpgradeResponse)(nil),                   // 72: cc.arduino.cli.commands.v1.PlatformUpgradeResponse
+	(*UploadResponse)(nil),                            // 73: cc.arduino.cli.commands.v1.UploadResponse
+	(*UploadUsingProgrammerResponse)(nil),             // 74: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
+	(*SupportedUserFieldsResponse)(nil),               // 75: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
+	(*ListProgrammersAvailableForUploadResponse)(nil), // 76: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
+	(*BurnBootloaderResponse)(nil),                    // 77: cc.arduino.cli.commands.v1.BurnBootloaderResponse
+	(*PlatformSearchResponse)(nil),                    // 78: cc.arduino.cli.commands.v1.PlatformSearchResponse
+	(*PlatformListResponse)(nil),                      // 79: cc.arduino.cli.commands.v1.PlatformListResponse
+	(*LibraryDownloadResponse)(nil),                   // 80: cc.arduino.cli.commands.v1.LibraryDownloadResponse
+	(*LibraryInstallResponse)(nil),                    // 81: cc.arduino.cli.commands.v1.LibraryInstallResponse
+	(*LibraryUpgradeResponse)(nil),                    // 82: cc.arduino.cli.commands.v1.LibraryUpgradeResponse
+	(*ZipLibraryInstallResponse)(nil),                 // 83: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
+	(*GitLibraryInstallResponse)(nil),                 // 84: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
+	(*LibraryUninstallResponse)(nil),                  // 85: cc.arduino.cli.commands.v1.LibraryUninstallResponse
+	(*LibraryUpgradeAllResponse)(nil),                 // 86: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
+	(*LibraryResolveDependenciesResponse)(nil),        // 87: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
+	(*LibrarySearchResponse)(nil),                     // 88: cc.arduino.cli.commands.v1.LibrarySearchResponse
+	(*LibraryListResponse)(nil),                       // 89: cc.arduino.cli.commands.v1.LibraryListResponse
+	(*MonitorResponse)(nil),                           // 90: cc.arduino.cli.commands.v1.MonitorResponse
+	(*EnumerateMonitorPortSettingsResponse)(nil),      // 91: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
 }
 var file_cc_arduino_cli_commands_v1_commands_proto_depIdxs = []int32{
 	25, // 0: cc.arduino.cli.commands.v1.CreateResponse.instance:type_name -> cc.arduino.cli.commands.v1.Instance
@@ -2065,58 +2074,60 @@ var file_cc_arduino_cli_commands_v1_commands_proto_depIdxs = []int32{
 	49, // 51: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:input_type -> cc.arduino.cli.commands.v1.PlatformListRequest
 	50, // 52: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:input_type -> cc.arduino.cli.commands.v1.LibraryDownloadRequest
 	51, // 53: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:input_type -> cc.arduino.cli.commands.v1.LibraryInstallRequest
-	52, // 54: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:input_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
-	53, // 55: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:input_type -> cc.arduino.cli.commands.v1.GitLibraryInstallRequest
-	54, // 56: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:input_type -> cc.arduino.cli.commands.v1.LibraryUninstallRequest
-	55, // 57: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
-	56, // 58: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:input_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
-	57, // 59: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:input_type -> cc.arduino.cli.commands.v1.LibrarySearchRequest
-	58, // 60: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:input_type -> cc.arduino.cli.commands.v1.LibraryListRequest
-	59, // 61: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:input_type -> cc.arduino.cli.commands.v1.MonitorRequest
-	60, // 62: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:input_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
-	1,  // 63: cc.arduino.cli.commands.v1.ArduinoCoreService.Create:output_type -> cc.arduino.cli.commands.v1.CreateResponse
-	3,  // 64: cc.arduino.cli.commands.v1.ArduinoCoreService.Init:output_type -> cc.arduino.cli.commands.v1.InitResponse
-	5,  // 65: cc.arduino.cli.commands.v1.ArduinoCoreService.Destroy:output_type -> cc.arduino.cli.commands.v1.DestroyResponse
-	7,  // 66: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateIndex:output_type -> cc.arduino.cli.commands.v1.UpdateIndexResponse
-	9,  // 67: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateLibrariesIndexResponse
-	11, // 68: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateCoreLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateCoreLibrariesIndexResponse
-	13, // 69: cc.arduino.cli.commands.v1.ArduinoCoreService.Outdated:output_type -> cc.arduino.cli.commands.v1.OutdatedResponse
-	15, // 70: cc.arduino.cli.commands.v1.ArduinoCoreService.Upgrade:output_type -> cc.arduino.cli.commands.v1.UpgradeResponse
-	17, // 71: cc.arduino.cli.commands.v1.ArduinoCoreService.Version:output_type -> cc.arduino.cli.commands.v1.VersionResponse
-	19, // 72: cc.arduino.cli.commands.v1.ArduinoCoreService.NewSketch:output_type -> cc.arduino.cli.commands.v1.NewSketchResponse
-	21, // 73: cc.arduino.cli.commands.v1.ArduinoCoreService.LoadSketch:output_type -> cc.arduino.cli.commands.v1.LoadSketchResponse
-	23, // 74: cc.arduino.cli.commands.v1.ArduinoCoreService.ArchiveSketch:output_type -> cc.arduino.cli.commands.v1.ArchiveSketchResponse
-	61, // 75: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardDetails:output_type -> cc.arduino.cli.commands.v1.BoardDetailsResponse
-	62, // 76: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardAttach:output_type -> cc.arduino.cli.commands.v1.BoardAttachResponse
-	63, // 77: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:output_type -> cc.arduino.cli.commands.v1.BoardListResponse
-	64, // 78: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:output_type -> cc.arduino.cli.commands.v1.BoardListAllResponse
-	65, // 79: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:output_type -> cc.arduino.cli.commands.v1.BoardSearchResponse
-	66, // 80: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:output_type -> cc.arduino.cli.commands.v1.BoardListWatchResponse
-	67, // 81: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:output_type -> cc.arduino.cli.commands.v1.CompileResponse
-	68, // 82: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:output_type -> cc.arduino.cli.commands.v1.PlatformInstallResponse
-	69, // 83: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:output_type -> cc.arduino.cli.commands.v1.PlatformDownloadResponse
-	70, // 84: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:output_type -> cc.arduino.cli.commands.v1.PlatformUninstallResponse
-	71, // 85: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:output_type -> cc.arduino.cli.commands.v1.PlatformUpgradeResponse
-	72, // 86: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:output_type -> cc.arduino.cli.commands.v1.UploadResponse
-	73, // 87: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:output_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
-	74, // 88: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:output_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
-	75, // 89: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:output_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
-	76, // 90: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:output_type -> cc.arduino.cli.commands.v1.BurnBootloaderResponse
-	77, // 91: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:output_type -> cc.arduino.cli.commands.v1.PlatformSearchResponse
-	78, // 92: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:output_type -> cc.arduino.cli.commands.v1.PlatformListResponse
-	79, // 93: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:output_type -> cc.arduino.cli.commands.v1.LibraryDownloadResponse
-	80, // 94: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:output_type -> cc.arduino.cli.commands.v1.LibraryInstallResponse
-	81, // 95: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:output_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
-	82, // 96: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:output_type -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse
-	83, // 97: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:output_type -> cc.arduino.cli.commands.v1.LibraryUninstallResponse
-	84, // 98: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
-	85, // 99: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:output_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
-	86, // 100: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:output_type -> cc.arduino.cli.commands.v1.LibrarySearchResponse
-	87, // 101: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:output_type -> cc.arduino.cli.commands.v1.LibraryListResponse
-	88, // 102: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:output_type -> cc.arduino.cli.commands.v1.MonitorResponse
-	89, // 103: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:output_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
-	63, // [63:104] is the sub-list for method output_type
-	22, // [22:63] is the sub-list for method input_type
+	52, // 54: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeRequest
+	53, // 55: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:input_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
+	54, // 56: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:input_type -> cc.arduino.cli.commands.v1.GitLibraryInstallRequest
+	55, // 57: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:input_type -> cc.arduino.cli.commands.v1.LibraryUninstallRequest
+	56, // 58: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
+	57, // 59: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:input_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
+	58, // 60: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:input_type -> cc.arduino.cli.commands.v1.LibrarySearchRequest
+	59, // 61: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:input_type -> cc.arduino.cli.commands.v1.LibraryListRequest
+	60, // 62: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:input_type -> cc.arduino.cli.commands.v1.MonitorRequest
+	61, // 63: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:input_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
+	1,  // 64: cc.arduino.cli.commands.v1.ArduinoCoreService.Create:output_type -> cc.arduino.cli.commands.v1.CreateResponse
+	3,  // 65: cc.arduino.cli.commands.v1.ArduinoCoreService.Init:output_type -> cc.arduino.cli.commands.v1.InitResponse
+	5,  // 66: cc.arduino.cli.commands.v1.ArduinoCoreService.Destroy:output_type -> cc.arduino.cli.commands.v1.DestroyResponse
+	7,  // 67: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateIndex:output_type -> cc.arduino.cli.commands.v1.UpdateIndexResponse
+	9,  // 68: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateLibrariesIndexResponse
+	11, // 69: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateCoreLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateCoreLibrariesIndexResponse
+	13, // 70: cc.arduino.cli.commands.v1.ArduinoCoreService.Outdated:output_type -> cc.arduino.cli.commands.v1.OutdatedResponse
+	15, // 71: cc.arduino.cli.commands.v1.ArduinoCoreService.Upgrade:output_type -> cc.arduino.cli.commands.v1.UpgradeResponse
+	17, // 72: cc.arduino.cli.commands.v1.ArduinoCoreService.Version:output_type -> cc.arduino.cli.commands.v1.VersionResponse
+	19, // 73: cc.arduino.cli.commands.v1.ArduinoCoreService.NewSketch:output_type -> cc.arduino.cli.commands.v1.NewSketchResponse
+	21, // 74: cc.arduino.cli.commands.v1.ArduinoCoreService.LoadSketch:output_type -> cc.arduino.cli.commands.v1.LoadSketchResponse
+	23, // 75: cc.arduino.cli.commands.v1.ArduinoCoreService.ArchiveSketch:output_type -> cc.arduino.cli.commands.v1.ArchiveSketchResponse
+	62, // 76: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardDetails:output_type -> cc.arduino.cli.commands.v1.BoardDetailsResponse
+	63, // 77: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardAttach:output_type -> cc.arduino.cli.commands.v1.BoardAttachResponse
+	64, // 78: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:output_type -> cc.arduino.cli.commands.v1.BoardListResponse
+	65, // 79: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:output_type -> cc.arduino.cli.commands.v1.BoardListAllResponse
+	66, // 80: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:output_type -> cc.arduino.cli.commands.v1.BoardSearchResponse
+	67, // 81: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:output_type -> cc.arduino.cli.commands.v1.BoardListWatchResponse
+	68, // 82: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:output_type -> cc.arduino.cli.commands.v1.CompileResponse
+	69, // 83: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:output_type -> cc.arduino.cli.commands.v1.PlatformInstallResponse
+	70, // 84: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:output_type -> cc.arduino.cli.commands.v1.PlatformDownloadResponse
+	71, // 85: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:output_type -> cc.arduino.cli.commands.v1.PlatformUninstallResponse
+	72, // 86: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:output_type -> cc.arduino.cli.commands.v1.PlatformUpgradeResponse
+	73, // 87: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:output_type -> cc.arduino.cli.commands.v1.UploadResponse
+	74, // 88: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:output_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
+	75, // 89: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:output_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
+	76, // 90: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:output_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
+	77, // 91: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:output_type -> cc.arduino.cli.commands.v1.BurnBootloaderResponse
+	78, // 92: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:output_type -> cc.arduino.cli.commands.v1.PlatformSearchResponse
+	79, // 93: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:output_type -> cc.arduino.cli.commands.v1.PlatformListResponse
+	80, // 94: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:output_type -> cc.arduino.cli.commands.v1.LibraryDownloadResponse
+	81, // 95: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:output_type -> cc.arduino.cli.commands.v1.LibraryInstallResponse
+	82, // 96: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeResponse
+	83, // 97: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:output_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
+	84, // 98: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:output_type -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse
+	85, // 99: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:output_type -> cc.arduino.cli.commands.v1.LibraryUninstallResponse
+	86, // 100: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
+	87, // 101: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:output_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
+	88, // 102: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:output_type -> cc.arduino.cli.commands.v1.LibrarySearchResponse
+	89, // 103: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:output_type -> cc.arduino.cli.commands.v1.LibraryListResponse
+	90, // 104: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:output_type -> cc.arduino.cli.commands.v1.MonitorResponse
+	91, // 105: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:output_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
+	64, // [64:106] is the sub-list for method output_type
+	22, // [22:64] is the sub-list for method input_type
 	22, // [22:22] is the sub-list for extension type_name
 	22, // [22:22] is the sub-list for extension extendee
 	0,  // [0:22] is the sub-list for field type_name
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.proto b/rpc/cc/arduino/cli/commands/v1/commands.proto
index ab3e0fd8903..38a958f2084 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.proto
+++ b/rpc/cc/arduino/cli/commands/v1/commands.proto
@@ -153,6 +153,10 @@ service ArduinoCoreService {
   rpc LibraryInstall(LibraryInstallRequest)
       returns (stream LibraryInstallResponse);
 
+  // Upgrade a library to the newest version available.
+  rpc LibraryUpgrade(LibraryUpgradeRequest)
+      returns (stream LibraryUpgradeResponse);
+
   // Install a library from a Zip File
   rpc ZipLibraryInstall(ZipLibraryInstallRequest)
       returns (stream ZipLibraryInstallResponse);
diff --git a/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go b/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
index cc0e336bdc3..46eb24ee9fd 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
@@ -92,6 +92,8 @@ type ArduinoCoreServiceClient interface {
 	LibraryDownload(ctx context.Context, in *LibraryDownloadRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryDownloadClient, error)
 	// Download and install an Arduino library from the libraries index.
 	LibraryInstall(ctx context.Context, in *LibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryInstallClient, error)
+	// Upgrade a library to the newest version available.
+	LibraryUpgrade(ctx context.Context, in *LibraryUpgradeRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUpgradeClient, error)
 	// Install a library from a Zip File
 	ZipLibraryInstall(ctx context.Context, in *ZipLibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_ZipLibraryInstallClient, error)
 	// Download and install a library from a git url
@@ -799,8 +801,40 @@ func (x *arduinoCoreServiceLibraryInstallClient) Recv() (*LibraryInstallResponse
 	return m, nil
 }
 
+func (c *arduinoCoreServiceClient) LibraryUpgrade(ctx context.Context, in *LibraryUpgradeRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUpgradeClient, error) {
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[17], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgrade", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &arduinoCoreServiceLibraryUpgradeClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type ArduinoCoreService_LibraryUpgradeClient interface {
+	Recv() (*LibraryUpgradeResponse, error)
+	grpc.ClientStream
+}
+
+type arduinoCoreServiceLibraryUpgradeClient struct {
+	grpc.ClientStream
+}
+
+func (x *arduinoCoreServiceLibraryUpgradeClient) Recv() (*LibraryUpgradeResponse, error) {
+	m := new(LibraryUpgradeResponse)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
 func (c *arduinoCoreServiceClient) ZipLibraryInstall(ctx context.Context, in *ZipLibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_ZipLibraryInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[17], "/cc.arduino.cli.commands.v1.ArduinoCoreService/ZipLibraryInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[18], "/cc.arduino.cli.commands.v1.ArduinoCoreService/ZipLibraryInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -832,7 +866,7 @@ func (x *arduinoCoreServiceZipLibraryInstallClient) Recv() (*ZipLibraryInstallRe
 }
 
 func (c *arduinoCoreServiceClient) GitLibraryInstall(ctx context.Context, in *GitLibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_GitLibraryInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[18], "/cc.arduino.cli.commands.v1.ArduinoCoreService/GitLibraryInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[19], "/cc.arduino.cli.commands.v1.ArduinoCoreService/GitLibraryInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -864,7 +898,7 @@ func (x *arduinoCoreServiceGitLibraryInstallClient) Recv() (*GitLibraryInstallRe
 }
 
 func (c *arduinoCoreServiceClient) LibraryUninstall(ctx context.Context, in *LibraryUninstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUninstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[19], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUninstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[20], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUninstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -896,7 +930,7 @@ func (x *arduinoCoreServiceLibraryUninstallClient) Recv() (*LibraryUninstallResp
 }
 
 func (c *arduinoCoreServiceClient) LibraryUpgradeAll(ctx context.Context, in *LibraryUpgradeAllRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUpgradeAllClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[20], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgradeAll", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[21], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgradeAll", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -955,7 +989,7 @@ func (c *arduinoCoreServiceClient) LibraryList(ctx context.Context, in *LibraryL
 }
 
 func (c *arduinoCoreServiceClient) Monitor(ctx context.Context, opts ...grpc.CallOption) (ArduinoCoreService_MonitorClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[21], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Monitor", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[22], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Monitor", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -1068,6 +1102,8 @@ type ArduinoCoreServiceServer interface {
 	LibraryDownload(*LibraryDownloadRequest, ArduinoCoreService_LibraryDownloadServer) error
 	// Download and install an Arduino library from the libraries index.
 	LibraryInstall(*LibraryInstallRequest, ArduinoCoreService_LibraryInstallServer) error
+	// Upgrade a library to the newest version available.
+	LibraryUpgrade(*LibraryUpgradeRequest, ArduinoCoreService_LibraryUpgradeServer) error
 	// Install a library from a Zip File
 	ZipLibraryInstall(*ZipLibraryInstallRequest, ArduinoCoreService_ZipLibraryInstallServer) error
 	// Download and install a library from a git url
@@ -1190,6 +1226,9 @@ func (UnimplementedArduinoCoreServiceServer) LibraryDownload(*LibraryDownloadReq
 func (UnimplementedArduinoCoreServiceServer) LibraryInstall(*LibraryInstallRequest, ArduinoCoreService_LibraryInstallServer) error {
 	return status.Errorf(codes.Unimplemented, "method LibraryInstall not implemented")
 }
+func (UnimplementedArduinoCoreServiceServer) LibraryUpgrade(*LibraryUpgradeRequest, ArduinoCoreService_LibraryUpgradeServer) error {
+	return status.Errorf(codes.Unimplemented, "method LibraryUpgrade not implemented")
+}
 func (UnimplementedArduinoCoreServiceServer) ZipLibraryInstall(*ZipLibraryInstallRequest, ArduinoCoreService_ZipLibraryInstallServer) error {
 	return status.Errorf(codes.Unimplemented, "method ZipLibraryInstall not implemented")
 }
@@ -1862,6 +1901,27 @@ func (x *arduinoCoreServiceLibraryInstallServer) Send(m *LibraryInstallResponse)
 	return x.ServerStream.SendMsg(m)
 }
 
+func _ArduinoCoreService_LibraryUpgrade_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(LibraryUpgradeRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
+	}
+	return srv.(ArduinoCoreServiceServer).LibraryUpgrade(m, &arduinoCoreServiceLibraryUpgradeServer{stream})
+}
+
+type ArduinoCoreService_LibraryUpgradeServer interface {
+	Send(*LibraryUpgradeResponse) error
+	grpc.ServerStream
+}
+
+type arduinoCoreServiceLibraryUpgradeServer struct {
+	grpc.ServerStream
+}
+
+func (x *arduinoCoreServiceLibraryUpgradeServer) Send(m *LibraryUpgradeResponse) error {
+	return x.ServerStream.SendMsg(m)
+}
+
 func _ArduinoCoreService_ZipLibraryInstall_Handler(srv interface{}, stream grpc.ServerStream) error {
 	m := new(ZipLibraryInstallRequest)
 	if err := stream.RecvMsg(m); err != nil {
@@ -2215,6 +2275,11 @@ var ArduinoCoreService_ServiceDesc = grpc.ServiceDesc{
 			Handler:       _ArduinoCoreService_LibraryInstall_Handler,
 			ServerStreams: true,
 		},
+		{
+			StreamName:    "LibraryUpgrade",
+			Handler:       _ArduinoCoreService_LibraryUpgrade_Handler,
+			ServerStreams: true,
+		},
 		{
 			StreamName:    "ZipLibraryInstall",
 			Handler:       _ArduinoCoreService_ZipLibraryInstall_Handler,
diff --git a/rpc/cc/arduino/cli/commands/v1/common.go b/rpc/cc/arduino/cli/commands/v1/common.go
index cc987d2f4ab..2c22394cb89 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.go
+++ b/rpc/cc/arduino/cli/commands/v1/common.go
@@ -20,3 +20,9 @@ type DownloadProgressCB func(curr *DownloadProgress)
 
 // TaskProgressCB is a callback to receive progress messages
 type TaskProgressCB func(msg *TaskProgress)
+
+// InstanceCommand is an interface that represents a gRPC command with
+// a gRPC Instance.
+type InstanceCommand interface {
+	GetInstance() *Instance
+}
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.pb.go b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
index 09b74859bbd..1b5bfe67f69 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
@@ -321,8 +321,8 @@ type LibraryInstallRequest struct {
 	// Set to true to skip installation of specified library's dependencies,
 	// defaults to false.
 	NoDeps bool `protobuf:"varint,4,opt,name=no_deps,json=noDeps,proto3" json:"no_deps,omitempty"`
-	// Set to true to skip installation if a different version of the library or one
-	// of its dependencies is already installed, defaults to false.
+	// Set to true to skip installation if a different version of the library or
+	// one of its dependencies is already installed, defaults to false.
 	NoOverwrite bool `protobuf:"varint,5,opt,name=no_overwrite,json=noOverwrite,proto3" json:"no_overwrite,omitempty"`
 }
 
@@ -450,6 +450,130 @@ func (x *LibraryInstallResponse) GetTaskProgress() *TaskProgress {
 	return nil
 }
 
+type LibraryUpgradeRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Arduino Core Service instance from the `Init` response.
+	Instance *Instance `protobuf:"bytes,1,opt,name=instance,proto3" json:"instance,omitempty"`
+	// Name of the library.
+	Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	// Set to true to skip installation of specified library's dependencies,
+	// defaults to false.
+	NoDeps bool `protobuf:"varint,3,opt,name=no_deps,json=noDeps,proto3" json:"no_deps,omitempty"`
+}
+
+func (x *LibraryUpgradeRequest) Reset() {
+	*x = LibraryUpgradeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *LibraryUpgradeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LibraryUpgradeRequest) ProtoMessage() {}
+
+func (x *LibraryUpgradeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use LibraryUpgradeRequest.ProtoReflect.Descriptor instead.
+func (*LibraryUpgradeRequest) Descriptor() ([]byte, []int) {
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *LibraryUpgradeRequest) GetInstance() *Instance {
+	if x != nil {
+		return x.Instance
+	}
+	return nil
+}
+
+func (x *LibraryUpgradeRequest) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *LibraryUpgradeRequest) GetNoDeps() bool {
+	if x != nil {
+		return x.NoDeps
+	}
+	return false
+}
+
+type LibraryUpgradeResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Progress of the library download.
+	Progress *DownloadProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"`
+	// Description of the current stage of the installation.
+	TaskProgress *TaskProgress `protobuf:"bytes,2,opt,name=task_progress,json=taskProgress,proto3" json:"task_progress,omitempty"`
+}
+
+func (x *LibraryUpgradeResponse) Reset() {
+	*x = LibraryUpgradeResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *LibraryUpgradeResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LibraryUpgradeResponse) ProtoMessage() {}
+
+func (x *LibraryUpgradeResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use LibraryUpgradeResponse.ProtoReflect.Descriptor instead.
+func (*LibraryUpgradeResponse) Descriptor() ([]byte, []int) {
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *LibraryUpgradeResponse) GetProgress() *DownloadProgress {
+	if x != nil {
+		return x.Progress
+	}
+	return nil
+}
+
+func (x *LibraryUpgradeResponse) GetTaskProgress() *TaskProgress {
+	if x != nil {
+		return x.TaskProgress
+	}
+	return nil
+}
+
 type LibraryUninstallRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -466,7 +590,7 @@ type LibraryUninstallRequest struct {
 func (x *LibraryUninstallRequest) Reset() {
 	*x = LibraryUninstallRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[4]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -479,7 +603,7 @@ func (x *LibraryUninstallRequest) String() string {
 func (*LibraryUninstallRequest) ProtoMessage() {}
 
 func (x *LibraryUninstallRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[4]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -492,7 +616,7 @@ func (x *LibraryUninstallRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryUninstallRequest.ProtoReflect.Descriptor instead.
 func (*LibraryUninstallRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{4}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *LibraryUninstallRequest) GetInstance() *Instance {
@@ -528,7 +652,7 @@ type LibraryUninstallResponse struct {
 func (x *LibraryUninstallResponse) Reset() {
 	*x = LibraryUninstallResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[5]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[7]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -541,7 +665,7 @@ func (x *LibraryUninstallResponse) String() string {
 func (*LibraryUninstallResponse) ProtoMessage() {}
 
 func (x *LibraryUninstallResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[5]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[7]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -554,7 +678,7 @@ func (x *LibraryUninstallResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryUninstallResponse.ProtoReflect.Descriptor instead.
 func (*LibraryUninstallResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{5}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *LibraryUninstallResponse) GetTaskProgress() *TaskProgress {
@@ -576,7 +700,7 @@ type LibraryUpgradeAllRequest struct {
 func (x *LibraryUpgradeAllRequest) Reset() {
 	*x = LibraryUpgradeAllRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[6]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[8]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -589,7 +713,7 @@ func (x *LibraryUpgradeAllRequest) String() string {
 func (*LibraryUpgradeAllRequest) ProtoMessage() {}
 
 func (x *LibraryUpgradeAllRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[6]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[8]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -602,7 +726,7 @@ func (x *LibraryUpgradeAllRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryUpgradeAllRequest.ProtoReflect.Descriptor instead.
 func (*LibraryUpgradeAllRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{6}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *LibraryUpgradeAllRequest) GetInstance() *Instance {
@@ -626,7 +750,7 @@ type LibraryUpgradeAllResponse struct {
 func (x *LibraryUpgradeAllResponse) Reset() {
 	*x = LibraryUpgradeAllResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[7]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[9]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -639,7 +763,7 @@ func (x *LibraryUpgradeAllResponse) String() string {
 func (*LibraryUpgradeAllResponse) ProtoMessage() {}
 
 func (x *LibraryUpgradeAllResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[7]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[9]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -652,7 +776,7 @@ func (x *LibraryUpgradeAllResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryUpgradeAllResponse.ProtoReflect.Descriptor instead.
 func (*LibraryUpgradeAllResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{7}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *LibraryUpgradeAllResponse) GetProgress() *DownloadProgress {
@@ -686,7 +810,7 @@ type LibraryResolveDependenciesRequest struct {
 func (x *LibraryResolveDependenciesRequest) Reset() {
 	*x = LibraryResolveDependenciesRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[8]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[10]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -699,7 +823,7 @@ func (x *LibraryResolveDependenciesRequest) String() string {
 func (*LibraryResolveDependenciesRequest) ProtoMessage() {}
 
 func (x *LibraryResolveDependenciesRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[8]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[10]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -712,7 +836,7 @@ func (x *LibraryResolveDependenciesRequest) ProtoReflect() protoreflect.Message
 
 // Deprecated: Use LibraryResolveDependenciesRequest.ProtoReflect.Descriptor instead.
 func (*LibraryResolveDependenciesRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{8}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *LibraryResolveDependenciesRequest) GetInstance() *Instance {
@@ -748,7 +872,7 @@ type LibraryResolveDependenciesResponse struct {
 func (x *LibraryResolveDependenciesResponse) Reset() {
 	*x = LibraryResolveDependenciesResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[9]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[11]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -761,7 +885,7 @@ func (x *LibraryResolveDependenciesResponse) String() string {
 func (*LibraryResolveDependenciesResponse) ProtoMessage() {}
 
 func (x *LibraryResolveDependenciesResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[9]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[11]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -774,7 +898,7 @@ func (x *LibraryResolveDependenciesResponse) ProtoReflect() protoreflect.Message
 
 // Deprecated: Use LibraryResolveDependenciesResponse.ProtoReflect.Descriptor instead.
 func (*LibraryResolveDependenciesResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{9}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *LibraryResolveDependenciesResponse) GetDependencies() []*LibraryDependencyStatus {
@@ -800,7 +924,7 @@ type LibraryDependencyStatus struct {
 func (x *LibraryDependencyStatus) Reset() {
 	*x = LibraryDependencyStatus{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[10]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -813,7 +937,7 @@ func (x *LibraryDependencyStatus) String() string {
 func (*LibraryDependencyStatus) ProtoMessage() {}
 
 func (x *LibraryDependencyStatus) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[10]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -826,7 +950,7 @@ func (x *LibraryDependencyStatus) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryDependencyStatus.ProtoReflect.Descriptor instead.
 func (*LibraryDependencyStatus) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{10}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *LibraryDependencyStatus) GetName() string {
@@ -864,7 +988,7 @@ type LibrarySearchRequest struct {
 func (x *LibrarySearchRequest) Reset() {
 	*x = LibrarySearchRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[11]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[13]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -877,7 +1001,7 @@ func (x *LibrarySearchRequest) String() string {
 func (*LibrarySearchRequest) ProtoMessage() {}
 
 func (x *LibrarySearchRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[11]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[13]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -890,7 +1014,7 @@ func (x *LibrarySearchRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibrarySearchRequest.ProtoReflect.Descriptor instead.
 func (*LibrarySearchRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{11}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *LibrarySearchRequest) GetInstance() *Instance {
@@ -921,7 +1045,7 @@ type LibrarySearchResponse struct {
 func (x *LibrarySearchResponse) Reset() {
 	*x = LibrarySearchResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[12]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -934,7 +1058,7 @@ func (x *LibrarySearchResponse) String() string {
 func (*LibrarySearchResponse) ProtoMessage() {}
 
 func (x *LibrarySearchResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[12]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -947,7 +1071,7 @@ func (x *LibrarySearchResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibrarySearchResponse.ProtoReflect.Descriptor instead.
 func (*LibrarySearchResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{12}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{14}
 }
 
 func (x *LibrarySearchResponse) GetLibraries() []*SearchedLibrary {
@@ -981,7 +1105,7 @@ type SearchedLibrary struct {
 func (x *SearchedLibrary) Reset() {
 	*x = SearchedLibrary{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[13]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -994,7 +1118,7 @@ func (x *SearchedLibrary) String() string {
 func (*SearchedLibrary) ProtoMessage() {}
 
 func (x *SearchedLibrary) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[13]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1007,7 +1131,7 @@ func (x *SearchedLibrary) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use SearchedLibrary.ProtoReflect.Descriptor instead.
 func (*SearchedLibrary) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{13}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{15}
 }
 
 func (x *SearchedLibrary) GetName() string {
@@ -1070,7 +1194,7 @@ type LibraryRelease struct {
 func (x *LibraryRelease) Reset() {
 	*x = LibraryRelease{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[14]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[16]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1083,7 +1207,7 @@ func (x *LibraryRelease) String() string {
 func (*LibraryRelease) ProtoMessage() {}
 
 func (x *LibraryRelease) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[14]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[16]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1096,7 +1220,7 @@ func (x *LibraryRelease) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryRelease.ProtoReflect.Descriptor instead.
 func (*LibraryRelease) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{14}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{16}
 }
 
 func (x *LibraryRelease) GetAuthor() string {
@@ -1204,7 +1328,7 @@ type LibraryDependency struct {
 func (x *LibraryDependency) Reset() {
 	*x = LibraryDependency{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[15]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[17]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1217,7 +1341,7 @@ func (x *LibraryDependency) String() string {
 func (*LibraryDependency) ProtoMessage() {}
 
 func (x *LibraryDependency) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[15]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[17]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1230,7 +1354,7 @@ func (x *LibraryDependency) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryDependency.ProtoReflect.Descriptor instead.
 func (*LibraryDependency) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{15}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{17}
 }
 
 func (x *LibraryDependency) GetName() string {
@@ -1268,7 +1392,7 @@ type DownloadResource struct {
 func (x *DownloadResource) Reset() {
 	*x = DownloadResource{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[16]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[18]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1281,7 +1405,7 @@ func (x *DownloadResource) String() string {
 func (*DownloadResource) ProtoMessage() {}
 
 func (x *DownloadResource) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[16]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[18]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1294,7 +1418,7 @@ func (x *DownloadResource) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DownloadResource.ProtoReflect.Descriptor instead.
 func (*DownloadResource) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{16}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{18}
 }
 
 func (x *DownloadResource) GetUrl() string {
@@ -1356,7 +1480,7 @@ type LibraryListRequest struct {
 func (x *LibraryListRequest) Reset() {
 	*x = LibraryListRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[17]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[19]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1369,7 +1493,7 @@ func (x *LibraryListRequest) String() string {
 func (*LibraryListRequest) ProtoMessage() {}
 
 func (x *LibraryListRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[17]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[19]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1382,7 +1506,7 @@ func (x *LibraryListRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryListRequest.ProtoReflect.Descriptor instead.
 func (*LibraryListRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{17}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{19}
 }
 
 func (x *LibraryListRequest) GetInstance() *Instance {
@@ -1432,7 +1556,7 @@ type LibraryListResponse struct {
 func (x *LibraryListResponse) Reset() {
 	*x = LibraryListResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[18]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[20]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1445,7 +1569,7 @@ func (x *LibraryListResponse) String() string {
 func (*LibraryListResponse) ProtoMessage() {}
 
 func (x *LibraryListResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[18]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[20]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1458,7 +1582,7 @@ func (x *LibraryListResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LibraryListResponse.ProtoReflect.Descriptor instead.
 func (*LibraryListResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{18}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{20}
 }
 
 func (x *LibraryListResponse) GetInstalledLibraries() []*InstalledLibrary {
@@ -1484,7 +1608,7 @@ type InstalledLibrary struct {
 func (x *InstalledLibrary) Reset() {
 	*x = InstalledLibrary{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[19]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[21]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1497,7 +1621,7 @@ func (x *InstalledLibrary) String() string {
 func (*InstalledLibrary) ProtoMessage() {}
 
 func (x *InstalledLibrary) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[19]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[21]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1510,7 +1634,7 @@ func (x *InstalledLibrary) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use InstalledLibrary.ProtoReflect.Descriptor instead.
 func (*InstalledLibrary) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{19}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{21}
 }
 
 func (x *InstalledLibrary) GetLibrary() *Library {
@@ -1594,7 +1718,7 @@ type Library struct {
 func (x *Library) Reset() {
 	*x = Library{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[20]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[22]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1607,7 +1731,7 @@ func (x *Library) String() string {
 func (*Library) ProtoMessage() {}
 
 func (x *Library) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[20]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[22]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1620,7 +1744,7 @@ func (x *Library) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Library.ProtoReflect.Descriptor instead.
 func (*Library) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{20}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{22}
 }
 
 func (x *Library) GetName() string {
@@ -1822,7 +1946,7 @@ type ZipLibraryInstallRequest struct {
 func (x *ZipLibraryInstallRequest) Reset() {
 	*x = ZipLibraryInstallRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[21]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[23]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1835,7 +1959,7 @@ func (x *ZipLibraryInstallRequest) String() string {
 func (*ZipLibraryInstallRequest) ProtoMessage() {}
 
 func (x *ZipLibraryInstallRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[21]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[23]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1848,7 +1972,7 @@ func (x *ZipLibraryInstallRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ZipLibraryInstallRequest.ProtoReflect.Descriptor instead.
 func (*ZipLibraryInstallRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{21}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{23}
 }
 
 func (x *ZipLibraryInstallRequest) GetInstance() *Instance {
@@ -1884,7 +2008,7 @@ type ZipLibraryInstallResponse struct {
 func (x *ZipLibraryInstallResponse) Reset() {
 	*x = ZipLibraryInstallResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[22]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[24]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1897,7 +2021,7 @@ func (x *ZipLibraryInstallResponse) String() string {
 func (*ZipLibraryInstallResponse) ProtoMessage() {}
 
 func (x *ZipLibraryInstallResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[22]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[24]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1910,7 +2034,7 @@ func (x *ZipLibraryInstallResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ZipLibraryInstallResponse.ProtoReflect.Descriptor instead.
 func (*ZipLibraryInstallResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{22}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{24}
 }
 
 func (x *ZipLibraryInstallResponse) GetTaskProgress() *TaskProgress {
@@ -1937,7 +2061,7 @@ type GitLibraryInstallRequest struct {
 func (x *GitLibraryInstallRequest) Reset() {
 	*x = GitLibraryInstallRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[23]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[25]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1950,7 +2074,7 @@ func (x *GitLibraryInstallRequest) String() string {
 func (*GitLibraryInstallRequest) ProtoMessage() {}
 
 func (x *GitLibraryInstallRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[23]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[25]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1963,7 +2087,7 @@ func (x *GitLibraryInstallRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GitLibraryInstallRequest.ProtoReflect.Descriptor instead.
 func (*GitLibraryInstallRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{23}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{25}
 }
 
 func (x *GitLibraryInstallRequest) GetInstance() *Instance {
@@ -1999,7 +2123,7 @@ type GitLibraryInstallResponse struct {
 func (x *GitLibraryInstallResponse) Reset() {
 	*x = GitLibraryInstallResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[24]
+		mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[26]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -2012,7 +2136,7 @@ func (x *GitLibraryInstallResponse) String() string {
 func (*GitLibraryInstallResponse) ProtoMessage() {}
 
 func (x *GitLibraryInstallResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[24]
+	mi := &file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[26]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -2025,7 +2149,7 @@ func (x *GitLibraryInstallResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GitLibraryInstallResponse.ProtoReflect.Descriptor instead.
 func (*GitLibraryInstallResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{24}
+	return file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP(), []int{26}
 }
 
 func (x *GitLibraryInstallResponse) GetTaskProgress() *TaskProgress {
@@ -2083,308 +2207,327 @@ var file_cc_arduino_cli_commands_v1_lib_proto_rawDesc = []byte{
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
 	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50,
 	0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f,
-	0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
-	0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
-	0x6e, 0x22, 0x69, 0x0a, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e,
-	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a,
-	0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c,
-	0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x5c, 0x0a, 0x18,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c,
-	0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74,
-	0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
-	0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xb4, 0x01, 0x0a, 0x19, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67,
-	0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
-	0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65,
-	0x73, 0x73, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72,
-	0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72,
-	0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
-	0x73, 0x22, 0x93, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73,
-	0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52,
-	0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
-	0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x7d, 0x0a, 0x22, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65,
-	0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a,
-	0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
-	0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
-	0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74,
-	0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
-	0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
-	0x64, 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65,
-	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x6e,
-	0x0a, 0x14, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
-	0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08,
-	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72,
-	0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0xab,
-	0x01, 0x0a, 0x15, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x6c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65,
-	0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
-	0x69, 0x65, 0x73, 0x12, 0x47, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74,
-	0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa9, 0x02, 0x0a,
-	0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x55, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73,
-	0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x6c,
-	0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x1a,
-	0x67, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x40, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf4, 0x03, 0x0a, 0x0e, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61,
-	0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74,
-	0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a,
-	0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a, 0x0a,
-	0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72,
-	0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61,
-	0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69,
-	0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74,
-	0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a,
-	0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x08,
-	0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75,
-	0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03,
-	0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x09, 0x72, 0x65, 0x73,
-	0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
-	0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
-	0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12,
-	0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c,
-	0x75, 0x64, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76,
-	0x69, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x0c,
-	0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
-	0x79, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22,
-	0x56, 0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
-	0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e,
-	0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e,
-	0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03,
-	0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x29,
-	0x0a, 0x10, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76,
-	0x65, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65,
-	0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65,
-	0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x63,
-	0x68, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
-	0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0xae, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
 	0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
 	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
 	0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-	0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03,
-	0x61, 0x6c, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c,
-	0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x22, 0x74, 0x0a, 0x13, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x5d, 0x0a, 0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x6c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x12, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x22,
-	0x97, 0x01, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x12, 0x3d, 0x0a, 0x07, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x07, 0x6c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x12, 0x44, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
-	0x52, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xee, 0x08, 0x0a, 0x07, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74,
-	0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f,
-	0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
-	0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a,
-	0x09, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x09, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x77,
-	0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65,
-	0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
-	0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72,
-	0x79, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72,
-	0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74,
-	0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73,
-	0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a,
-	0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0a, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x1d,
-	0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0b, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x69, 0x72, 0x12, 0x1f, 0x0a,
-	0x0b, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0c, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0a, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x69, 0x72, 0x12, 0x2d,
-	0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74,
-	0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1b, 0x0a,
-	0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x6f,
-	0x74, 0x5f, 0x61, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28,
-	0x08, 0x52, 0x0b, 0x64, 0x6f, 0x74, 0x41, 0x4c, 0x69, 0x6e, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x20,
-	0x0a, 0x0b, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x12, 0x20,
-	0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64,
-	0x12, 0x19, 0x0a, 0x08, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x13, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x07, 0x6c, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69,
-	0x73, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
-	0x69, 0x73, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x16, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a,
-	0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b,
+	0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x73,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6e, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x22, 0xb1,
+	0x01, 0x0a, 0x16, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64,
+	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x70, 0x72, 0x6f,
+	0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+	0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72,
+	0x65, 0x73, 0x73, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67,
+	0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67,
+	0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65,
+	0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e,
+	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40,
+	0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e,
+	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x69,
+	0x0a, 0x18, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61,
+	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61,
+	0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54,
+	0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73,
+	0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x5c, 0x0a, 0x18, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69,
+	0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xb4, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f,
+	0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12,
+	0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73,
+	0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x93,
+	0x01, 0x0a, 0x21, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76,
+	0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e,
+	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x22, 0x7d, 0x0a, 0x22, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52,
+	0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69,
+	0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x64, 0x65,
+	0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
 	0x32, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
 	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65,
-	0x73, 0x12, 0x47, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x18, 0x20,
-	0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+	0x69, 0x65, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44,
+	0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
+	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72,
+	0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x2b,
+	0x0a, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+	0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x73, 0x69,
+	0x6f, 0x6e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x14, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73,
+	0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0xab, 0x01, 0x0a, 0x15,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69,
+	0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73,
+	0x12, 0x47, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x0f, 0x53, 0x65,
+	0x61, 0x72, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x12, 0x0a,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x12, 0x55, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x06, 0x6c, 0x61,
-	0x79, 0x6f, 0x75, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c,
-	0x61, 0x79, 0x6f, 0x75, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x1a, 0x0a,
-	0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f,
-	0x76, 0x69, 0x64, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x1b,
-	0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x49, 0x6e,
-	0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74,
-	0x69, 0x62, 0x6c, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08,
+	0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65,
+	0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c,
+	0x65, 0x61, 0x73, 0x65, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x1a, 0x67, 0x0a, 0x0d,
+	0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+	0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+	0x40, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf4, 0x03, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68,
+	0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
+	0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61,
+	0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65,
+	0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65,
+	0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72,
+	0x61, 0x70, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x61, 0x67,
+	0x72, 0x61, 0x70, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x18,
+	0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1a,
+	0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x72,
+	0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
+	0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73,
+	0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52,
+	0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+	0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x0b, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x11,
+	0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
+	0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+	0x73, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x64, 0x65, 0x70,
+	0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
 	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57,
-	0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74,
-	0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, 0x68, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70,
-	0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+	0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0c,
+	0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x56, 0x0a, 0x11,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+	0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72,
+	0x61, 0x69, 0x6e, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+	0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x61,
+	0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x46, 0x69,
+	0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73,
+	0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73,
+	0x75, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+	0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f,
+	0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68,
+	0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0xae, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08,
+	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74,
+	0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x10,
+	0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c,
+	0x12, 0x1c, 0x0a, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x22, 0x74, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a,
+	0x13, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65,
+	0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x12, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+	0x6c, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x22, 0x97, 0x01, 0x0a,
+	0x10, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x12, 0x3d, 0x0a, 0x07, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x07, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x12, 0x44, 0x0a, 0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52, 0x07, 0x72,
+	0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xee, 0x08, 0x0a, 0x07, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x1e,
+	0x0a, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a,
+	0x0a, 0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61,
+	0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70,
+	0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73,
+	0x69, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69,
+	0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x07,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x24,
+	0x0a, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18,
+	0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74,
+	0x75, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20,
+	0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e,
+	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x69, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x74,
+	0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0a, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x69, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x63,
+	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
+	0x6d, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+	0x65, 0x72, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65,
+	0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72,
+	0x65, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x6f, 0x74, 0x5f, 0x61,
+	0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
+	0x64, 0x6f, 0x74, 0x41, 0x4c, 0x69, 0x6e, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70,
+	0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x0b, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x19, 0x0a,
+	0x08, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x6c, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x6c,
+	0x65, 0x67, 0x61, 0x63, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4c,
+	0x65, 0x67, 0x61, 0x63, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
+	0x18, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
+	0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74,
+	0x72, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x47,
+	0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x06, 0x6c, 0x61, 0x79, 0x6f, 0x75,
+	0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f,
+	0x75, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
+	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78,
+	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
+	0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28,
+	0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x63, 0x6c, 0x75,
+	0x64, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c,
+	0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, 0x68,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c,
+	0x65, 0x57, 0x69, 0x74, 0x68, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+	0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x3a, 0x02, 0x38, 0x01, 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62,
+	0x6c, 0x65, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
 	0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61,
-	0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
-	0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
-	0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x5a,
-	0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52,
-	0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74,
-	0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a,
-	0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
-	0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x6a, 0x0a, 0x19, 0x5a,
-	0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b,
-	0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73,
-	0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50,
-	0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4c,
+	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61,
+	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x5a, 0x69, 0x70, 0x4c,
 	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71,
 	0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
 	0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e,
-	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72,
-	0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65,
-	0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x6a, 0x0a, 0x19, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67,
-	0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67,
-	0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65,
-	0x73, 0x73, 0x2a, 0x5a, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49, 0x42,
-	0x52, 0x41, 0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54,
-	0x55, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4c,
-	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54,
-	0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x2a, 0x46,
-	0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12,
-	0x17, 0x0a, 0x13, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55,
-	0x54, 0x5f, 0x46, 0x4c, 0x41, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52,
-	0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x52, 0x45, 0x43, 0x55, 0x52,
-	0x53, 0x49, 0x56, 0x45, 0x10, 0x01, 0x2a, 0xc7, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49,
-	0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49,
-	0x44, 0x45, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
-	0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e,
-	0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x4c, 0x49, 0x42, 0x52, 0x41,
-	0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x4c, 0x41, 0x54,
-	0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x30,
-	0x0a, 0x2c, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49,
-	0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x44, 0x5f, 0x50, 0x4c,
-	0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x03,
-	0x12, 0x1e, 0x0a, 0x1a, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41,
-	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04,
-	0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63,
-	0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76,
-	0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x33,
+	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76,
+	0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f,
+	0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x6a, 0x0a, 0x19, 0x5a, 0x69, 0x70, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72,
+	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72,
+	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67,
+	0x72, 0x65, 0x73, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61,
+	0x6e, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69,
+	0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72,
+	0x69, 0x74, 0x65, 0x22, 0x6a, 0x0a, 0x19, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2a,
+	0x5a, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
+	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52,
+	0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
+	0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x49, 0x42, 0x52,
+	0x41, 0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
+	0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x2a, 0x46, 0x0a, 0x0d, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x17, 0x0a, 0x13,
+	0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x46,
+	0x4c, 0x41, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59,
+	0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x52, 0x45, 0x43, 0x55, 0x52, 0x53, 0x49, 0x56,
+	0x45, 0x10, 0x01, 0x2a, 0xc7, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c,
+	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49, 0x42, 0x52, 0x41,
+	0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x45, 0x5f,
+	0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x42,
+	0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x53,
+	0x45, 0x52, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f,
+	0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52,
+	0x4d, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x30, 0x0a, 0x2c, 0x4c,
+	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+	0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46,
+	0x4f, 0x52, 0x4d, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x1e, 0x0a,
+	0x1a, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f,
+	0x4e, 0x5f, 0x55, 0x4e, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04, 0x42, 0x48, 0x5a,
+	0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f,
+	0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63,
+	0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -2400,7 +2543,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_rawDescGZIP() []byte {
 }
 
 var file_cc_arduino_cli_commands_v1_lib_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
-var file_cc_arduino_cli_commands_v1_lib_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
+var file_cc_arduino_cli_commands_v1_lib_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
 var file_cc_arduino_cli_commands_v1_lib_proto_goTypes = []interface{}{
 	(LibrarySearchStatus)(0),                   // 0: cc.arduino.cli.commands.v1.LibrarySearchStatus
 	(LibraryLayout)(0),                         // 1: cc.arduino.cli.commands.v1.LibraryLayout
@@ -2409,72 +2552,77 @@ var file_cc_arduino_cli_commands_v1_lib_proto_goTypes = []interface{}{
 	(*LibraryDownloadResponse)(nil),            // 4: cc.arduino.cli.commands.v1.LibraryDownloadResponse
 	(*LibraryInstallRequest)(nil),              // 5: cc.arduino.cli.commands.v1.LibraryInstallRequest
 	(*LibraryInstallResponse)(nil),             // 6: cc.arduino.cli.commands.v1.LibraryInstallResponse
-	(*LibraryUninstallRequest)(nil),            // 7: cc.arduino.cli.commands.v1.LibraryUninstallRequest
-	(*LibraryUninstallResponse)(nil),           // 8: cc.arduino.cli.commands.v1.LibraryUninstallResponse
-	(*LibraryUpgradeAllRequest)(nil),           // 9: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
-	(*LibraryUpgradeAllResponse)(nil),          // 10: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
-	(*LibraryResolveDependenciesRequest)(nil),  // 11: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
-	(*LibraryResolveDependenciesResponse)(nil), // 12: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
-	(*LibraryDependencyStatus)(nil),            // 13: cc.arduino.cli.commands.v1.LibraryDependencyStatus
-	(*LibrarySearchRequest)(nil),               // 14: cc.arduino.cli.commands.v1.LibrarySearchRequest
-	(*LibrarySearchResponse)(nil),              // 15: cc.arduino.cli.commands.v1.LibrarySearchResponse
-	(*SearchedLibrary)(nil),                    // 16: cc.arduino.cli.commands.v1.SearchedLibrary
-	(*LibraryRelease)(nil),                     // 17: cc.arduino.cli.commands.v1.LibraryRelease
-	(*LibraryDependency)(nil),                  // 18: cc.arduino.cli.commands.v1.LibraryDependency
-	(*DownloadResource)(nil),                   // 19: cc.arduino.cli.commands.v1.DownloadResource
-	(*LibraryListRequest)(nil),                 // 20: cc.arduino.cli.commands.v1.LibraryListRequest
-	(*LibraryListResponse)(nil),                // 21: cc.arduino.cli.commands.v1.LibraryListResponse
-	(*InstalledLibrary)(nil),                   // 22: cc.arduino.cli.commands.v1.InstalledLibrary
-	(*Library)(nil),                            // 23: cc.arduino.cli.commands.v1.Library
-	(*ZipLibraryInstallRequest)(nil),           // 24: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
-	(*ZipLibraryInstallResponse)(nil),          // 25: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
-	(*GitLibraryInstallRequest)(nil),           // 26: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
-	(*GitLibraryInstallResponse)(nil),          // 27: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
-	nil,                                        // 28: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry
-	nil,                                        // 29: cc.arduino.cli.commands.v1.Library.PropertiesEntry
-	nil,                                        // 30: cc.arduino.cli.commands.v1.Library.CompatibleWithEntry
-	(*Instance)(nil),                           // 31: cc.arduino.cli.commands.v1.Instance
-	(*DownloadProgress)(nil),                   // 32: cc.arduino.cli.commands.v1.DownloadProgress
-	(*TaskProgress)(nil),                       // 33: cc.arduino.cli.commands.v1.TaskProgress
+	(*LibraryUpgradeRequest)(nil),              // 7: cc.arduino.cli.commands.v1.LibraryUpgradeRequest
+	(*LibraryUpgradeResponse)(nil),             // 8: cc.arduino.cli.commands.v1.LibraryUpgradeResponse
+	(*LibraryUninstallRequest)(nil),            // 9: cc.arduino.cli.commands.v1.LibraryUninstallRequest
+	(*LibraryUninstallResponse)(nil),           // 10: cc.arduino.cli.commands.v1.LibraryUninstallResponse
+	(*LibraryUpgradeAllRequest)(nil),           // 11: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
+	(*LibraryUpgradeAllResponse)(nil),          // 12: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
+	(*LibraryResolveDependenciesRequest)(nil),  // 13: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
+	(*LibraryResolveDependenciesResponse)(nil), // 14: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
+	(*LibraryDependencyStatus)(nil),            // 15: cc.arduino.cli.commands.v1.LibraryDependencyStatus
+	(*LibrarySearchRequest)(nil),               // 16: cc.arduino.cli.commands.v1.LibrarySearchRequest
+	(*LibrarySearchResponse)(nil),              // 17: cc.arduino.cli.commands.v1.LibrarySearchResponse
+	(*SearchedLibrary)(nil),                    // 18: cc.arduino.cli.commands.v1.SearchedLibrary
+	(*LibraryRelease)(nil),                     // 19: cc.arduino.cli.commands.v1.LibraryRelease
+	(*LibraryDependency)(nil),                  // 20: cc.arduino.cli.commands.v1.LibraryDependency
+	(*DownloadResource)(nil),                   // 21: cc.arduino.cli.commands.v1.DownloadResource
+	(*LibraryListRequest)(nil),                 // 22: cc.arduino.cli.commands.v1.LibraryListRequest
+	(*LibraryListResponse)(nil),                // 23: cc.arduino.cli.commands.v1.LibraryListResponse
+	(*InstalledLibrary)(nil),                   // 24: cc.arduino.cli.commands.v1.InstalledLibrary
+	(*Library)(nil),                            // 25: cc.arduino.cli.commands.v1.Library
+	(*ZipLibraryInstallRequest)(nil),           // 26: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
+	(*ZipLibraryInstallResponse)(nil),          // 27: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
+	(*GitLibraryInstallRequest)(nil),           // 28: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
+	(*GitLibraryInstallResponse)(nil),          // 29: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
+	nil,                                        // 30: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry
+	nil,                                        // 31: cc.arduino.cli.commands.v1.Library.PropertiesEntry
+	nil,                                        // 32: cc.arduino.cli.commands.v1.Library.CompatibleWithEntry
+	(*Instance)(nil),                           // 33: cc.arduino.cli.commands.v1.Instance
+	(*DownloadProgress)(nil),                   // 34: cc.arduino.cli.commands.v1.DownloadProgress
+	(*TaskProgress)(nil),                       // 35: cc.arduino.cli.commands.v1.TaskProgress
 }
 var file_cc_arduino_cli_commands_v1_lib_proto_depIdxs = []int32{
-	31, // 0: cc.arduino.cli.commands.v1.LibraryDownloadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	32, // 1: cc.arduino.cli.commands.v1.LibraryDownloadResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
-	31, // 2: cc.arduino.cli.commands.v1.LibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	32, // 3: cc.arduino.cli.commands.v1.LibraryInstallResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
-	33, // 4: cc.arduino.cli.commands.v1.LibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	31, // 5: cc.arduino.cli.commands.v1.LibraryUninstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	33, // 6: cc.arduino.cli.commands.v1.LibraryUninstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	31, // 7: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	32, // 8: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
-	33, // 9: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	31, // 10: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	13, // 11: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse.dependencies:type_name -> cc.arduino.cli.commands.v1.LibraryDependencyStatus
-	31, // 12: cc.arduino.cli.commands.v1.LibrarySearchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	16, // 13: cc.arduino.cli.commands.v1.LibrarySearchResponse.libraries:type_name -> cc.arduino.cli.commands.v1.SearchedLibrary
-	0,  // 14: cc.arduino.cli.commands.v1.LibrarySearchResponse.status:type_name -> cc.arduino.cli.commands.v1.LibrarySearchStatus
-	28, // 15: cc.arduino.cli.commands.v1.SearchedLibrary.releases:type_name -> cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry
-	17, // 16: cc.arduino.cli.commands.v1.SearchedLibrary.latest:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
-	19, // 17: cc.arduino.cli.commands.v1.LibraryRelease.resources:type_name -> cc.arduino.cli.commands.v1.DownloadResource
-	18, // 18: cc.arduino.cli.commands.v1.LibraryRelease.dependencies:type_name -> cc.arduino.cli.commands.v1.LibraryDependency
-	31, // 19: cc.arduino.cli.commands.v1.LibraryListRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	22, // 20: cc.arduino.cli.commands.v1.LibraryListResponse.installed_libraries:type_name -> cc.arduino.cli.commands.v1.InstalledLibrary
-	23, // 21: cc.arduino.cli.commands.v1.InstalledLibrary.library:type_name -> cc.arduino.cli.commands.v1.Library
-	17, // 22: cc.arduino.cli.commands.v1.InstalledLibrary.release:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
-	29, // 23: cc.arduino.cli.commands.v1.Library.properties:type_name -> cc.arduino.cli.commands.v1.Library.PropertiesEntry
-	2,  // 24: cc.arduino.cli.commands.v1.Library.location:type_name -> cc.arduino.cli.commands.v1.LibraryLocation
-	1,  // 25: cc.arduino.cli.commands.v1.Library.layout:type_name -> cc.arduino.cli.commands.v1.LibraryLayout
-	30, // 26: cc.arduino.cli.commands.v1.Library.compatible_with:type_name -> cc.arduino.cli.commands.v1.Library.CompatibleWithEntry
-	31, // 27: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	33, // 28: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	31, // 29: cc.arduino.cli.commands.v1.GitLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	33, // 30: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	17, // 31: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
-	32, // [32:32] is the sub-list for method output_type
-	32, // [32:32] is the sub-list for method input_type
-	32, // [32:32] is the sub-list for extension type_name
-	32, // [32:32] is the sub-list for extension extendee
-	0,  // [0:32] is the sub-list for field type_name
+	33, // 0: cc.arduino.cli.commands.v1.LibraryDownloadRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	34, // 1: cc.arduino.cli.commands.v1.LibraryDownloadResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
+	33, // 2: cc.arduino.cli.commands.v1.LibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	34, // 3: cc.arduino.cli.commands.v1.LibraryInstallResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
+	35, // 4: cc.arduino.cli.commands.v1.LibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	33, // 5: cc.arduino.cli.commands.v1.LibraryUpgradeRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	34, // 6: cc.arduino.cli.commands.v1.LibraryUpgradeResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
+	35, // 7: cc.arduino.cli.commands.v1.LibraryUpgradeResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	33, // 8: cc.arduino.cli.commands.v1.LibraryUninstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	35, // 9: cc.arduino.cli.commands.v1.LibraryUninstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	33, // 10: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	34, // 11: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse.progress:type_name -> cc.arduino.cli.commands.v1.DownloadProgress
+	35, // 12: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	33, // 13: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	15, // 14: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse.dependencies:type_name -> cc.arduino.cli.commands.v1.LibraryDependencyStatus
+	33, // 15: cc.arduino.cli.commands.v1.LibrarySearchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	18, // 16: cc.arduino.cli.commands.v1.LibrarySearchResponse.libraries:type_name -> cc.arduino.cli.commands.v1.SearchedLibrary
+	0,  // 17: cc.arduino.cli.commands.v1.LibrarySearchResponse.status:type_name -> cc.arduino.cli.commands.v1.LibrarySearchStatus
+	30, // 18: cc.arduino.cli.commands.v1.SearchedLibrary.releases:type_name -> cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry
+	19, // 19: cc.arduino.cli.commands.v1.SearchedLibrary.latest:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
+	21, // 20: cc.arduino.cli.commands.v1.LibraryRelease.resources:type_name -> cc.arduino.cli.commands.v1.DownloadResource
+	20, // 21: cc.arduino.cli.commands.v1.LibraryRelease.dependencies:type_name -> cc.arduino.cli.commands.v1.LibraryDependency
+	33, // 22: cc.arduino.cli.commands.v1.LibraryListRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	24, // 23: cc.arduino.cli.commands.v1.LibraryListResponse.installed_libraries:type_name -> cc.arduino.cli.commands.v1.InstalledLibrary
+	25, // 24: cc.arduino.cli.commands.v1.InstalledLibrary.library:type_name -> cc.arduino.cli.commands.v1.Library
+	19, // 25: cc.arduino.cli.commands.v1.InstalledLibrary.release:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
+	31, // 26: cc.arduino.cli.commands.v1.Library.properties:type_name -> cc.arduino.cli.commands.v1.Library.PropertiesEntry
+	2,  // 27: cc.arduino.cli.commands.v1.Library.location:type_name -> cc.arduino.cli.commands.v1.LibraryLocation
+	1,  // 28: cc.arduino.cli.commands.v1.Library.layout:type_name -> cc.arduino.cli.commands.v1.LibraryLayout
+	32, // 29: cc.arduino.cli.commands.v1.Library.compatible_with:type_name -> cc.arduino.cli.commands.v1.Library.CompatibleWithEntry
+	33, // 30: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	35, // 31: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	33, // 32: cc.arduino.cli.commands.v1.GitLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	35, // 33: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	19, // 34: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
+	35, // [35:35] is the sub-list for method output_type
+	35, // [35:35] is the sub-list for method input_type
+	35, // [35:35] is the sub-list for extension type_name
+	35, // [35:35] is the sub-list for extension extendee
+	0,  // [0:35] is the sub-list for field type_name
 }
 
 func init() { file_cc_arduino_cli_commands_v1_lib_proto_init() }
@@ -2533,7 +2681,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryUninstallRequest); i {
+			switch v := v.(*LibraryUpgradeRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2545,7 +2693,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryUninstallResponse); i {
+			switch v := v.(*LibraryUpgradeResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2557,7 +2705,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryUpgradeAllRequest); i {
+			switch v := v.(*LibraryUninstallRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2569,7 +2717,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryUpgradeAllResponse); i {
+			switch v := v.(*LibraryUninstallResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2581,7 +2729,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryResolveDependenciesRequest); i {
+			switch v := v.(*LibraryUpgradeAllRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2593,7 +2741,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryResolveDependenciesResponse); i {
+			switch v := v.(*LibraryUpgradeAllResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2605,7 +2753,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryDependencyStatus); i {
+			switch v := v.(*LibraryResolveDependenciesRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2617,7 +2765,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibrarySearchRequest); i {
+			switch v := v.(*LibraryResolveDependenciesResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2629,7 +2777,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibrarySearchResponse); i {
+			switch v := v.(*LibraryDependencyStatus); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2641,7 +2789,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*SearchedLibrary); i {
+			switch v := v.(*LibrarySearchRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2653,7 +2801,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryRelease); i {
+			switch v := v.(*LibrarySearchResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2665,7 +2813,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryDependency); i {
+			switch v := v.(*SearchedLibrary); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2677,7 +2825,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DownloadResource); i {
+			switch v := v.(*LibraryRelease); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2689,7 +2837,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryListRequest); i {
+			switch v := v.(*LibraryDependency); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2701,7 +2849,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LibraryListResponse); i {
+			switch v := v.(*DownloadResource); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2713,7 +2861,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*InstalledLibrary); i {
+			switch v := v.(*LibraryListRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2725,7 +2873,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Library); i {
+			switch v := v.(*LibraryListResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2737,7 +2885,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ZipLibraryInstallRequest); i {
+			switch v := v.(*InstalledLibrary); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2749,7 +2897,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ZipLibraryInstallResponse); i {
+			switch v := v.(*Library); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2761,7 +2909,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GitLibraryInstallRequest); i {
+			switch v := v.(*ZipLibraryInstallRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -2773,6 +2921,30 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ZipLibraryInstallResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GitLibraryInstallRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_cc_arduino_cli_commands_v1_lib_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GitLibraryInstallResponse); i {
 			case 0:
 				return &v.state
@@ -2791,7 +2963,7 @@ func file_cc_arduino_cli_commands_v1_lib_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_cc_arduino_cli_commands_v1_lib_proto_rawDesc,
 			NumEnums:      3,
-			NumMessages:   28,
+			NumMessages:   30,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.proto b/rpc/cc/arduino/cli/commands/v1/lib.proto
index d4cc36864ea..cae03fcc6cf 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.proto
+++ b/rpc/cc/arduino/cli/commands/v1/lib.proto
@@ -57,6 +57,23 @@ message LibraryInstallResponse {
   TaskProgress task_progress = 2;
 }
 
+message LibraryUpgradeRequest {
+  // Arduino Core Service instance from the `Init` response.
+  Instance instance = 1;
+  // Name of the library.
+  string name = 2;
+  // Set to true to skip installation of specified library's dependencies,
+  // defaults to false.
+  bool no_deps = 3;
+}
+
+message LibraryUpgradeResponse {
+  // Progress of the library download.
+  DownloadProgress progress = 1;
+  // Description of the current stage of the installation.
+  TaskProgress task_progress = 2;
+}
+
 message LibraryUninstallRequest {
   // Arduino Core Service instance from the `Init` response.
   Instance instance = 1;