Skip to content

Commit f9ca11c

Browse files
committed
Auto CLAUDE.md
1 parent ef30da8 commit f9ca11c

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Build, Test, Run
6+
7+
- `mvn clean package` — full build; produces the shaded kernel jar and the kernelspec zip under `jjava-distro/target/`.
8+
- `mvn clean verify` — what CI runs on Linux/macOS. Adds Failsafe integration tests (the `*IT.java` cases in `jjava-distro`, which spin up `eclipse-temurin` containers via Testcontainers). Testcontainers does not work on Windows; CI uses `mvn clean test` there.
9+
- `mvn test -pl jjava-kernel -am` — single-module unit tests (with required upstream modules built).
10+
- `mvn -pl jjava-kernel test -Dtest=JavaKernelExtensionsLifecycleTest` — run a single test class.
11+
- Surefire in `jjava-kernel` and `jjava-distro` is configured with `--add-opens jdk.jshell/jdk.jshell=ALL-UNNAMED` — required for JShell reflection. Anything that exercises `JavaKernel`/`CodeEvaluator` directly needs the same flag.
12+
- Local install of the freshly built kernel into Jupyter: see `DEV-GUIDE.md` (`unzip` the kernelspec zip, then `jupyter kernelspec install ... --name=java --user`).
13+
14+
Minimum toolchain: JDK 11 (`maven.compiler.release=11`). CI matrix builds against 11, 17, 21, 25.
15+
16+
## Module Layout and Dependency Graph
17+
18+
This is a multi-module Maven project (`groupId: org.dflib.jjava`). Each module has a distinct role — do not collapse them.
19+
20+
```
21+
jjava-jupyter ← generic, language-agnostic Jupyter kernel framework
22+
23+
jjava-kernel ← Java-specific kernel (uses JShell), built on jjava-jupyter
24+
25+
jjava-maven ← Maven dependency resolution magics, built on jjava-kernel
26+
27+
jjava-distro ← Fat/shaded jar combining kernel + maven + magics. THE deliverable.
28+
29+
jjava-launcher ← Tiny no-dependency jar; spawns the child java process for jjava-distro.
30+
```
31+
32+
- **`jjava-jupyter`** — Reusable JVM Jupyter library: the ZMQ wire protocol (jeromq), message types and Gson adapters, channel loops (`shell`, `iopub`, `stdin`, `heartbeat`, `control`), display/rendering, magics infrastructure (`MagicsRegistry`, `MagicsResolver`, `MagicTranspiler`), comm, history, and `BaseKernel` — the abstract superclass that any language-specific kernel extends. Published to Maven Central as a library for building other JVM kernels.
33+
- **`jjava-kernel`**`JavaKernel extends BaseKernel`. Owns the `JShell` instance and `CodeEvaluator` (with custom `JJavaExecutionControl` and `JJavaLoaderDelegate`). Ships built-in magics under `org.dflib.jjava.kernel.magics`: `%load`, `%classpath`, `%time`, `%jars` (deprecated).
34+
- **`jjava-maven`** — Maven dependency resolution, isolated so the core kernel stays slim. Uses Maveniverse Mima for resolution. Ships `%maven`, `%mavenRepo`, `%loadFromPOM` (line + cell), `%addMavenDependency` (deprecated).
35+
- **`jjava-distro`** — The actual runnable kernel jar. Main class: `org.dflib.jjava.distro.JJava`. Wires all magics into `JavaKernel.builder()`, reads `JJAVA_*` env vars (see `Env.java`), parses the Jupyter connection file, and runs the message loop. Uses `maven-shade-plugin` to relocate every 3rd-party package (gson, jeromq, slf4j, maven, mima, etc.) under `org.dflib.jjava.shaded.*` — keep this in mind when reading stack traces from a built kernel. SLF4J is bound to `slf4j-jdk14` (JUL) inside the shaded jar.
36+
- **`jjava-launcher`** — Standalone jar with zero dependencies. Spawns a child `java` process running the distro jar, applying `--add-opens jdk.jshell/jdk.jshell=ALL-UNNAMED` and any `JJAVA_JVM_OPTS`. Its `package` phase also copies the launcher jar into `kernelspec/java/jjava-launcher.jar`. Uses `java.util.logging` directly rather than SLF4J because it must remain dependency-free.
37+
38+
`kernelspec/java/kernel.json` is the Jupyter kernel descriptor — its `argv` invokes `jjava-launcher.jar`, which in turn invokes `jjava.jar`. The shade output of `jjava-distro` and the `jjava-launcher` jar are both copied into the assembled `jjava-<version>-kernelspec.zip` (see `jjava-distro/assembly/zipped-kernel.xml`).
39+
40+
`pip/jjava/` and `pyproject.toml` package the kernelspec for PyPI distribution; version is injected from the git tag by the release workflow.
41+
42+
## Runtime Behavior to Keep in Mind
43+
44+
- **JShell-based execution.** All user code runs in a `JShell` instance owned by `JavaKernel`. `CodeEvaluator` orchestrates snippet evaluation, and `JJavaLoaderDelegate` participates in JShell's class loading. Adding to the classpath at runtime means calling `kernel.addToClasspath(...)`, which both extends JShell's classpath *and* triggers extension discovery from the new entries.
45+
- **Magic resolution happens before evaluation.** Cells are passed through `MagicTranspiler` / `MagicsResolver`. Line magics start with `%`, cell magics with `%%`. New magics are registered in `JJava.main()` via `.lineMagic(...)` / `.cellMagic(...)` on the `JavaKernel.Builder`.
46+
- **Extensions** are discovered via `ServiceLoader` for `org.dflib.jjava.jupyter.Extension`, scanning both the application classpath and any classpath added at runtime through magics. `JJAVA_LOAD_EXTENSIONS=false` disables this entirely. Extensions get an `install(BaseKernel)` callback on load and `uninstall` on shutdown.
47+
- **Environment variables** consumed by the kernel are centralized in `org.dflib.jjava.distro.Env`: `JJAVA_COMPILER_OPTS`, `JJAVA_TIMEOUT`, `JJAVA_CLASSPATH`, `JJAVA_STARTUP_SCRIPT`, `JJAVA_STARTUP_SCRIPTS_PATH`, `JJAVA_LOAD_EXTENSIONS`. `JJAVA_JVM_OPTS` is read by the launcher, not the kernel, and is *not* forwarded to the child process beyond being unpacked into the JVM command line.
48+
- **Logging.** Code in `jjava-jupyter`, `jjava-kernel`, `jjava-maven` uses SLF4J. The launcher and `JJava` main class use JUL directly (the launcher because it has no dependencies; `JJava.main` because it sets the JUL `SimpleFormatter.format` system property to mimic Jupyter's log style before the SLF4J→JUL bridge takes over). In the shaded distro jar, SLF4J is itself relocated to `org.dflib.jjava.shaded.org.slf4j` and routed to JUL via `slf4j-jdk14`.
49+
- **Integration tests** (`jjava-distro/src/test/java/.../*IT.java`) extend `ContainerizedKernelCase`, which mounts the locally-built `kernelspec/java` and `src/test/resources` into an `eclipse-temurin:<jdkVersion>` container and runs `jupyter` against the real kernel. These tests need a working Docker daemon and the kernel jars must already be packaged (Failsafe runs in the `verify` phase, after `package`).

0 commit comments

Comments
 (0)