# LivePlugin and the case for writing IntelliJ plugins without a plugin project

> LivePlugin loads Kotlin or Groovy scripts into the running IDE JVM and reloads them on demand. It removes the plugin project overhead and the restart cycle, at the cost of several limits the README states plainly.

**dkandalov/live-plugin** — IntelliJ plugin for writing IntelliJ plugins at runtime ⚡️

- Repository: https://github.com/dkandalov/live-plugin
- Website: https://plugins.jetbrains.com/plugin/7282
- Stars: 950 · Forks: 73
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/dkandalov-live-plugin

## A plugin that runs your plugin code in the IDE that is already open

LivePlugin is an IntelliJ plugin for IntelliJ based IDEs, and its whole purpose is to let you write plugin code while the IDE is running. You write a script in Kotlin or Groovy, you run it, and the code executes inside the IDE process. The project's description puts it plainly: an IntelliJ plugin for writing IntelliJ plugins at runtime.

The problem it solves is the plugin development loop itself. A normal IntelliJ plugin lives in its own Gradle project, gets compiled, packaged, and installed, and any change means a rebuild and an IDE restart. LivePlugin removes both halves of that. The README lists the reasons as minimal setup, a fast feedback loop with plugins reloaded in the same JVM instance as the IDE, and a usable IDE API with entry points for common IDE APIs.

The audience is IntelliJ developers and the people who script their IDE. The listed use cases are project-specific workflow automation, integrating shell scripts with the IDE, and prototyping plugins while experimenting with the IntelliJ API. That is a different user from someone shipping a plugin to the Marketplace, and the difference shows up later in the project design.

Installing it means going to IDE Settings, then Plugins, then Marketplace and searching for LivePlugin, or using the Install button on the Plugin Marketplace website at plugins.jetbrains.com/plugin/7282. There is no download link to chase and no configuration file to edit before the first run.

## Disposal, a fresh classloader, then execution on the EDT

The mechanism is described in the README with more precision than most plugin projects offer, and the four steps explain both what works and what does not.

First, if there is an instance of pluginDisposable from a previous execution, that instance is disposed, and this happens on the EDT, the event dispatch thread. Second, a new classloader is created with dependencies on other plugins and jars, on a background thread. Third, the code is compiled if necessary and the classes are loaded in that classloader, also on a background thread. Fourth, the plugin code itself runs on the EDT.

The split between background work and EDT work is the part worth understanding. Compilation and classloading happen off the UI thread, so a slow script does not freeze the window, while the actual plugin action runs on the EDT because that is where IDE state is safe to touch. Because the plugin runs in the IDE JVM, its code can use internal IDE APIs and observe or change IDE state, which is exactly what is not possible from an external process.

The same architecture explains the limits. A fresh classloader per run means static state from the previous run does not carry over, and the README names two concrete limitations: final fields, and IDE APIs which are not designed to be re-initialized. Anything you register with the IDE and then expect to replace on the next run is the risk area.

## Running a hello world and reloading it from the tool window

The README walks through a first run in a specific order, and the order is the point: you confirm the basic path works before you change anything.

In the Live Plugins tool window, select the hello-world plugin and click the Run button, which is the Run Plugin action bound to ctrl+shift+L or alt+C, alt+E. A message should appear. A Groovy plugin of the smallest possible size looks like this.

```groovy
import static liveplugin.PluginUtil.show
show("Hello world") // Shows balloon notification popup with "Hello world" text
```

Then make a small modification in plugin.groovy or plugin.kts and run it again. On the second run the previous version is unloaded before the code is evaluated again. Then modify the script so that it fails to compile or run, and you should see an error message in the Run tool window rather than a silent no-op. Testing the failure case early is worth the minute it costs.

The structural point is that a plugin here is just a folder containing a plugin.groovy or plugin.kts script as its entry point. There is no manifest to write and no descriptor file. The README points out the practical consequence: you can copy the path to the plugin folder with the Copy Path action on ctrl/cmd+alt+C, which makes it easy to keep such a folder inside a project and share it.

Two settings in the same tool window matter for day to day use. Run Plugins on IDE Start runs everything when the IDE boots, and Run Project Specific Plugins runs all plugins in a .live-plugins project directory when the project opens and unloads them when it closes.

## Kotlin gets its own compiler, Groovy borrows the IDE's

The two supported languages are not treated the same way, and the difference shows up in the toolchain rather than in the syntax.

Most IntelliJ based IDEs come with a bundled Groovy jar, and that jar is what LivePlugin uses for loading and running live plugins. If the IDE does not bundle one, the groovy-all jar is downloaded. Kotlin is the opposite case: LivePlugin uses its own version of the Kotlin stdlib and compiler, because the version bundled with IDEs changes quite often and seems to be harder to rely on. Shipping its own compiler removes a class of breakage, at the cost of a larger plugin footprint.

That same asymmetry shows up in editing support. Adding jars from LivePlugin and the IDE to the current project as a library, through the Add LivePlugin and IDE Jars to Project setting, is described as a bit of a hack, but it is useful for Groovy plugins to get auto-completion and code navigation in the plugin code. Kotlin plugins with a single plugin.kts file should have auto-completion and code navigation without it. Multiple Kotlin files are not highlighted at the moment, and the README links a YouTrack issue for that, though such plugins should still compile and run.

So if you are writing in Groovy and want navigation, you will turn that hack on. If you are writing Kotlin, you get less editing help for multi-file plugins today, and that is a known gap rather than a misconfiguration.

## Registering a real action in Kotlin against the IntelliJ API

The bundled examples go past a notification. Here is the Kotlin action from the README, trimmed to the import and the registration call, which registers an Insert New Line Above action bound to ctrl alt shift ENTER.

