Kotlin Notebook
Kotlin Notebook brings the versatility of notebooks to IntelliJ IDEA.
Notebooks are interactive editors that integrate code, graphics, and text in a single environment. When using a notebook, you can run code cells and immediately see the output, gaining real-time code insights.
Kotlin Notebook is a plugin that allows you to create and edit notebooks smoothly within the IntelliJ IDEA ecosystem while coding with Kotlin.
Kotlin Notebook provides you with a rich set of tools to tackle tasks like:
Data analytics and visualization: you can intuitively retrieve, transform, plot, and model your data while getting outputs of your operations as you code.
Prototyping: you can run code in small chunks and see the results in real time. This hands-on environment enables rapid experimentation and iteration.
Explore and test APIs: Kotlin Notebook offers the ability to call APIs within cells and interact with external services.
Code documentation: you can include inline comments within code cells and text annotations within Markdown cells to provide further context, explanations, instructions, and more.
Additionally, you can effortlessly share your work across Kotlin Notebook, Datalore, and Kotlin-Jupyter Notebook without issues. This compatibility is possible because Kotlin Notebook is based on our Kotlin Kernel, ensuring seamless integration among our different Kotlin notebook solutions.
Explore the sections below to learn about the Kotlin Notebook's usage and key features!
note
To discover what you can achieve with Kotlin Notebook and its use cases, read the Kotlin Notebook overview in the Kotlin docs.
Install the Kotlin Notebook plugin by downloading it from JetBrains Marketplace. Ensure you use the latest version of both the plugin and IntelliJ IDEA Ultimate.
Alternatively, access the Kotlin Notebook plugin from Settings | Plugins | Marketplace within IntelliJ IDEA Ultimate.
![Install the Kotlin Notebook plugin Install the Kotlin Notebook plugin](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-plugin-install.png)
Once you have installed the plugin in IntelliJ IDEA Ultimate, select File | New | Kotlin Notebook to create a new notebook.
Alternatively, right-click on the directory you want to locate your notebook and select New | Kotlin Notebook.
![Create new Kotlin Notebook Create new Kotlin Notebook](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-create-notebook.png)
A file with a .ipynb
extension is created.
Starting from IntelliJ IDEA 2024.1.1, you can also create a Kotlin Notebook as a scratch (temporary) file by selecting File | New | Scratch File. Scratch files allow for testing small pieces of code without creating a new project or modifying an existing one.
At the top of your Kotlin Notebook, you can find the notebook toolbar. This toolbar contains buttons for quick cell actions that allow you to dynamically run or modify your code and see the output immediately.
![Kotlin Notebook toolbar Kotlin Notebook toolbar](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-bar.png)
The main actions you can perform from the toolbar are:
Add code cell below
Cut selection
Copy selection
Paste selection
Move cell up
Move cell down
Run cell and select below
Interrupt kernel
Restart kernel
Run all cells
Clear outputs
Delete cell
Code
Select type of cell
Create gist
See Kotlin Notebook settings
When working with notebooks, each cell contributes to the whole state of the notebook, but only after you run the cells. The order of cells in the notebook itself doesn't matter, but the order of running the cells does.
For example, when using a library, although you can run any cell at any time, you need to run the cell that imports the library before running the cells that call the library.
![Kotlin Notebook cells Kotlin Notebook cells](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-cells.png)
Unlike traditional programming, notebooks allow you to declare multiple variables with the same name within different cells. However, each new declaration of a variable with the same name overrides the previous ones. Only the most recent declaration you run is valid in subsequent cells.
![Kotlin Notebook variables Kotlin Notebook variables](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-variables.png)
Usually, notebooks have code running under the hood, which may cause unexpected behavior when joining cells. This behavior is because if one of the joined cells contains code that modifies the environment, the changes might not be immediately reflected in the following cell.
Notebooks may have limitations on certain language constructs. Generally, only valid function-level operations are allowed, like working inside a function body.
note
For more details about working with notebooks and using the toolbar, see Best practices.
You can access the Kotlin Notebook API directly within cells. The Kotlin Notebook API provides functionality to customize and configure your notebook behavior, such as handling outputs, retrieving information from previously executed code snippets, seamless integration with libraries, and more.
For example, notebook
is an entry point for the Kotlin Notebook API. You can use notebook
with certain methods to retrieve notebook insights like the executed code cells or declared variables.
![Kotlin Notebook API Kotlin Notebook API](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-api.png)
note
For more information about what you can do with the Kotlin Notebook API, see the supported integration features on GitHub.
For sample codes accessing the Kotlin Notebook API, see the libraries API guide notebook.
You can easily add dynamic dependencies to your notebook from a remote Maven repository or local ones (local JARs). To add dependencies, you have two options: annotations or Gradle-like syntax.
There are two annotations to manage dependencies in your Kotlin Notebook:
@file:DependsOn():
In this annotation, you need to specify the coordinates of the dependency. This annotation adds artifacts (like JAR files) to the notebook's classpath. It supports absolute and relative paths to class directories or JARs, as well as Ivy and Maven artifacts:@file:DependsOn(“io.ktor:ktor-client-core-jvm:$ktorVersion“)
@file:Repository():
In this annotation, you need to specify the absolute path of the dependency. This annotation adds a directory or an Ivy or Maven repository to the notebook environment. To specify a Maven local repository, use@file:Repository("*mavenLocal")
.
You can load any library from the Maven repository using Gradle-like syntax in any cell, specifying repositories, locations, and so on:
USE {
repositories {
maven {
url = "https://my.secret.repo/maven/"
credentials {
username = USER
password = TOKEN
}
}
}
dependencies {
val ktorVersion = "2.0.3"
implementation("my.secret:artifact:1.0-beta")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-apache:$ktorVersion")
}
}
note
While you can utilize Gradle-like syntax, Gradle is not running under the hood, and Gradle metadata is not resolved. Therefore, advanced dependency configurations are not available. For example, top-level Multiplatform dependencies are not supported. In these cases, you need to use the
-jvm
variant manually. For more information, see Dependencies resolving on GitHub.
Kotlin Notebook provides special commands, starting with the %
character, that interact with the notebook on a per-line basis. These commands, known as line magics, allow you to import libraries, configure output settings, and perform more operations.
note
To check the list of line magics supported in Kotlin Notebook, see Line magics on GitHub.
Kotlin Notebook comes with a set of integrated libraries to perform various tasks, from deep learning to HTTP networking. You can import these integrated libraries just by running the %use
line magic before the library's name.
Along with the %use
keyword, you can specify a particular library version or include several libraries using a single %use
statement.
![Kotlin Notebook libraries Kotlin Notebook libraries](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-libraries.png)
You can add and use libraries that are not yet integrated into Kotlin Notebook. There are two ways to integrate a new library: creating a JSON library descriptor or using the Kotlin Notebook API.
To support a new library and make it available via the %use
line magic, you need to create a library descriptor. The library descriptor is a .json
file defining the most frequent library features, such as properties, renderers, and initial imports:
This example shows the usage of a custom renderer defined within the library descriptor:
USE {
render<Int> { "[$it]" }
}
note
For more details, see Adding new libraries on GitHub and examples of Kotlin libraries descriptors.
To add a new library using the Kotlin Notebook API, you need to define an integration class within your library and ensure the integration class name is in the current notebook classpath.
note
For examples of integration classes, see the Kandy library integration class and the DataFrame library integration class.
Once you have defined the integration class, you can leverage all available integration features provided by the Kotlin Notebook API. These features facilitate seamless interaction between your library and the Kotlin Notebook environment.
You can use the available integration features directly from the notebook cells employing the USE {}
block along with the feature method. Here's an example with the import ()
method:
USE {
import("my.awesome.Clazz")
}
note
For more details about adding new libraries with the Kotlin Notebook API, see the libraries API guide notebook.
Use REPL commands to explore your notebook environment, understand the classpath, and inspect the values of variables during execution.
![Kotlin Notebook REPL commands Kotlin Notebook REPL commands](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-repl-commands.png)
Kotlin Notebook supports the following REPL commands:
| Displays help information with details of the notebook version, line magics, and supported libraries. |
---|---|
| Displays the current classpath of your notebook environment, showing a list of locations where the notebook searches for libraries and resources. |
| Displays information about the declared variables and their values. |
By default, Kotlin Notebook displays return values in text form. However, you can enrich the output by rendering graphics, HTML, or other MIME-encoded data format.
One approach is to send MIME-encoded results to the client using the MIME
helper function. Another approach is to use the HTML
helper function, which provides a simpler way to display HTML content directly. See samples of these functions in our Kotlin-Jupyter repository on GitHub.
Beyond these functions, Kotlin Notebook supports various features and mechanisms for rendering values:
Renderers: Transform values into other representations. Renderers are controlled via the
RenderersProcessor
method, and you can access it with thenotebook
API entry point.DisplayResult
andRenderable:
Objects implementingDisplayResult
andRenderable
interfaces are rendered to output JSON.Text rendering: Render objects to strings using text renderers. Text renderers are controlled via the
TextRenderersProcessor
method, and you can access it with thenotebook
API entry point.Throwables rendering: Throwable renderers behave as regular renderers but handle exceptions and errors generated during cell execution.
note
To explore more about rendering in Kotlin Notebook, see Common rendering semantics on GitHub.
Effortlessly retrieve data with simple drag-and-drop functionality, bringing the data from your project directory to the notebook cells.
In a matter of clicks, load CSV, XLS, and JSON files and have them in a data-frame-like structure, ready to be processed. Check the video below to see the drag-and-drop functionality in action.
Just as easy as loading data, you can intuitively export both data and graphics from the notebook by clicking on the exporting options in the cells.
![Kotlin Notebook exporting Kotlin Notebook exporting](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-export.png)
When something doesn't go as expected in your code, Kotlin Notebook displays error messages and a stack trace in the output cells, providing insights for debugging.
![Kotlin Notebook analyse errors Kotlin Notebook analyse errors](https://resources.jetbrains.com/help/img/idea/2024.3/kotlin-notebook-analyse-errors.png)
Kotlin Notebook is a variant of Jupyter Notebooks and share a similar internal structure.
When you open a notebook and run the first cell, the notebook creates a session under the hood. This session communicates with a kernel, which keeps track of the notebook's runtime state throughout your work.
Working with a notebook has some implications compared to working with regular Kotlin files:
When the session is started, the project dependencies that you selected as notebook dependencies are compiled and added to the kernel's classpath. For this reason, if you make changes to your project code, these changes will be available within the notebook only after you restart the kernel.
Restarting the kernel is useful when the kernel becomes unresponsive or if you make significant changes to the environment. This action terminates the current running environment, clearing all the declared variables, functions, and objects.
The state of a notebook combines aspects of runtime and compile time. For this reason, restarting the kernel clears all previously evaluated variables from the notebook's memory. This can result in unresolved symbol errors if one cell depends on the output of another cell.
Interrupting the kernel only pauses the current running cell without terminating the entire environment. This action is useful when you need to pause and resume the execution, for example, when a cell is taking too long to run.
The dependencies you add in cells become available only after you run those cells. This means that if you add a dependency and try to use that dependency in the same cell, the symbols from the dependency are marked as unresolved until you run the cell for the first time.
You can run the cells independently in any order, regardless of their position in the notebook. The notebook's runtime state depends on the order of execution, not the cell's position in the notebook.
The cells you run are marked with a number indicating the execution order. On the other hand, those cells that you haven't run are marked with a * symbol. If you restart the kernel and click the Run All button, all the code cells run sequentially. Each cell is marked with a number matching their order of execution. When you run all the cells, the execution starts from the top to the button, so the order naturally aligns with the cells' position in the notebook.
We suggest clicking the Run All button after restarting the kernel. By running all cells, the cells are executed in the correct order, recreating the necessary variables and functions within the memory.
Thanks for your feedback!