diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53d08204098..61ee8f2e57e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -126,9 +126,11 @@ Requires Java 21 (see [Prerequisites](#prerequisites)). From `packages/kilo-jetb ```bash ./gradlew typecheck # Compile-check all Kotlin sources ./gradlew test # Run all tests (backend + frontend) -./gradlew runIde # Launch sandboxed IntelliJ with the plugin +./gradlew --no-configuration-cache runIdeSplitMode # Launch local split-mode sandbox and prepare the CLI ``` +Use `./gradlew runIde` only for a monolithic sandbox; prepare the CLI first with `bun run build --prepare-cli`. + Or via the root turbo filter to run only JetBrains checks from the repo root: ```bash diff --git a/packages/kilo-docs/pages/contributing/architecture/jetbrains-plugin.md b/packages/kilo-docs/pages/contributing/architecture/jetbrains-plugin.md index d54224b8f8a..bbfa42efc4d 100644 --- a/packages/kilo-docs/pages/contributing/architecture/jetbrains-plugin.md +++ b/packages/kilo-docs/pages/contributing/architecture/jetbrains-plugin.md @@ -124,7 +124,7 @@ Split mode changes path and UI assumptions: ## Development checks -JetBrains Kotlin toolchain is Java 21. Check `java -version` before Gradle verification. +JetBrains Kotlin toolchain is Java 21. Gradle commands report missing or incompatible Java clearly; check Java only when diagnosing that failure mode. | Check | Command from `packages/kilo-jetbrains/` | |---|---| @@ -132,9 +132,9 @@ JetBrains Kotlin toolchain is Java 21. Check `java -version` before Gradle verif | Tests | `./gradlew test` | | Full plugin build | `bun run build` | | Gradle plugin assembly with prepared CLI binaries | `./gradlew buildPlugin` | -| Sandbox IDE | `./gradlew runIde` | -| Split backend sandbox | `./gradlew runIdeBackend` | -| Split-mode run configs | `./gradlew generateSplitModeRunConfigurations` | +| Split-mode sandbox | `./gradlew --no-configuration-cache runIdeSplitMode` | +| Split backend sandbox | `./gradlew --no-configuration-cache runIdeBackend` | +| Monolithic sandbox IDE | `./gradlew runIde` after `bun run build --prepare-cli` | Run `Plugin DevKit | Code | Frontend and Backend API Usage` inspection when moving code across split boundary. diff --git a/packages/kilo-jetbrains/.run/Run IDE (Backend).run.xml b/packages/kilo-jetbrains/.run/Run IDE (Backend).run.xml index 84c1fe34e03..cfa3d9997d4 100644 --- a/packages/kilo-jetbrains/.run/Run IDE (Backend).run.xml +++ b/packages/kilo-jetbrains/.run/Run IDE (Backend).run.xml @@ -5,7 +5,7 @@ diff --git a/packages/kilo-jetbrains/.run/Run IDE (Frontend).run.xml b/packages/kilo-jetbrains/.run/Run IDE (Frontend).run.xml index 9613fd9791f..337d1e72f31 100644 --- a/packages/kilo-jetbrains/.run/Run IDE (Frontend).run.xml +++ b/packages/kilo-jetbrains/.run/Run IDE (Frontend).run.xml @@ -5,7 +5,7 @@ diff --git a/packages/kilo-jetbrains/.run/runIdeSplitMode.run.xml b/packages/kilo-jetbrains/.run/runIdeSplitMode.run.xml index 3fd81ac0533..58cae943e2e 100644 --- a/packages/kilo-jetbrains/.run/runIdeSplitMode.run.xml +++ b/packages/kilo-jetbrains/.run/runIdeSplitMode.run.xml @@ -1,7 +1,29 @@ - - - + + + + + + + + true + true + false + false + false + false + false diff --git a/packages/kilo-jetbrains/AGENTS.md b/packages/kilo-jetbrains/AGENTS.md index fb38dd51ad6..57e27724e28 100644 --- a/packages/kilo-jetbrains/AGENTS.md +++ b/packages/kilo-jetbrains/AGENTS.md @@ -171,8 +171,8 @@ For blocking I/O in coroutines, move the dispatcher switch inside the callee usi ### Dev Storage Isolation -- In development (`runIdeBackend` / `runIde`), the Gradle property `kilo.dev.storage.isolated=true` makes the backend set `XDG_DATA_HOME`, `XDG_CONFIG_HOME`, `XDG_STATE_HOME`, and `XDG_CACHE_HOME` to `/.kilo-dev/{data,config,state,cache}` before spawning the CLI. The worktree root comes from the `kilo.dev.worktree.root` JVM system property (auto-set by Gradle from the project directory). -- The checked-in `Run IDE (Backend)` run configuration enables isolation by default (`-Pkilo.dev.storage.isolated=true`). Developers can disable it by passing `-Pkilo.dev.storage.isolated=false`. +- In development (`runIdeSplitMode`, `runIdeBackend`, `runIdeFrontend`, or `runIde`), the Gradle property `kilo.dev.storage.isolated=true` makes the backend set `XDG_DATA_HOME`, `XDG_CONFIG_HOME`, `XDG_STATE_HOME`, and `XDG_CACHE_HOME` to `/.kilo-dev/{data,config,state,cache}` before spawning the CLI. The worktree root comes from the `kilo.dev.worktree.root` JVM system property (auto-set by Gradle from the project directory). +- The checked-in `Run IDE (Backend)`, `Run IDE (Frontend)`, and `Run IDE (Split Mode)` run configurations enable isolation by default (`-Pkilo.dev.storage.isolated=true`). Developers can disable it by passing `-Pkilo.dev.storage.isolated=false`. - Use standard `XDG_*_HOME` env vars for this isolation. Do not introduce custom `KILO_DATA_DIR`, `KILO_GLOBAL_CONFIG_DIR`, `KILO_STATE_DIR`, or `KILO_CACHE_DIR` env vars — the CLI core already respects `XDG_*_HOME` via `xdg-basedir`. - The `.kilo-dev/` directory is gitignored and created automatically on first run. - The implementation lives in `KiloBackendCliManager.buildEnv()` / `devStorageEnv()`. Tests: `KiloBackendCliManagerEnvTest`. @@ -194,9 +194,9 @@ For blocking I/O in coroutines, move the dispatcher switch inside the callee usi - **Gradle only**: `./gradlew buildPlugin` from `packages/kilo-jetbrains/` (requires CLI binaries already present in `backend/build/generated/cli/`; run `bun run build --prepare-cli` first). - **Java checks**: Do not run `java -version` as a routine preflight. Gradle commands already fail clearly when Java is missing or incompatible; check Java only when diagnosing that failure mode. - **Via Turbo**: `bun turbo build --filter=@kilocode/kilo-jetbrains` from repo root. -- **Run in sandbox**: `./gradlew runIde` — launches sandboxed IntelliJ with the plugin. Does NOT build CLI binaries. -- **Run split backend**: `./gradlew runIdeBackend` — if it exits shortly after startup, check for an orphaned Java process from a previous backend run and kill it before restarting. -- **Test split mode**: `./gradlew generateSplitModeRunConfigurations` creates a "Run IDE (Split Mode)" config that starts both frontend and backend processes locally. Emulate latency via the Split Mode widget (requires internal mode: `-Didea.is.internal=true`). +- **Run split mode**: `./gradlew --no-configuration-cache runIdeSplitMode` or the checked-in `Run IDE (Split Mode)` configuration — launches backend and frontend locally and prepares the local-platform CLI binary automatically. Emulate latency via the Split Mode widget (requires internal mode: `-Didea.is.internal=true`). +- **Run split backend**: `./gradlew --no-configuration-cache runIdeBackend` — prepares the local-platform CLI binary automatically; if it exits shortly after startup, check for an orphaned Java process from a previous backend run and kill it before restarting. +- **Run in monolithic sandbox**: `./gradlew runIde` — launches sandboxed IntelliJ with the plugin. Does NOT build CLI binaries. ### CLI/SDK Change Awareness diff --git a/packages/kilo-jetbrains/README.md b/packages/kilo-jetbrains/README.md index 2d704f9fee5..78978d66337 100644 --- a/packages/kilo-jetbrains/README.md +++ b/packages/kilo-jetbrains/README.md @@ -84,31 +84,34 @@ See [RELEASING.md](RELEASING.md) for the full release process, including how to ## Run the plugin -Use the `runIde` Gradle task (available in the Gradle tool window or via `./gradlew runIde` from `packages/kilo-jetbrains/`) to launch a sandboxed IntelliJ instance with the plugin installed. +Use the checked-in `Run IDE (Split Mode)` run configuration (or `./gradlew --no-configuration-cache runIdeSplitMode` from `packages/kilo-jetbrains/`) to launch the backend and frontend halves of a local split-mode sandbox. The task prepares the local-platform CLI binary automatically when `backend/build/generated/cli/cli/` does not contain the expected binary. -`runIde` does not prepare the CLI binary automatically. Run `bun run build --prepare-cli` from `packages/kilo-jetbrains/` first to copy the local-platform binary into `backend/build/generated/cli/cli/`. +Use `runIde` only when you need a monolithic sandboxed IntelliJ instance. `runIde` does not prepare the CLI binary automatically, so run `bun run build --prepare-cli` from `packages/kilo-jetbrains/` first to copy the local-platform binary into `backend/build/generated/cli/cli/`. Production packaging still requires running `bun run build:production` so all platform binaries are present. ### Run the split backend -Use the checked-in `Run IDE (Backend)` run configuration (or `./gradlew runIdeBackend`) to launch just the backend half of a split-mode session. It prepares the local-platform CLI binary automatically when `backend/build/generated/cli/cli/` does not contain the expected binary. +Use the checked-in `Run IDE (Backend)` run configuration (or `./gradlew --no-configuration-cache runIdeBackend`) to launch just the backend half of a split-mode session. It prepares the local-platform CLI binary automatically when `backend/build/generated/cli/cli/` does not contain the expected binary. If `Run IDE (Backend)` exits shortly after startup, check for an orphaned Java process from a previous backend run and kill it before restarting the backend. -Use `Run IDE (Split Mode)` to launch both halves at once (composes `Run IDE (Backend)` + `Run IDE (Frontend)`). +Use `Run IDE (Frontend)` (or `./gradlew --no-configuration-cache runIdeFrontend`) with a running backend when you need frontend JVM debugging; `Run IDE (Split Mode)` launches the frontend itself and does not attach frontend debugging. -### Backend Gradle properties +### Development Gradle properties All properties below are passed with `-P` on the Gradle command line or in the run configuration's script parameters field. | Property | Default | Description | |---|---|---| -| `kilo.splitModeServerPort` | random high port | Backend split-mode server port. `0` or omitted picks a random port from 49152-65535. | -| `kilo.dev.storage.isolated` | `false` | When `true`, CLI runs with `XDG_*_HOME` pointing to `.kilo-dev/` in the worktree root, fully isolating dev storage from your real Kilo installation. Enabled by default in `Run IDE (Backend)`. | +| `kilo.splitModeServerPort` | `0` | Backend split-mode server port. `0` or omitted lets the IntelliJ Platform Gradle Plugin pick a free port when the task runs. | +| `kilo.dev.storage.isolated` | `false` | When `true`, CLI runs with `XDG_*_HOME` pointing to `.kilo-dev/` in the worktree root, fully isolating dev storage from your real Kilo installation. Enabled by default in the checked-in split-mode run configurations. | | `kilo.dev.worktree.root` | monorepo root | Worktree root used to resolve `.kilo-dev/`. Auto-detected from the Gradle project directory; override only when the auto-detection is wrong. | | `kilo.bun.path` | `bun` on `$PATH` | Absolute path to Bun. Set this when IntelliJ-launched Gradle cannot find Bun automatically. | +The checked-in IDE run configurations pass `--no-configuration-cache` because the IntelliJ Platform Gradle Plugin run-IDE tasks are not configuration-cache compatible in this setup. +They also pass `--purge-old-log-directories` so stale sandbox logs do not hide the current backend and frontend `kilo-dev.log` files. + Example with a fixed split-mode port: ```text @@ -129,7 +132,7 @@ When `kilo.dev.storage.isolated=true`, the CLI subprocess receives standard `XDG This keeps all development data isolated from your real Kilo installation. The `.kilo-dev/` directory is gitignored and created automatically on first run. -The `Run IDE (Backend)` run configuration enables this by default. To disable it: +The checked-in `Run IDE (Backend)`, `Run IDE (Frontend)`, and `Run IDE (Split Mode)` run configurations enable this by default. To disable it: ```text -Pkilo.dev.storage.isolated=false @@ -139,7 +142,7 @@ The `Run IDE (Backend)` run configuration enables this by default. To disable it ### Debug logging properties -The plugin supports a few JVM system properties for local debugging. These are most useful with `runIde` in sandbox mode because the logs are mirrored to `kilo-dev.log` files for frontend and backend. +The plugin supports a few JVM system properties for local debugging. These are most useful with sandbox runs because the logs are mirrored to `kilo-dev.log` files for frontend and backend. `kilo.dev.log.level` @@ -164,7 +167,7 @@ The plugin supports a few JVM system properties for local debugging. These are m Where to find the log files: -- In sandbox `runIde` runs, Kilo writes separate dev log files for each side under the IDE sandbox log directory reported by `PathManager.getLogDir()`. +- In sandbox runs, Kilo writes separate dev log files for each side under the IDE sandbox log directory reported by `PathManager.getLogDir()`. - Frontend log file: `/kilo-frontend/kilo-dev.log` - Backend log file: `/kilo-backend/kilo-dev.log` - In practice these sit under the current `log_run*` sandbox logs for the active run. diff --git a/packages/kilo-jetbrains/build.gradle.kts b/packages/kilo-jetbrains/build.gradle.kts index 890853a9c22..50c07ca0044 100644 --- a/packages/kilo-jetbrains/build.gradle.kts +++ b/packages/kilo-jetbrains/build.gradle.kts @@ -3,26 +3,21 @@ import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType import org.jetbrains.intellij.platform.gradle.TestFrameworkType import org.jetbrains.intellij.platform.gradle.tasks.InstrumentCodeTask import org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask -import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware.SplitModeTarget +import org.jetbrains.intellij.platform.gradle.tasks.aware.SplitModeAware.PluginInstallationTarget import java.time.LocalDate group = "ai.kilocode.jetbrains" -val ports = 49152..65535 - -fun fallback(): Int { - return ports.random() -} - fun port(value: String): Int { val text = value.trim() - if (text.isEmpty()) return fallback() + require(text.isNotEmpty()) { + "kilo.splitModeServerPort must be an integer from 0 to 65535; use 0 or omit it for a random port" + } val n = text.toIntOrNull() - ?: error("kilo.splitModeServerPort must be an integer from 0 to 65535; use 0 or omit it for a random high port") + ?: error("kilo.splitModeServerPort must be an integer from 0 to 65535; use 0 or omit it for a random port") require(n in 0..65535) { - "kilo.splitModeServerPort must be an integer from 0 to 65535; use 0 or omit it for a random high port" + "kilo.splitModeServerPort must be an integer from 0 to 65535; use 0 or omit it for a random port" } - if (n == 0) return fallback() return n } @@ -95,7 +90,7 @@ val ver = override?.let(::checked) ?: prop?.let(::checked) ?: if (release) check ) else checked(tag ?: "0.0.0-dev") val channel = providers.gradleProperty("kilo.channel").map { it.trim() }.orElse("default") -val splitPort = providers.gradleProperty("kilo.splitModeServerPort").orNull?.let(::port) ?: fallback() +val splitPort = providers.gradleProperty("kilo.splitModeServerPort").map(::port).orElse(0) val isolated = providers.gradleProperty("kilo.dev.storage.isolated").map { it.toBoolean() }.orElse(false) val worktreeRoot = providers.gradleProperty("kilo.dev.worktree.root").orElse( providers.provider { rootProject.layout.projectDirectory.asFile.parentFile.parentFile.canonicalPath } @@ -180,7 +175,7 @@ dependencies { intellijPlatform { splitMode = true - splitModeTarget = SplitModeTarget.BOTH + pluginInstallationTarget = PluginInstallationTarget.BOTH pluginConfiguration { id = "ai.kilocode.jetbrains" @@ -229,6 +224,16 @@ tasks { dependsOn(":backend:prepareLocalCli") dependsOn(":backend:processResources") } + + runIdeFrontend { + splitModeServerPort.set(splitPort) + } + + runIdeSplitMode { + splitModeServerPort.set(splitPort) + dependsOn(":backend:prepareLocalCli") + dependsOn(":backend:processResources") + } } project(":backend").tasks.named("processResources") { diff --git a/packages/kilo-jetbrains/gradle/libs.versions.toml b/packages/kilo-jetbrains/gradle/libs.versions.toml index dca51580893..2cfb8872e11 100644 --- a/packages/kilo-jetbrains/gradle/libs.versions.toml +++ b/packages/kilo-jetbrains/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] intellij-platform = "2026.1" -intellij-gradle-plugin = "2.16.1-20260623.221413-11" +intellij-gradle-plugin = "2.17.0" intellij-rpc-plugin = "2.3.20-RC2-0.1" kotlin-jvm-plugin = "2.3.20" kotlin-serialization-plugin = "2.3.20" diff --git a/packages/kilo-jetbrains/settings.gradle.kts b/packages/kilo-jetbrains/settings.gradle.kts index d18a5006659..c9b17f77c25 100644 --- a/packages/kilo-jetbrains/settings.gradle.kts +++ b/packages/kilo-jetbrains/settings.gradle.kts @@ -6,19 +6,7 @@ include("backend") pluginManagement { includeBuild("build-tasks") - resolutionStrategy { - eachPlugin { - if (requested.id.id == "org.jetbrains.intellij.platform") { - useModule("org.jetbrains.intellij.platform:intellij-platform-gradle-plugin:${requested.version}") - } - } - } repositories { - maven("https://central.sonatype.com/repository/maven-snapshots/") { - content { - includeGroup("org.jetbrains.intellij.platform") - } - } mavenCentral() gradlePluginPortal() maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies/")