Reworked Terminal API is available in 2025.3

Hello everyone!

As you may know, the Reworked Terminal became the default terminal implementation in version 2025.2.

For the upcoming 2025.3 release, we are introducing the base version of the public API. This enables you to integrate the Reworked Terminal into your plugins and benefit from its deeper shell integration. You can find the documentation in the IntelliJ Platform SDK.

The API currently supports the following capabilities:

  • Creating Reworked Terminal tabs in the Terminal Tool Window.
  • Accessing terminal output and text selection.
  • Sending input to the shell process.
  • Adding actions to the terminal.
  • New: Listening for command execution events.

Please note that this API is currently experimental. We are working on it, so you may see slight changes and additions in future releases.

We invite you to try it out! Feel free to share your feedback, questions, and suggestions in this topic or via the YouTrack issue.

4 Likes

How to tell if a user has Reworked Terminal enabled?

Hello! You can use org.jetbrains.plugins.terminal.TerminalOptionsProvider#getTerminalEngine and compare it with TerminalEngine.Reworked.

Hi Konstantin,

I have a plugin where I’m executing shell commands via my own pty, i.e. I’m not executing in the user’s terminal widget, but I’d like to take advantage of IntelliJ’s terminal infrastructure to get a good pty setup. This is what I have right now:

    val base = ShellStartupOptions.Builder().workingDirectory(workingDir).build()

    @Suppress("UnstableApiUsage")
    val configured = LocalOptionsConfigurer.configureStartupOptions(base, project)
    val shellCommand = buildOneOffShellCommand(configured.shellCommand!!, command)

    val env = configured.envVariables
    val dir = configured.workingDirectory!!

    val builder =
        PtyProcessBuilder(shellCommand.toTypedArray())
            .setDirectory(dir)
            .setEnvironment(env)
            .setConsole(true) // PTY mode
            .setInitialColumns(80)
            .setInitialRows(24)

Where:

  private fun buildOneOffShellCommand(shellCommand: List<String>, userCmd: String): List<String> {
    val shellExe = shellCommand.firstOrNull()?.lowercase() ?: "sh"
    return when {
      shellExe.contains("powershell") || shellExe.contains("pwsh") ->
          listOf(
              shellCommand[0],
              "-NoLogo",
              "-NonInteractive",
              "-ExecutionPolicy",
              "Bypass",
              "-Command",
              userCmd,
          )

      shellExe.endsWith("cmd.exe") || shellExe == "cmd" ->
          listOf("cmd.exe", "/d", "/s", "/c", userCmd)

      shellExe.endsWith("fish") || shellExe == "fish" -> listOf("fish", "-l", "-c", userCmd)

      shellExe.endsWith("zsh") || shellExe == "zsh" -> listOf("zsh", "--login", "-c", userCmd)

      shellExe.endsWith("bash") || shellExe == "bash" || shellExe == "sh" ->
          listOf(shellCommand[0], "--login", "-c", userCmd)

      else ->
          // Default POSIX-ish
          listOf(shellCommand[0], "-c", userCmd)
    }
  }

However LocalOptionsConfigurer is marked Internal, is there another way I can do this with the new API? Is there anything in the API which would do something equivalent to buildOneOffShellCommand?

Hi!

LocalOptionsConfigurer is the implementation detail of LocalTerminalDirectRunner we use to start the shell process. Unfortunately, there is no public API that can help to configure shell command line and env variables.
Actually, shell path is taken from the user settings TerminalProjectOptionsProvider#getShellPath. Custom env variables can be taken from getEnvData method.
Also, there is no API to configure “one shot” shell command like buildOneOffShellCommand .

Regarding starting PTY manually, I would suggest to use com.intellij.platform.eel.EelExecApi#spawnProcess - it is a new API for starting processes. Its benefit is that it can start the process both locally and remotely (for example, when project is opened in WSL or inside docker container).

Hi, @konstantin.hudyakov !

I’ve implemented a completion for project console commands in my plugin (https://x.com/laravel_idea/status/2021220594239312181) using <completion.contributor language="any">. It works in 253, but doesn’t in 261. Are there any changes? Is it still possible to complete in the terminal?