Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,17 @@ 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/` |
|---|---|
| Typecheck | `./gradlew typecheck` |
| 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.

Expand Down
2 changes: 1 addition & 1 deletion packages/kilo-jetbrains/.run/Run IDE (Backend).run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/packages/kilo-jetbrains" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pkilo.dev.log.level=debug -Pkilo.splitModeServerPort=0 -Pkilo.dev.storage.isolated=true" />
<option name="scriptParameters" value="--no-configuration-cache --purge-old-log-directories -Pkilo.dev.log.level=debug -Pkilo.splitModeServerPort=0 -Pkilo.dev.storage.isolated=true" />
<option name="taskDescriptions">
<list />
</option>
Expand Down
2 changes: 1 addition & 1 deletion packages/kilo-jetbrains/.run/Run IDE (Frontend).run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/packages/kilo-jetbrains" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pkilo.dev.log.level=debug" />
<option name="scriptParameters" value="--no-configuration-cache --purge-old-log-directories -Pkilo.dev.log.level=debug -Pkilo.splitModeServerPort=0 -Pkilo.dev.storage.isolated=true" />
<option name="taskDescriptions">
<list />
</option>
Expand Down
28 changes: 25 additions & 3 deletions packages/kilo-jetbrains/.run/runIdeSplitMode.run.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run IDE (Split Mode)" type="CompoundRunConfigurationType" factoryName="Compound Run Configuration">
<toRun type="GradleRunConfiguration" name="Run IDE (Backend)" />
<toRun type="GradleRunConfiguration" name="Run IDE (Frontend)" />
<configuration default="false" name="Run IDE (Split Mode)" type="GradleRunConfiguration" factoryName="Gradle">
<log_file alias="Backend Kilo" path="$PROJECT_DIR$/packages/kilo-jetbrains/.intellijPlatform/sandbox/kilo.jetbrains/kilo-backend/kilo-dev.log" show_all="true" />
<log_file alias="Frontend Kilo" path="$PROJECT_DIR$/packages/kilo-jetbrains/.intellijPlatform/sandbox/kilo.jetbrains/kilo-frontend/kilo-dev.log" show_all="true" />
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/packages/kilo-jetbrains" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--no-configuration-cache --purge-old-log-directories -Pkilo.dev.log.level=debug -Pkilo.splitModeServerPort=0 -Pkilo.dev.storage.isolated=true" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":runIdeSplitMode" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
10 changes: 5 additions & 5 deletions packages/kilo-jetbrains/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<worktree>/.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 `<worktree>/.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`.
Expand All @@ -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

Expand Down
23 changes: 13 additions & 10 deletions packages/kilo-jetbrains/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment thread
kirillk marked this conversation as resolved.
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
Expand All @@ -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
Expand All @@ -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`

Expand All @@ -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: `<sandbox log dir>/kilo-frontend/kilo-dev.log`
- Backend log file: `<sandbox log dir>/kilo-backend/kilo-dev.log`
- In practice these sit under the current `log_run*` sandbox logs for the active run.
Expand Down
31 changes: 18 additions & 13 deletions packages/kilo-jetbrains/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -180,7 +175,7 @@ dependencies {

intellijPlatform {
splitMode = true
splitModeTarget = SplitModeTarget.BOTH
pluginInstallationTarget = PluginInstallationTarget.BOTH

pluginConfiguration {
id = "ai.kilocode.jetbrains"
Expand Down Expand Up @@ -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") {
Expand Down
2 changes: 1 addition & 1 deletion packages/kilo-jetbrains/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
12 changes: 0 additions & 12 deletions packages/kilo-jetbrains/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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/")
Expand Down
Loading