This file provides guidance to coding agents (Claude Code, and other tools that read AGENTS.md) when
working with code in this repository.
Kotlin DataFrame — a typesafe, immutable, hierarchical in-memory data-processing library for the JVM
(org.jetbrains.kotlinx:dataframe). Every DataFrame operation returns a new instance, reusing underlying
column storage where possible. Type-safe column access is provided through auto-generated extension properties
(on-the-fly in notebooks, via the compiler plugin / KSP in projects).
Gradle (Kotlin DSL), multi-module. Use the wrapper (./gradlew, or gradlew.bat on Windows). A JDK must be on
JAVA_HOME/PATH to launch the wrapper; the build daemon JDK is provisioned from gradle/gradle-daemon-jvm.properties
(version controlled by gradle-jdk in gradle/libs.versions.toml).
./gradlew build— full build; runs all tests and the ktlint check../gradlew <module>:test— test a single module (e.g../gradlew core:test); much faster during development../gradlew <module>:test --tests "org.jetbrains.kotlinx.dataframe.SomeTest"— run a single test class/method.- Add
-Pkotlin.dataframe.debug=truewhen validating changes. It enables extra, heavier correctness checks that are off in production. PR/CI builds run with this flag (build -Pkotlin.dataframe.debug=true), so match it locally. ./gradlew publishToMavenLocal -PskipKodex— publish locally for iteration.-PskipKodexskips KDoc preprocessing (see below); the result has "broken" KDocs, so it is for local dev only.
Module names for <module>: come from settings.gradle.kts (e.g. core, dataframe-csv, dataframe-jdbc,
dataframe-json, dataframe-arrow, dataframe-excel, dataframe-jupyter).
Dependency graph is rooted at core, with I/O and integration split into optional modules (see MODULES.md):
core— base module, no deps. DataFrame/DataColumn/DataRow types, the operations API (core/.../api/), aggregations, math, schema handling, codegen, and theimpl/internals. Also holds deprecated csv/tsv and HTML integrations that now live in dedicated modules.- I/O modules (each depends on
core):dataframe-csv,dataframe-json,dataframe-excel,dataframe-arrow,dataframe-jdbc. The rootdataframeartifact re-exports Arrow/Excel/JDBC/CSV/JSON asapi.dataframe-jdbcships built-inDbTypesupport for H2, MariaDB, MySQL, MS SQL Server, PostgreSQL, SQLite, and DuckDB (any other JDBC database works via a user-suppliedDbType); seedataframe-jdbc/AGENTS.md. - Integrations:
dataframe-jupyter,dataframe-geo→dataframe-geo-jupyter,dataframe-openapi→dataframe-openapi-generator. - Compiler/build tooling:
- The Kotlin DataFrame compiler plugin — the recommended way to get compile-time type-safe extension
properties — is NOT in this repo. It is developed in the Kotlin repository at
github.com/JetBrains/kotlin/tree/master/plugins/kotlin-dataframe. This repo'splugins/kotlin-dataframeis a disabled, out-of-date legacy copy (its tests are turned off; see issue #1290) — do not treat it as the live plugin. dataframe-compiler-plugin-core— a shaded subset of:corebundled inside that compiler plugin (and IntelliJ) to run compile-time interpreters of operations; it is not itself a compiler plugin. See itsAGENTS.md.plugins/*:plugins/symbol-processor(KSP codegen for@DataSchema),plugins/dataframe-gradle-plugin, and support plugins (expressions-converter,public-api-modifier,keywords-generator— the last is a separate build with its own Kotlin version).
- The Kotlin DataFrame compiler plugin — the recommended way to get compile-time type-safe extension
properties — is NOT in this repo. It is developed in the Kotlin repository at
- Build logic lives in
build-logic/andbuild-settings-logic/as convention plugins (e.g.conventions.plugins.dfbuild.*), not inline in the module build files.
Most modules ship their own AGENTS.md (core, dataframe-csv, dataframe-json, dataframe-excel,
dataframe-arrow, dataframe-jdbc, dataframe-geo, dataframe-compiler-plugin-core, samples,
docs/StardustDocs) with module-specific details. Read the relevant module's AGENTS.md before working in
it — it usually answers structure/pattern questions directly, so you can skip broad code exploration.
The public operations API is organized as one file per operation under
core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/ (e.g. filter.kt, groupBy.kt, join.kt). When adding
or changing an operation, find the sibling file for the closest existing operation and follow its structure.
Public KDocs use KoDEx notations ({@include [X]}, @set/@get/$, @sample, @ExcludeFromSources,
@ExportAsHtml). See KODEX_KDOC_PREPROCESSING.md and KDOC_GUIDELINES.md.
- KoDEx (an external KDoc-preprocessing tool, applied via the
kodexconvention plugin) expands the templated KDocs.core:processKDocsMainprocesses KDocs intogenerated-sources;changeJarTaskmakessources.jaruse those. - Don't hand-edit generated sources, and don't grep/crawl the tree. Every module built with KoDEx (
core,dataframe-csv,dataframe-excel,dataframe-geo,dataframe-jdbc) has a trackedgenerated-sources/copy, plus checked-in accessors under**/src/generated-dataschema-accessors/and generated HTML underdocs/StardustDocs/resources/. Ingenerated-sources/the implementation and public API are the same as the hand-writtensrc/main/kotlin/…— KoDEx only expands the KDoc and strips the doc-only fragments (declarations marked@ExcludeFromSources). So searching the tree (**/generated-sources/**,**/generated-dataschema-accessors/**) just doubles every hit and bloats context — do code work fromsrc/main/kotlin/…. The one reason to open a generated file is the KDoc: it is the fully-expanded documentation (all{@include …}/@set/@getresolved, URLs inlined). If you specifically need a symbol's final rendered docs, open that single generated file deliberately — don't explore. A CI bot regenerates and auto-commits all of these onmasterafter merge — you don't run/commit generation yourself. - For KDocs: never write from scratch — reuse/
@includean existing operation's KDoc and adapt it. Reusable KDoc fragments are written once asinternal/privateinterfaces andtypealias … = Nothingdeclarations and composed via@include; this pattern is used in every KoDEx module (the shared cross-module fragment library lives incore'sdocumentation/package).
Documentation snippets are runnable tests. The samples module and core's samplesTest/korro tasks execute
sample code, save outputs, and inject them into the WriterSide docs under docs/StardustDocs/. Migration of samples
into the :samples module is in progress; new documentation samples belong there.
-
Kotlin official style, enforced by ktlint (
ktlint_official, experimental rules enabled) via.editorconfig. IntelliJ Ktlint plugin recommended. In IDEA, delegate build actions to Gradle. -
4-space indent, LF, UTF-8, 120-column max line length (see
.editorconfigfor exact per-glob overrides). -
No wildcard imports — star-import thresholds are set to effectively infinite.
-
Class/function signatures with ≥4 parameters are forced multiline.
-
ktlint_standard_chain-method-continuation = disabled— deliberate. Group operations on one line when possible so a chain reads like a sentence; only start a new line when a new operation begins:df .update { x and y }.where { true }.with { it + 1 } .split { z }.by(",").into("z1", "z2") .groupBy { cols(a, b, c) }.aggregate { count { d } into "count" mean { d } into "mean" } .print()
- Base all PRs on
master; the current checked-out branch may be a feature branch (git statusat session start). - Bug fixes require a reproducing test; new public APIs require docs + tests.
- Public API is guarded by binary-compatibility-validator in every publishable module — when you change public
signatures, run the
apiDump/apiCheckGradle tasks and commit the module's updatedapi/*.apidump. - DB tests in
dataframe-jdbcare structured to run against either Dockerized or locally installed DBMS (io/local/per-database tests,io/db/type tests,io/h2/). Do not point tests at production databases.