Toolbox App Help

Remote Development API

Implement the Remote Development extension and provider. This section explains data flows, lifecycle, and recommended patterns.

Entry point

  • Registration: JetBrains Toolbox uses Java ServiceLoader to discover RemoteDevExtension in your JAR files (see META-INF/services/...).

  • RemoteDevExtension (functional interface): create your RemoteProvider using ServiceLocator.

RemoteProvider

  • Lifecycle:

    • Instances may be created and closed multiple times. Avoid leaking resources.

    • Defer expensive work until setVisible signals interest.

  • Recommended patterns:

    • Keep a single coroutine scope per provider; it is provided to you obtainable via ServiceLocator.

    • Expose environment lists with LoadableState (Loading/Ready/Error) to improve perceived performance.

RemoteProvider components

  • Identity and visuals: name, iconResource, noEnvironmentsIconResource, descriptions

  • Capabilities: canCreateNewEnvironments, isSingleEnvironment

  • Data: environments: Flow<LoadableState<List<RemoteProviderEnvironment>>>

  • Visibility: setVisible(ProviderVisibilityState)

  • UI: getNewEnvironmentUiPage(), getOverrideUiPage(), additionalPluginActions

  • Account UI: getAccountDropDown()

  • Deep link: handleUri(uri: URI) (intercepts jetbrains://gateway/<provider-id>/...)

  • Diagnostics: getDiagnosticInfoCollector()

  • Optional: refresh()

RemoteProviderEnvironment

State model: your environment should expose state and description promptly when visible.

  • Use StandardRemoteEnvironmentState for common cases (Disconnected/Connecting/Connected/Disconnecting).

  • Use CustomRemoteEnvironmentState(V2) for advanced states with custom colors/icons.

Deletion UX: prefer deleteActionFlow over deprecated onDelete().

RemoteProviderEnvironment components

  • Identity: id, nameFlow (deprecated name setter kept for compatibility)

  • Features: supportedFeatures: Set<RemoteEnvironmentAbility>

  • Tabs: pageTabs: List<TabDefinition> (defaults include projects or tools tabs)

  • State and description: state: StateFlow<RemoteEnvironmentState>, description: StateFlow<EnvironmentDescription>

  • Connect/disconnect programmatically: connectionRequest: Flow<Boolean>?

  • Actions: actionsList: StateFlow<List<ActionDescription>>

  • Visibility: setVisible(EnvironmentVisibilityState)

  • Hooks: getBeforeConnectionHooks(), getAfterDisconnectHooks()

  • Deletion: getDeleteEnvironmentConfirmationParams(), deleteActionFlow

  • Issues: getEnvironmentIssueFlow(): Flow<EnvironmentIssue?>

  • Diagnostics: diagnosticInfoCollector

  • Additional info: additionalEnvironmentInformation: Map<LocalizableString, String>?

  • Contents view: getContentsView(): EnvironmentContentsView

EnvironmentContentsView and variants

Use the following Decision guide:

  • If you control the host and can run the agent upfront, implement AgentConnectionBasedEnvironmentContentsView.

  • If SSH is available, SshEnvironmentContentsView is the simplest integration (JetBrains Toolbox handles deployment and flows).

  • If the environment is offline, supplement with ManualEnvironmentContentsView for early UI.

  • If you have custom networking, implement PortForwardingCapableEnvironmentContentsView.

  • Base sealed interface, close(); getSupportsRedeploy() flag

  • At least one of the following:

    • SshEnvironmentContentsView: return SshConnectionInfo; redeploy supported by default

    • AgentConnectionBasedEnvironmentContentsView: return AgentConnectionHandle

  • Optional mix-ins are as follows:

    • ManualEnvironmentContentsView: ideListState, projectListState of LoadableState<List<Cached*Stub>>

    • PortForwardingCapableEnvironmentContentsView: getHostTunnelConnector()

Connections and helpers

ToolboxProxySettings:

  • Access the user-configured HTTP/SOCKS proxy as a Proxy or ProxySelector.

  • Listen for changes with addProxyChangeListener. Reconfigure your clients on change.

  • If getProxyAuth() returns Basic, set the Proxy-Authorization header accordingly.

Check the following (OkHttp) example:

val proxySettings = serviceLocator.getService<ToolboxProxySettings>() val proxy = proxySettings.getProxy() val proxySelector = proxySettings.getProxySelector() val clientBuilder = OkHttpClient.Builder() if (proxy != null) clientBuilder.proxy(proxy) if (proxySelector != null) clientBuilder.proxySelector(proxySelector) val auth = proxySettings.getProxyAuth() if (auth is ProxyAuth.Basic) { val creds = Credentials.basic(auth.username, auth.password) clientBuilder.proxyAuthenticator { _, response -> response.request.newBuilder().header("Proxy-Authorization", creds).build() } }

For the ClientHelper:

  • Pre-download the IDE clients for specific host versions to speed up first connections.

  • Request automatic client connection once environment becomes connected.

Check the following example:

val ch = serviceLocator.getService<ClientHelper>() ch.prepareClient(environmentId = env.id, hostIdeVersion = "IU-251.*") ch.connectToIde(environmentId = env.id, ideVersionHint = "IU-251.*", projectPathHint = "/home/user/project")

For RemoteToolsHelper (experimental):

  • Inspect and manage IDEs/tools on the host (server side) by hint.

  • Toolbox installs the latest version matching the hint.

Check the following example:

val tools = serviceLocator.getService<RemoteToolsHelper>() val available = tools.getAvailableRemoteTools(env.id, hint = "IU-251.*") val installed = tools.getInstalledRemoteTools(env.id, hint = "IU-*") val ok = tools.installRemoteTool(env.id, hint = "IU-251.*")

For the SshConnectionValidator:

  • Validate SSH configuration before attempting to connect.

  • Returns a list of SshValidationFailure subclasses describing issues (host key, permissions, agent conflicts, and so on).

Check the following example:

val validator = serviceLocator.getService<SshConnectionValidator>() val failures = validator.validate(env.id, connectionInfo) if (failures.isNotEmpty()) { // show a UI page with guidance, or map to human-readable errors }

Agent deployment helpers

  • AgentDistributionProvider: obtain agent binaries suitable for your host platform. DeploymentSettings and DeploymentTarget: configure deployment flow for SSH flows; pre-seed locations, retries, and permissions.

Logs and diagnostics

  • LogCollector: contribute environment-specific logs (JetBrains Toolbox already collects IDE/Agent logs when connected).

  • DiagnosticInfoCollector: attach plugin-specific logs or state snapshots to the support bundle.

UI integration

  • EnvironmentUiPageManager: request JetBrains Toolbox to re-evaluate or switch the plugin’s environments UI (such as after login completes).

  • ToolboxProxySettings, ClientHelper, RemoteToolsHelper

  • SSH validation helpers: SshConnectionValidator, SshValidationFailure

  • Agent deployment: AgentDistributionProvider, DeploymentSettings, DeploymentTarget

  • Logs: LogCollector, DiagnosticInfoCollector

  • UI integration: EnvironmentUiPageManager

  • Your provider receives all URIs of the form jetbrains://gateway/<provider-id>/... in handleUri.

  • Use this to complete OAuth flows, open specific environments, or trigger actions.

  • As a side effect, JetBrains Toolbox App will suggest installing your plugin if it is not installed.

Diagnostics and logs

  • Return DiagnosticInfoCollector from provider/environment to add files to the diagnostic bundle.

  • Ensure you do not include secrets; prefer redaction where needed.

11 September 2025