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 that produces deployable code with no ongoing inference costs, no added latency in production, and a workflow that stays inside the familiar IDE.
What Are Smart Macros? KotlinLLM’s Two Core Functions
The plugin adds two primary macros to the Kotlin language: asLlm()codecodecodecodecode and mockLlm()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.
What is KotlinLLM? 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 — no model call, no added latency, no cost.
asLlm()codecodecodecodecode converts an input of type Fcodecodecodecodecode into a typed value Tcodecodecodecodecode, 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. mockLlm()codecodecodecodecode generates a stateful implementation of an interface Tcodecodecodecodecode, 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.
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 — no dependency on the LLM, no special runtime library beyond the plugin’s own scaffolding.
The Full Runtime Evolution Loop: How KotlinLLM Generates and Hardens Code
KotlinLLM’s 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:
- Scan phase: When a project launches through the KotlinLLM run configuration, the plugin scans all source files for
asLlmcodecodecodecodecode andmockLlmcodecodecodecodecode calls. - File generation: It creates or updates bootstrap, provider, parser, and mock files that wire the macros to the runtime loop.
- JDI launch: The plugin launches the original run configuration under the Java Debug Interface, giving it deep control over the executing JVM.
- Breakpoint registration: It registers breakpoints on the generated regenerate hooks — code paths that signal an uncovered scenario.
- Hook hit: When a scenario reaches a generate hook for the first time, execution suspends at the breakpoint.
- Value capture: The plugin captures runtime values, types, and the input data from the suspended stack frame.
- LLM submission: An LLM agent reads the captured values, the input data, and the hint, then submits a code update for the macro’s body.
- Compile and redefine: The update is compiled and the loaded class is redefined in the running JVM — no restart required.
- Retry: The original application call is retried against the new implementation, which now contains the generated Kotlin for that scenario.
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.
How KotlinLLM Differs from Traditional LLM Integration
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 evolution engine that writes code once and then steps aside.
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 its own model; it uses an OpenAI API key stored in the project’s .kotlinllmcodecodecodecodecode file. This separation of concerns means the output is as portable and predictable as any other Kotlin code.
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.
Reported Results: 24/24 Scenarios and Minimal Overhead
JetBrains Research evaluated KotlinLLM on an adapted Spring Petclinic Kotlin project containing 18 asLlmcodecodecodecodecode 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 — negligible in a development workflow.
A second evaluation used a synthetic “GitHub Beginner Issue Radar” 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.
Setup Requirements for KotlinLLM
To use KotlinLLM, you need IntelliJ IDEA 2025.2.x, JDK 21, and an OpenAI API key. The key is stored in the target project’s .kotlinllmcodecodecodecodecode file, configured via Tools > KotlinLLM Settingscodecodecodecodecode. The plugin is published under the Apache License 2.0 and is available from the JetBrains Research GitHub repository.
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 .kotlinllmcodecodecodecodecode file containing the API key, and write asLlmcodecodecodecodecode or mockLlmcodecodecodecodecode calls in the code.
Is KotlinLLM Ready for Production?
JetBrains explicitly labels KotlinLLM a research prototype and an experimental IntelliJ IDEA plugin. It is not intended as a production runtime — at least not yet. The plugin itself is experimental, but the output is deployable. 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.
That distinction matters. A regulated enterprise can treat the generated sources as reviewable code — 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’s risk is confined to the development environment, not the deployed application.
For companies, the best fit today is R&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 — fintech, banking, developer tooling, e-commerce, logistics — stand to benefit most, especially teams that parse messy third-party API payloads or need evolving test doubles.
Industries and Use Cases Where KotlinLLM Fits
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’s behavior is not fully known in advance.
- Fintech and banking: 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’s strengths. The generated code can be reviewed for compliance and committed.
- Developer tooling: 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.
- E-commerce and logistics: 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.
- API integration: When integrating with third-party REST APIs that lack strict schemas,
asLlmcodecodecodecodecode can turn raw JSON strings into typed objects based on a hint, reducing boilerplate and making the integration self-documenting.
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.
The Strategic Significance: LLMs as Code-Generation Engines, Not Runtime Dependencies
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.
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.
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 — such as parsing and mocking — rather than critical path logic.
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 “generate once, run forever” 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.