```kotlin
import com.intellij.openapi.actionSystem.AnActionEvent
import liveplugin.*

registerAction(id = "Insert New Line Above", keyStroke = "ctrl alt shift ENTER") { event: AnActionEvent ->
    val project = event.project ?: return@registerAction
    val editor = event.editor ?: return@registerAction
    executeCommand(editor.document, project) { document ->
        val caretModel = editor.caretModel
        val lineStartOffset = document.getLineStartOffset(caretModel.logicalPosition.line)
        document.insertString(lineStartOffset, "\n")
        caretModel.moveToOffset(caretModel.offset + 1)
    }
}
```

The shape is the interesting part. The event is unpacked with safe calls, the document change goes through executeCommand so the edit is registered with the IDE undo stack rather than applied raw, and the caret is moved afterwards. The README notes that a built-in Start New Line Before Current action already exists on ctrl+alt+enter, so this example is partly a demonstration of the API surface.

For anyone learning the IntelliJ API, the README names two starting points: the PluginUtil class in the Groovy plugin API and the liveplugin package in the Kotlin plugin API, both of which have entry points for common IDE APIs. It also suggests searching the IntelliJ source code for text you can see in the IDE interface, then tracing how that text connects to the code doing the work, which is a more useful technique than reading the API from the top down.

## The escape hatch is a real plugin project, not a better live plugin

LivePlugin is deliberately a prototype stage. The README is explicit about the path forward: once your plugin has grown, move it to a proper plugin project, still using LivePlugin for reloading, and possibly convert it into a dynamic plugin afterwards. The repository even carries a wiki page on LivePlugin as an entry point for standard plugins.

That two-stage route is the honest answer to the question of when to adopt it. A live script is fast to write and fast to reload, but it lives in a folder, is loaded by a classloader, and is bound by the re-initialization limits described earlier. A standard plugin project gets you a real artifact, a version number, a build and a distribution, at the cost of the build cycle you came here to avoid.

The repository layout backs this up. There is a build.gradle and settings.gradle, a gradle wrapper with gradlew and gradlew.bat, a kotlin-compiler-wrapper directory, a plugin-examples directory, and a.live-plugins directory at the top level that matches the project specific setting described earlier. There is also an IntellijApiCheatSheet.md file, which is a faster reference for the API than the plugin itself is.

The examples list also shows where this approach has been taken: intellij-emacs for emacs style macros, a simplistic compile and run haskell action. A workflow written in Groovy against the IDE can be shared by copying a folder, which is a real advantage over a distributed plugin for a small team.

## Beta releases, a last push on 2026-10-19, and an Apache-2.0 licence

The release history is worth reading before you plan around the project. The listed releases are v0.9.8beta on 2025-11-11, v0.9.9beta on 2025-12-20 and v0.9.10beta on 2026-03-19. Every published version carries a beta suffix, and the version numbers sit below 1.0, so a reader should assume the packaging and the API surface may still change between versions.

The repository itself is not archived, and the last push was on 2026-10-19, which is later than the newest tagged release listed above. That gap between the last release tag and the last push is normal for a plugin, but it also means the Marketplace version and the tip of master are not the same thing.

The licence field on the repository says Apache-2.0. The plugin executes with the full privileges of the IDE process, which is a point about trust rather than licensing: a live plugin can reach any API the IDE itself can reach, so what matters operationally is who writes the script folder and what it is allowed to call.

Contributing is documented in CONTRIBUTING.md, and issues are collected in the repository tracker, where the README explicitly invites questions as issues.

## Conclusion

LivePlugin fits IntelliJ developers who want to prototype an IDE extension, script a project-specific workflow or learn the IntelliJ API without assembling a Gradle plugin project, and it fits best when the code is short and re-runnable from the Live Plugins tool window. It does not fit teams that need a signed, published, versioned plugin, because every published release in the project history is tagged beta and the README's own path for a grown plugin is to move it into a proper plugin project and possibly convert it into a dynamic plugin. Before relying on it, check the Groovy and Kotlin language plugins are installed in your IDE, confirm your code avoids final fields and IDE APIs that are not designed to be re-initialized, and read the reload behaviour in the How does LivePlugin work section before you build a workflow on top of it.

## FAQ

### How do I install LivePlugin in an IntelliJ IDE?

Open IDE Settings, go to Plugins, then Marketplace, and search for LivePlugin. You can also use the Install button on the Plugin Marketplace website at plugins.jetbrains.com/plugin/7282.

### How do I run and reload a LivePlugin script?

In the Live Plugins tool window, select the plugin and click the Run button, which is the Run Plugin action on ctrl+shift+L or alt+C, alt+E. On the next run the previous version is unloaded before the new code is evaluated, and a script that fails to compile shows an error in the Run tool window.

### Do I need the Kotlin or Groovy language plugin to use LivePlugin?

It may be useful to install the Kotlin or Groovy plugin if your IDE supports them. Most IntelliJ based IDEs bundle a Groovy jar that LivePlugin uses to load and run live plugins, and LivePlugin ships its own Kotlin stdlib and compiler.

### What are the limitations of reloading a LivePlugin?

The README names two: final fields, and IDE APIs which are not designed to be re-initialized. Since each run uses a new classloader, state left in static fields does not carry over to the next execution.

## Sources

- [dkandalov/live-plugin on GitHub](https://github.com/dkandalov/live-plugin)
- [License: Apache-2.0](https://github.com/dkandalov/live-plugin/blob/master/LICENSE)
- [Project website](https://plugins.jetbrains.com/plugin/7282)
- [README](https://github.com/dkandalov/live-plugin/blob/master/README.md)
- [Releases](https://github.com/dkandalov/live-plugin/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dkandalov-live-plugin
