{"id":13754828,"url":"https://github.com/dkandalov/live-plugin","last_synced_at":"2025-05-15T01:06:29.611Z","repository":{"id":1745605,"uuid":"2571524","full_name":"dkandalov/live-plugin","owner":"dkandalov","description":"IntelliJ plugin for writing IntelliJ plugins at runtime ⚡️","archived":false,"fork":false,"pushed_at":"2025-04-28T22:20:14.000Z","size":61141,"stargazers_count":894,"open_issues_count":43,"forks_count":68,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-28T23:35:10.019Z","etag":null,"topics":["dynamic-plugin","groovy","groovy-language","groovy-script","ide","intellij-api","intellij-plugin","kotlin","kotlin-script","micro-plugin"],"latest_commit_sha":null,"homepage":"https://plugins.jetbrains.com/plugin/7282","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dkandalov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":["https://www.buymeacoffee.com/dmitrykandalov"]}},"created_at":"2011-10-13T18:41:43.000Z","updated_at":"2025-04-28T22:20:18.000Z","dependencies_parsed_at":"2024-01-13T02:49:16.936Z","dependency_job_id":"093770b4-4a9f-45b1-bf60-b529a4a01065","html_url":"https://github.com/dkandalov/live-plugin","commit_stats":{"total_commits":1663,"total_committers":16,"mean_commits":103.9375,"dds":0.0198436560432953,"last_synced_commit":"19a828195f06474e055559a9a009b130fccf0bad"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkandalov%2Flive-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkandalov%2Flive-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkandalov%2Flive-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkandalov%2Flive-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkandalov","download_url":"https://codeload.github.com/dkandalov/live-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254041,"owners_count":22039792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dynamic-plugin","groovy","groovy-language","groovy-script","ide","intellij-api","intellij-plugin","kotlin","kotlin-script","micro-plugin"],"created_at":"2024-08-03T10:00:34.639Z","updated_at":"2025-05-15T01:06:24.600Z","avatar_url":"https://github.com/dkandalov.png","language":"Kotlin","readme":"[![Build Status](https://github.com/dkandalov/live-plugin/workflows/CI/badge.svg)](https://github.com/dkandalov/live-plugin/actions)\n\n# LivePlugin\nPlugin for [IntelliJ](https://github.com/JetBrains/intellij-community)-based IDEs to create plugins at runtime\nusing [Kotlin](http://kotlinlang.org) and [Groovy](http://groovy.codehaus.org).\nTo install search for \"LivePlugin\" in `IDE Preferences -\u003e Plugins -\u003e Marketplace`\nor use the \"Install\" button on the [Plugin Marketplace website](http://plugins.jetbrains.com/plugin/7282).\n\n\u003cimg src=\"https://raw.github.com/dkandalov/live-plugin/master/screenshots/live-plugin-demo.gif\" alt=\"demo\" title=\"demo\" align=\"middle\"/\u003e\n\n\n## Table of Contents\n- [Why?](#why)\n- [Examples](#examples)\n- [Getting started](#getting-started)\n- [How does LivePlugin work?](#how-does-liveplugin-work)\n- [Some practical use cases](#some-practical-use-cases)\n- [More examples](#more-examples)\n- [Similar plugins](#similar-plugins)\n- [Contributing](#contributing)\n\n\n## Why?\n - **Minimal setup** — no need to set up a separate project for plugin development\n - **Fast feedback loop** — plugins are (re)loaded in the same JVM instance as IDE without restart\n - **Usable IDE API** — LivePlugin has a small API with entry points for common IDE APIs\n\n\n## Examples\nHello world (Groovy):\n```groovy\nimport static liveplugin.PluginUtil.show\nshow(\"Hello world\") // Shows balloon notification popup with \"Hello world\" text\n```\nInsert New Line Above action (Kotlin):\n```kotlin\nimport com.intellij.openapi.actionSystem.AnActionEvent\nimport liveplugin.*\n\n// Action to insert a new line above the current line.\n// Based on this post https://martinfowler.com/bliki/InternalReprogrammability.html\n// Note that there is also built-in \"Start New Line Before Current\" action (ctrl+alt+enter).\nregisterAction(id = \"Insert New Line Above\", keyStroke = \"ctrl alt shift ENTER\") { event: AnActionEvent -\u003e\n    val project = event.project ?: return@registerAction\n    val editor = event.editor ?: return@registerAction\n    executeCommand(editor.document, project) { document -\u003e\n        val caretModel = editor.caretModel\n        val lineStartOffset = document.getLineStartOffset(caretModel.logicalPosition.line)\n        document.insertString(lineStartOffset, \"\\n\")\n        caretModel.moveToOffset(caretModel.offset + 1)\n    }\n}\nshow(\"Loaded 'Insert New Line Above' action\u003cbr/\u003eUse 'ctrl+alt+shift+Enter' to run it\")\n```\n\n\n## Getting started\nMake sure \"hello world\" works fine:\n- In the `Live Plugins` tool window select \"hello-world\" plugin and click \"Run\" button to execute the plugin \n  (`Run Plugin` action with `ctrl+shift+L` or `alt+C, alt+E` shortcut). It should display a message.\n- Make a small modification in `plugin.groovy`/`plugin.kts` and rerun the plugin. \n  On the second run, the previous version of the plugin will be unloaded before the code is evaluated again.\n- Modify `plugin.groovy`/`plugin.kts` file so that it fails to compile/run.\n  You should see an error message in the `Run` tool window.\n- Note that plugins are just folders with `plugin.groovy` or `plugin.kts` scripts as entry points. \n  This means that you can, for example, copy the path to the plugin folder using the `Copy Path` action (`ctrl/cmd+alt+C` shortcut).\n\nTry bundled examples:\n- In the `Live Plugins` tool window click the \"Plus\" button (`Add Plugin` action) to add Kotlin or Groovy examples. \n- It might be useful to install [Kotlin](https://plugins.jetbrains.com/plugin/6954-kotlin) or \n[Groovy](http://plugins.jetbrains.com/plugin/1524?pr=idea) plugin if your IDE supports them. \n\nTake a look at settings in the `Live Plugins` tool window:\n- `Run Plugins on IDE Start` — run all plugins on IDE start.\n- `Run Project Specific Plugins` — run all plugins in `.live-plugins` project directory when \nthe project is opened and unload them when the project is closed.\n- `Add LivePlugin and IDE Jars to Project` — add jars from LivePlugin and IDE to the current project as a library (see `Project Settings -\u003e Modules`).\nAdding unrelated jars to your project is a bit of a hack, but it can be useful for Groovy plugins to get auto-completion and code navigation in the plugin code.\nKotlin plugins with a single `plugin.kts` should have auto-completion and code navigation without it.\nMultiple Kotlin files are not highlighted at the moment (see [this YouTrack issue](https://github.com/dkandalov/live-plugin/issues/105)) but should compile and run.\n\nLearn more about IntelliJ API:\n- Read (or at least skim) [plugin development fundamentals](https://plugins.jetbrains.com/docs/intellij/fundamentals.html).\n- Explore [IntelliJ source code](https://github.com/JetBrains/intellij-community)\nby cloning it, browsing it on GitHub or in \n[Upsource](https://upsource.jetbrains.com/idea-ce/structure/idea-ce-ba0c8fc9ab9bf23a71a6a963cd84fc89b09b9fc8/).\n  One useful strategy is to search for text you can see in IDE UI and then figure out \n  how it's connected to the code which does the actual work.\n- [PluginUtil](https://github.com/dkandalov/live-plugin/blob/master/src/plugin-api-groovy/liveplugin/PluginUtil.groovy) class\n  and [liveplugin](https://github.com/dkandalov/live-plugin/tree/master/src/plugin-api-kotlin/liveplugin) package\n  might have some good starting points to explore IntelliJ API.\n\nOnce your plugin has grown, you can move it to a proper plugin project \n[still using live plugin for reloading](https://github.com/dkandalov/live-plugin/wiki/Liveplugin-as-an-entry-point-for-standard-plugins)\nand maybe then convert it to become a [dynamic plugin](https://plugins.jetbrains.com/docs/intellij/dynamic-plugins.html).\n\nIf something doesn't work or doesn't make sense, please feel free to ask\nin `#plugin-live-plugin` channel on [Jetbrains platform slack](https://plugins.jetbrains.com/slack)\nor [report an issue](https://github.com/dkandalov/live-plugin/issues) \n(it's ok to report an issue even if it's just a question).\n\n\n## How does LivePlugin work?\nOverall, the idea is just to load and run plugin Groovy or Kotlin classes in the IDE JVM at runtime.\nMore specifically the steps are:\n- if there is an instance of `pluginDisposable` from previous execution, then dispose it (on EDT)\n- create a new classloader with dependencies on other plugins and jars (on a background thread)\n- compile code if necessary and load classes in the classloader (on a background thread)\n- run the plugin code (on EDT)\n\nThis means that plugin code can use any internal IDE API and observe/change IDE state.\nThere are some limitations of course, such as `final` fields and IDE APIs which are not designed to be re-initialized. \n\nMost IntelliJ-based IDEs come with a bundled Groovy jar which is used for loading and running live plugins\n(otherwise, the groovy-all jar will be downloaded). LivePlugin uses its own version of Kotlin stdlib and compiler because\nthe version bundled with IDEs changes quite often and seems to be harder to rely on.\n\n\n## Some practical use cases\n- project-specific workflow automation\n- integrating shell scripts with IDE\n- prototyping plugins, experimenting with IntelliJ API\n\n\n## More examples\n - [intellij-emacs](https://github.com/kenfox/intellij-emacs) - macros for making IntelliJ more friendly to emacs users (see also [blog post](http://spin.atomicobject.com/2014/08/07/intellij-emacs/))\n - [Simplistic \"compile and run haskell\" action](https://gist.github.com/dkandalov/11051113) - this can also be done for other languages/environments\n - [Google quick search popup](https://gist.github.com/dkandalov/277800d12ecbfc533fcd) - prototype of Google popup search mini-plugin\n - [Scripting a macros](https://github.com/dkandalov/live-plugin/wiki/Scripting-a-macros) - example of finding and invoking built-in actions\n - [Console filter/transform example](https://github.com/dkandalov/live-plugin/wiki/Console-filtering) - example of filtering and changing console output\n - [VCS update listener example](https://gist.github.com/dkandalov/8840509) - example of adding callback on VCS update\n - [Find class dependencies](https://gist.github.com/dkandalov/6976133) - simple action to find all class dependencies within current project\n - [Module transitive dependencies](https://gist.github.com/dkandalov/80d8d4f71bef54290a71) - finds all transitive dependencies for modules in IDEA project\n - [Show text diff](https://gist.github.com/dkandalov/6728950) - really lame example of opening IntelliJ text diff window (please don't use it!)\n - [Find all recursive methods in project (for Java)](https://gist.github.com/dkandalov/7248184) - quick plugin as a follow-up for this [talk](http://skillsmatter.com/podcast/nosql/using-graphs-for-source-code-analysis)\n - [Watching projects open/close events](https://gist.github.com/dkandalov/6427087) - an example of reloadable project listener\n - [Minimalistic view for java code](https://gist.github.com/dkandalov/708664109a37c3c0ff15) - collapses most of Java keywords and types leaving only variable names\n - [Symbolize keywords](https://gist.github.com/dkandalov/5553999) - collapses Java keywords into shorter symbols\n - [Change List Size Watchdog](https://gist.github.com/dkandalov/5004622) - micro-plugin to show warning when change list size exceeds threshold (see also [Limited WIP plugin](https://github.com/dkandalov/limited-wip))\n - [Template completion on \"Tab\"](https://gist.github.com/dkandalov/5222759) - simplistic prototype for auto-completion on tab key (in case built-in live templates are not enough)\n - [Completion contributor example](https://gist.github.com/dkandalov/5977888) - only gives an idea which part of IntelliJ API to use\n - [Google auto-completion contributor example](https://github.com/dkandalov/live-plugin/wiki/Google-auto-complete) - same as above but with Google search plugged in\n - [Add custom search example](https://gist.github.com/dkandalov/5956923) - only gives an idea which part of IntelliJ API to use\n - [Get files from last commits example](https://gist.github.com/dkandalov/5984577) - gets VirtualFiles from several last commits\n - [Show PSI view dialog](https://gist.github.com/dkandalov/5979943) - one-liner to show PSI viewer dialog. Normally it's only enabled in plugin projects.\n - [Simplistic \"generify return type\"](https://gist.github.com/dkandalov/5992191) - attempt to pattern-match PSI tree\n - [No copy-paste](https://gist.github.com/dkandalov/5430282) - disables copy/paste actions\n - [Text munging actions](https://gist.github.com/dkandalov/34daca651fb3fbb9b33f) - simple actions on text (sort, unique, keep/delete lines)\n - [Wrap selection](https://gist.github.com/dkandalov/5129543) - micro-plugin to wrap long lines with separator\n - [Wrap selected text to column width](https://gist.github.com/dkandalov/5557393) - copy of this plugin https://github.com/abrookins/WrapToColumn\n - [Create .jar patch file for current change list](https://gist.github.com/dkandalov/5502872) - that's what it does\n - [Create .jar patch file for specified favorites list](https://gist.github.com/chanshuikay/9850327817fbedceba75) - similar to the above mini-plugin\n - [Remove getters/setters](https://gist.github.com/dkandalov/5476562) - removes all setters or getters in a class\n - [ISO DateTime / Epoch timestamp converter](https://gist.github.com/xhanin/4948901) - converts Epoch time to/from ISO format\n - [Make cursor move in circle](https://gist.github.com/dkandalov/11326385) - definitely not practical but gives an idea about threading\n - [Word Cloud](https://github.com/dkandalov/intellij-wordcloud) - shows world cloud for the selected item (file/package/folder)\n - [Project TreeMap View](https://github.com/dkandalov/project-treemap) - shows project structure (packages/classes) as treemap based on size of classes\n - [Method History](https://github.com/dkandalov/history-slider-plugin) - combines built-in method history based on selection and method history based on method name\n - [Evaluate selection as Groovy](https://gist.github.com/dkandalov/5024580) - that's exactly what it does\n - [Taskbar Icon Changer](https://gist.github.com/markusmo3/ee46e5fe81d4dacea7110134f4ca953f) - Changes the Windows Taskbar icon depending on the project name to provide a better overview when working with multiple projects\n - [Refocus Pinned Find Window](https://gist.github.com/fc1943s/411540e9e29a1296650bcaa8f9a27eec) - Shortcut to refocus the 'Find in Path' dialog with the Pin option enabled after selecting a result entry\n\n\n## Similar plugins\nThe idea of running code inside IntelliJ is not original. \nThere are/were similar plugins:\n - [Flora](http://plugins.intellij.net/plugin?id=17669) - a similar plugin from JetBrains Hackathon\n - [IDE Scripting Console](https://youtrack.jetbrains.com/issue/IDEA-138252) - experimental feature bundled since IntelliJ 14.1\n - [Script Monkey](http://plugins.intellij.net/plugin?pr=idea\u0026pluginId=3674) (out-of-date)\n - [PMIP - Poor Mans IDE Plugin](http://plugins.intellij.net/plugin/?idea\u0026pluginId=4571) (no longer available)\n - [Remote Groovy Console](http://plugins.intellij.net/plugin/?id=5373) (out-of-date)\n - [Groovy Console Plugin](http://plugins.intellij.net/plugin?pr=idea\u0026pluginId=4660) (out-of-date)\n - [HotPlugin](http://plugins.intellij.net/plugin?pr=idea\u0026pluginId=1020) (out-of-date)\n\n\n## Contributing\nPlease see [CONTRIBUTING.md](https://github.com/dkandalov/live-plugin/blob/master/CONTRIBUTING.md).\n","funding_links":["https://www.buymeacoffee.com/dmitrykandalov"],"categories":["[Other](#other)"],"sub_categories":["Third Party"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkandalov%2Flive-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkandalov%2Flive-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkandalov%2Flive-plugin/lists"}