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.
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)
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?
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).
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?
Hello! Thank you for improving the completion content!
The completion system in the Terminal is quite complex and usage of completion.contributor API was only the detail of the initial implementation.
In the scope of 2026.1 we stopped using it because contracts of the editor’s completion API are not suitable for the Terminal case.
But we have a more suitable API - org.jetbrains.plugins.terminal.block.completion.spec.ShellCommandSpecsProvider.
Please use it to provide specifications for terminal commands. You can define subcommands, options and specify the code that will compute the runtime-dependant arguments.
This way you can avoid implementing the code that strongly relies on the terminal internals - parsing the typed command and inserting the chosen completion item.
Thank you. I tried it, but I’m not sure it will work for my case.
I complete project-defined commands for every call. They might be “a”, “php artisan”, “sail artisan”, or “docker exec php artisan”, etc. In my implementation, I find “a” or “artisan” and start to complete everything after it. In ShellCommandSpecsProvider I have to define every case, right? Or I didn’t get it?
Yes, with ShellCommandSpecsProvider you need to define all these cases.
It is less flexible, indeed.
I would recommend creating a specification for artisan command and defining it in all contexts you need to show the suggestions.
You can define command specs with only artisan subcommand for php, sail and docker with ShellCommandSpecConflictStrategy.OVERRIDE, so your specs will be merged with original ones.
But, there can be a problem if the initial spec is defined using REPLACE strategy - it is not possible to override it. As I remember, we have php spec defined like that.
I think I can manage to address it before the 2026.1 release: IJPL-235142
Well, I could make it work for calls like “a command”, but it doesn’t work for “php artisan command”, probably because of the reason you said.
Honestly, it makes it almost impossible to implement my completion, even if you fix “php” issue. Users can write “docker exec php artisan command” or “de a command” with shorcuts. My current completion works in any case, finding only “artisan” or “a” and completing everything after it… Do you have any other option to implement the completion?
Well, that’s fair. There are can be many ways of how to type your command.
But I think that implementing it for a limited scope of cases would be still beneficial now.
It should cover most common use cases.
The php case doesn’t work because of IJPL-235142. Please leave it for now, I plan to fix it soon.
Regarding shortcuts like “de a command“ - if “de“ is an alias to some command, for example, “docker“, we will expand it in the completion logic. So the command spec for “docker“ will be used to complete here.
We have no other way of extending terminal completion at the moment.
But we will definitely consider the case of commands like “artisan“ that can be used in a lot of different contexts. This case requires a better API: IJPL-235288