{"id":65391,"date":"2026-07-31T12:42:36","date_gmt":"2026-07-31T16:42:36","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=65391"},"modified":"2026-07-31T12:42:36","modified_gmt":"2026-07-31T16:42:36","slug":"jetbrains-kotlinllm-smart-macros","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/jetbrains-kotlinllm-smart-macros\/","title":{"rendered":"JetBrains Open-Sources KotlinLLM: Smart Macros Generate Runtime Kotlin"},"content":{"rendered":"<p><a href=\"https:\/\/www.jetbrains.com\/research\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">JetBrains Research<\/a> has open-sourced <strong><a href=\"https:\/\/github.com\/JetBrains\/kotlinllm\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">KotlinLLM<\/a><\/strong>, an IntelliJ IDEA plugin that introduces a novel language feature called <strong>Smart macros<\/strong> for Kotlin\/JVM projects. Unlike typical LLM integrations that call a model on every request, KotlinLLM generates plain Kotlin <a href=\"https:\/\/overcentral.com\/en\/accenture-confirms-breach-hacker-sells-35gb-source-code\/\" title=\"Accenture Confirms Breach, Hacker Sells 35GB Source Code\" data-iacss-internal=\"1\">source code<\/a> at runtime and then stops needing the model for covered scenarios. The result is a development tool that produces deployable code with no ongoing inference costs, no added latency in production, and a workflow that stays inside the familiar IDE.<\/p>\n<h2>What Are Smart Macros? KotlinLLM\u2019s Two Core Functions<\/h2>\n<p>The plugin adds two primary macros to the Kotlin language: <code>asLlm()<\/code>codecodecodecodecode and <code>mockLlm()<\/code>codecodecodecodecode. A Smart macro is a regular Kotlin function call whose body is generated Kotlin code. The public API is deliberately small to keep the surface area manageable and the generated code reviewable.<\/p>\n<p><strong>What is KotlinLLM?<\/strong> KotlinLLM is an experimental IntelliJ IDEA plugin from JetBrains Research that uses an LLM to generate Kotlin source code on demand. It operates through a runtime evolution loop: when a scenario is not yet covered, the plugin captures runtime values, sends them to an OpenAI model, compiles the returned code, and redefines the loaded class in the live JVM. Once a scenario is covered, subsequent invocations use the generated Kotlin directly \u2014 no model call, no added latency, no cost.<\/p>\n<p><code>asLlm()<\/code>codecodecodecodecode converts an input of type <code>F<\/code>codecodecodecodecode into a typed value <code>T<\/code>codecodecodecodecode, such as a data class, enum, list, or primitive. It takes an optional hint string to guide the LLM. For example, developers can convert a raw API response string into a strongly typed list of issue objects. <code>mockLlm()<\/code>codecodecodecodecode generates a stateful implementation of an interface <code>T<\/code>codecodecodecodecode, whose behavior depends on which methods are called on it at runtime. Both macros produce Kotlin source files that live in the project and can be committed to version control, reviewed, and tested like any hand-written code.<\/p>\n<p>The plugin scans the project for these macro calls during launch, generates bootstrap and provider files, and prepares the runtime redefinition machinery. The generated code is ordinary Kotlin \u2014 no dependency on the LLM, no special runtime library beyond the plugin\u2019s own scaffolding.<\/p>\n<h2>The Full Runtime Evolution Loop: How KotlinLLM Generates and Hardens Code<\/h2>\n<p>KotlinLLM\u2019s core innovation is its nine-step runtime loop that transforms an uncovered scenario into a permanently covered one. The loop depends on JVM class redefinition through the Java Debug Interface (JDI), which is why the plugin targets Kotlin\/JVM specifically. Here is how it works in detail:<\/p>\n<ol>\n<li><strong>Scan phase:<\/strong> When a project launches through the KotlinLLM run configuration, the plugin scans all source files for <code>asLlm<\/code>codecodecodecodecode and <code>mockLlm<\/code>codecodecodecodecode calls.<\/li>\n<li><strong>File generation:<\/strong> It creates or updates bootstrap, provider, parser, and mock files that wire the macros to the runtime loop.<\/li>\n<li><strong>JDI launch:<\/strong> The plugin launches the original run configuration under the Java Debug Interface, giving it deep control over the executing JVM.<\/li>\n<li><strong>Breakpoint registration:<\/strong> It registers breakpoints on the generated <em>regenerate hooks<\/em> \u2014 code paths that signal an uncovered scenario.<\/li>\n<li><strong>Hook hit:<\/strong> When a scenario reaches a generate hook for the first time, execution suspends at the breakpoint.<\/li>\n<li><strong>Value capture:<\/strong> The plugin captures runtime values, types, and the input data from the suspended stack frame.<\/li>\n<li><strong>LLM submission:<\/strong> An LLM agent reads the captured values, the input data, and the hint, then submits a code update for the macro\u2019s body.<\/li>\n<li><strong>Compile and redefine:<\/strong> The update is compiled and the loaded class is redefined in the running JVM \u2014 no restart required.<\/li>\n<li><strong>Retry:<\/strong> The original application call is retried against the new implementation, which now contains the generated Kotlin for that scenario.<\/li>\n<\/ol>\n<p>Once a scenario is covered, the generated code path is taken directly on all subsequent invocations. The breakpoint remains registered, but it is never hit because the hook condition is satisfied. This design ensures that the LLM is invoked only when genuinely new behavior is required.<\/p>\n<h2>How KotlinLLM Differs from Traditional LLM Integration<\/h2>\n<p>Typical LLM-powered code generation operates at design time or on every API call. For instance, a developer might prompt an LLM to write a parser, then manually copy the output into the source code. Alternatively, some systems call an LLM at runtime for every request, incurring latency and cost proportional to traffic. KotlinLLM takes a third path: it treats the LLM as an <em>evolution engine<\/em> that writes code once and then steps aside.<\/p>\n<p>The generated Kotlin source becomes a permanent part of the project. It can be edited by hand, reviewed in pull requests, and compiled into the final artifact with zero runtime dependency on the LLM. The plugin does not ship <a href=\"https:\/\/overcentral.com\/en\/polymarket-fails-to-predict-its-own-3m-security-breach\/\" title=\"Polymarket Fails to Predict Its Own $3M Security Breach\" data-iacss-internal=\"1\">its own<\/a> model; it uses an OpenAI API key stored in the project\u2019s <code>.kotlinllm<\/code>codecodecodecodecode file. This separation of concerns means the output is as portable and predictable as any other Kotlin code.<\/p>\n<p>Another key distinction: the runtime loop is transparent to the developer. The plugin logs its actions to the IntelliJ console, but the application continues normally after each evolution step. The developer can observe the generated code in the project tree and even commit it before the application finishes running.<\/p>\n<h2>Reported Results: 24\/24 Scenarios and Minimal Overhead<\/h2>\n<p>JetBrains Research evaluated KotlinLLM on an adapted Spring Petclinic Kotlin project containing 18 <code>asLlm<\/code>codecodecodecodecode call sites. The plugin completed all 24 application scenarios after Smart macro evolution. The hot-reload success rate was 100%, and the compilation and class redefinition overhead added roughly 1% of total runtime \u2014 negligible in a development workflow.<\/p>\n<p>A second evaluation used a synthetic \u201c<a href=\"https:\/\/overcentral.com\/en\/github-api-ghost-accounts-recon\/\" title=\"Ghost Accounts Abuse GitHub API in Mass Recon Campaign\" data-iacss-internal=\"1\">GitHub<\/a> Beginner Issue Radar\u201d that parsed real issue data across 20 repositories and more than 30,000 issues. The plugin achieved approximately 0.89 recall on ground-truth beginner labels, meaning it successfully extracted the correct labels from the unstructured text nine times out of ten. These numbers reflect a research prototype, but the pattern is clear: for sufficiently well-scoped tasks, the generated code is both functional and efficient.<\/p>\n<h2>Setup Requirements for KotlinLLM<\/h2>\n<p>To use KotlinLLM, you need <strong>IntelliJ IDEA 2025.2.x<\/strong>, <strong>JDK 21<\/strong>, and an OpenAI API key. The key is stored in the target project\u2019s <code>.kotlinllm<\/code>codecodecodecodecode file, configured via <code>Tools &gt; KotlinLLM Settings<\/code>codecodecodecodecode. The plugin is published under the Apache License 2.0 and is available from the JetBrains Research GitHub repository.<\/p>\n<p>The repository includes runnable examples, a thesis write-up that details the technical design, and a recording of the KotlinConf 2026 talk. Developers can quickly clone the repo and experiment with the macros in a local Kotlin\/JVM project. The setup process is straightforward: install the plugin, create a project with an <code>.kotlinllm<\/code>codecodecodecodecode file containing the API key, and write <code>asLlm<\/code>codecodecodecodecode or <code>mockLlm<\/code>codecodecodecodecode calls in the code.<\/p>\n<h2>Is KotlinLLM Ready for Production?<\/h2>\n<p>JetBrains explicitly labels KotlinLLM a <strong>research prototype<\/strong> and an experimental IntelliJ IDEA plugin. It is not intended as a production runtime \u2014 at least not yet. The plugin itself is experimental, but the <strong>output is deployable<\/strong>. Once behavior has been generated, the target project can compile and run that behavior without any further LLM requests for the same scenario. The generated code is reviewed, committed, and shipped as ordinary Kotlin, with no model dependency attached to the artifact.<\/p>\n<p>That distinction matters. A regulated enterprise can treat the generated sources as reviewable code \u2014 exactly how KotlinLLM stores them. The generated files are plain text, structured as Kotlin classes and functions, and can be subjected to all standard quality checks. The plugin\u2019s risk is confined to the development environment, not the deployed application.<\/p>\n<p>For companies, the best fit today is R&amp;D groups, platform teams at mid-size to large Kotlin\/JVM entities, and startups with tolerance for prototype tooling. Industries with heavy JVM\/Kotlin estates \u2014 fintech, banking, developer tooling, e-commerce, logistics \u2014 stand to benefit most, especially teams that parse messy third-party API payloads or need evolving test doubles.<\/p>\n<h2>Industries and Use Cases Where KotlinLLM Fits<\/h2>\n<p>KotlinLLM addresses a specific pain point: converting unstructured or semi-structured data into typed Kotlin values without writing boilerplate parsers by hand. It also handles the creation of stateful test doubles that mimic external services. The common thread is scenarios where the shape of the data drifts over time or where an interface\u2019s behavior is not fully known in advance.<\/p>\n<ul>\n<li><strong>Fintech and banking:<\/strong> Many financial institutions run Kotlin on the JVM for their back-end services. Parsing regulatory feed messages, normalizing credit bureau responses, and adapting to upstream schema changes all align with KotlinLLM\u2019s strengths. The generated code can be reviewed for compliance and committed.<\/li>\n<li><strong>Developer tooling:<\/strong> IDEs, CI\/CD pipelines, and code analysis tools often need to parse output from other systems. KotlinLLM can generate parsers for log formats, build tool outputs, or API error bodies on the fly.<\/li>\n<li><strong>E-commerce and logistics:<\/strong> Product feeds, tracking updates, and inventory reports arrive in varied formats. A Smart macro can normalize these into typed Kotlin models without manual pattern matching.<\/li>\n<li><strong>API integration:<\/strong> When integrating with third-party REST APIs that lack strict schemas, <code>asLlm<\/code>codecodecodecodecode can turn raw JSON strings into typed objects based on a hint, reducing boilerplate and making the integration self-documenting.<\/li>\n<\/ul>\n<p>For regulated enterprises, the key is that the generated code is committed and reviewed before production deployment. The plugin itself never touches the runtime environment. This separation allows teams to experiment with LLM-assisted code generation while maintaining audit trails and code quality processes.<\/p>\n<h2>The Strategic Significance: LLMs as Code-Generation Engines, Not Runtime Dependencies<\/h2>\n<p>KotlinLLM represents a broader shift in how developers think about LLMs in the software lifecycle. Rather than embedding a model call into every request or using an LLM only for one-off code snippets, this approach treats the model as a development-stage oracle that writes code and then recedes. The cost per invocation drops to zero for all covered scenarios, and the latency is eliminated entirely. The result is a tool that feels more like an advanced autocomplete than a black-box API.<\/p>\n<p>The open-source release under Apache 2.0 also lowers the barrier for experimentation. Other teams can fork the plugin, modify the runtime loop, or adapt it to different LLM providers. The thesis write-up included in the repository provides the theoretical underpinning, making it easier for researchers and engineers to understand the design decisions and explore improvements.<\/p>\n<p>That said, KotlinLLM is not a general-purpose code generator. It is narrowly scoped to generating Kotlin\/JVM code from typed macros. It will not replace hand-coded business logic, and the quality of the generated code depends heavily on the quality of the hint and the underlying model. The Petclinic evaluation achieved a 100% scenario completion rate, but real-world conditions may vary. The plugin is best used for well-defined, repetitive tasks where the cost of incorrectly generated code is low \u2014 such as parsing and mocking \u2014 rather than critical path logic.<\/p>\n<p>As JetBrains continues to refine the plugin, we can expect tighter integration with the Kotlin compiler, support for more LLM providers, and possibly a mode that runs entirely off-line using local models. The concept of \u201cgenerate once, run forever\u201d has clear appeal in a world where LLM inference costs and latencies are still significant. KotlinLLM shows a path forward: let the model do the hard thinking once, then ship the result as plain code that everyone can trust.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JetBrains Research has open-sourced KotlinLLM, an IntelliJ IDEA plugin that introduces a novel language feature called Smart macros for Kotlin\/JVM projects. Unlike typical LLM integrations that call a model on every request, KotlinLLM generates plain Kotlin source code at runtime and then stops needing the model for covered scenarios. The result is a development tool [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":83619,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/65391.png","fifu_image_alt":"JetBrains Open-Sources KotlinLLM: Smart Macros Generate Runtime Kotlin","footnotes":""},"categories":[349],"tags":[],"class_list":["post-65391","post","type-post","status-publish","format-standard","has-post-thumbnail","category-articles"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/65391.png","fifu_image_alt":"JetBrains Open-Sources KotlinLLM: Smart Macros Generate Runtime Kotlin","fifu_redirection_url":"https:\/\/www.neowin.net\/news\/jetbrains-open-sources-mellum-its-specialized-ai-model-for-code-completion\/","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/65391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=65391"}],"version-history":[{"count":0,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/65391\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/83619"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=65391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=65391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=65391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}