.kilo/plans/jetbrains-context-settings-page.md
Implement the Tier 1 Context settings from docs/jetbrains-vscode-settings-parity.md in the JetBrains plugin. This is a pure kilo.json settings UI: no CLI feature work, no SDK regen, and no session-rendering changes.
Add a new JetBrains settings page under Settings -> Tools -> Kilo Code -> Context for:
| Setting | Config key | Type |
|---|---|---|
| Auto-compaction | compaction.auto | boolean |
| Compaction threshold percent | compaction.threshold_percent | number or null |
| Prune on compaction | compaction.prune | boolean |
| Watcher ignore patterns | watcher.ignore | string array |
Do not include VS Code Context-tab memory/indexing controls in this first pass. JetBrains does not have the equivalent memory/indexing settings service yet, and the parity doc excludes indexing from easy wins.
Do not put snapshot on this page unless product explicitly decides to combine Context and Checkpoints. The parity doc suggests snapshot belongs on a new Checkpoints page.
docs/jetbrains-vscode-settings-parity.md.packages/kilo-jetbrains/AGENTS.md, especially Settings UI.packages/kilo-jetbrains/frontend/src/main/resources/kilo.jetbrains.frontend.xml.packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/models/ModelsConfigurable.ktpackages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/models/ModelsSettingsUi.ktpackages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/models/ModelsSettingsState.ktKiloAppService.updateConfigAsync(...)KiloAppRpcApi.updateConfig(patch: ConfigPatchDto)KiloBackendAppService.updateConfig(...)PATCH /global/config, then GET /global/configConfigPatchDto.values; Context needs typed booleans, numbers, explicit null, and string arrays.ConfigPatchDto.values for non-string values.clear list for nullable compaction fields, because Double? cannot distinguish absent from explicit null.BaseSettingsUi, DraftReadyConfigurable, SettingsDraftState, SettingsRows, SettingsRow, and SettingsToggle.watcher.ignore; do not build a bespoke add/remove list if SettingsListPanel or adjacent list primitives fit.KiloBundle.properties. Let other locale bundles fall back unless the repo's resource-bundle checks require duplicated English keys.File: packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/dto/KiloAppStateDto.kt
Add config read DTOs:
@Serializable
data class WatcherConfigDto(
val ignore: List<String> = emptyList(),
)
@Serializable
data class CompactionConfigDto(
val auto: Boolean? = null,
val threshold_percent: Double? = null,
val prune: Boolean? = null,
)
Extend ConfigDto:
val watcher: WatcherConfigDto? = null,
val compaction: CompactionConfigDto? = null,
Add patch DTOs:
@Serializable
data class WatcherPatchDto(
val ignore: List<String>? = null,
)
@Serializable
data class CompactionPatchDto(
val clear: List<String> = emptyList(),
val auto: Boolean? = null,
val threshold_percent: Double? = null,
val prune: Boolean? = null,
)
Extend ConfigPatchDto:
val watcher: WatcherPatchDto? = null,
val compaction: CompactionPatchDto? = null,
Notes:
watcher.ignore = null means no change.watcher.ignore = emptyList() means explicitly save an empty list.compaction.threshold_percent = null alone means no change.compaction.clear = listOf("threshold_percent") means emit JSON "threshold_percent": null.false boolean values must be serialized; do not treat false as absent.File: packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloCliDataParser.kt
Extend parseConfig(raw) to read:
watcher.ignorecompaction.autocompaction.threshold_percentcompaction.pruneAdd private helpers near parseSkillsConfig / parseMcpConfig:
private fun parseWatcherConfig(obj: JsonObject?): WatcherConfigDto?
private fun parseCompactionConfig(obj: JsonObject?): CompactionConfigDto?
Use existing helper style:
str(...)flagOrNull(...)num(...)arr()?.mapNotNull { it.jsonPrimitive.contentOrNull }Extend buildConfigPatch(patch) to emit typed context patches:
{
"watcher": {
"ignore": ["**/node_modules/**"]
},
"compaction": {
"auto": true,
"threshold_percent": 80,
"prune": false
}
}
For explicit threshold clearing:
{
"compaction": {
"threshold_percent": null
}
}
Keep the existing values allowlist for string model keys. Do not pass Context values through values.
Add package: packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/context/
New file: ContextSettingsState.kt
Define:
internal data class ContextDraft(
val auto: Boolean? = null,
val threshold: String = "",
val prune: Boolean? = null,
val ignore: List<String> = emptyList(),
)
Use a string for the threshold draft so the UI can represent blank/invalid intermediate input without losing user text. Convert only when building a patch.
Functions to add:
contextDraft(config: ConfigDto?): ContextDraftpatch(from: ContextDraft, to: ContextDraft): ConfigPatchDtosavedMatches(base: ContextDraft, draft: ContextDraft): Booleanthreshold(value: String): Double? or equivalent parsing helperPatch behavior:
CompactionPatchDto(auto = false) when the user turns auto-compaction off.CompactionPatchDto(prune = false) when the user turns pruning off.CompactionPatchDto(threshold_percent = 80.0) for a non-blank valid number.CompactionPatchDto(clear = listOf("threshold_percent")) when an existing threshold is cleared.WatcherPatchDto(ignore = emptyList()) when the last ignore pattern is removed.New file: ContextConfigurable.kt
Mirror ModelsConfigurable:
DraftReadyConfigurable<JComponent>.ID = "ai.kilocode.jetbrains.settings.context".getDisplayName() returns KiloBundle.message("settings.context.displayName").create(cs) returns ContextSettingsUi(cs).New file: ContextSettingsUi.kt
Mirror the simple parts of ModelsSettingsUi:
BaseSettingsUi<ContextSettingsContent, ContextDraft, ConfigPatchDto, KiloAppStateDto, Unit>.ContextDraft().save(change, done) calls app.updateConfigAsync(change, done).base(result) and draft(state) call contextDraft(state.config).saved(base, draft) calls savedMatches(base, draft).pendingText() uses settings.context.save.pending.failedText() uses settings.context.save.failed.loadWorkspace(root) returns Unit; applyWorkspace(result) is Unit.models(state) is Unit.syncContent() updates enabled states, field values, save/progress overlay, and validation messaging.New content class: ContextSettingsContent
Suggested layout:
settings.context.compaction.title
settings.context.compaction.auto.titlesettings.context.compaction.threshold.titlesettings.context.compaction.prune.titlesettings.context.watcher.title
Controls:
SettingsToggle for booleans.JBTextField or a small reusable numeric field pattern based on AgentEditDialog for threshold.SettingsListPanel / SettingsListView / SettingsListItem / SettingsListCell) for watcher.ignore where practical.Validation:
apply() from sending a patch.0..100; if existing CLI allows a broader range, follow CLI behavior.File: packages/kilo-jetbrains/frontend/src/main/resources/kilo.jetbrains.frontend.xml
Add a child configurable:
<applicationConfigurable
parentId="ai.kilocode.jetbrains.settings"
id="ai.kilocode.jetbrains.settings.context"
groupWeight="3"
instance="ai.kilocode.client.settings.context.ContextConfigurable"
bundle="messages.KiloBundle"
key="settings.context.displayName"/>
Adjust weights so the desired order is stable. Recommended order:
| Page | Weight |
|---|---|
| User Profile | 5 |
| Models | 4 |
| Context | 3 |
| Providers | 2 |
| Agent Behavior | 1 |
File: packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/settings/KiloSettingsConfigurable.kt
Add a root-page ActionLink for Context between Models and Providers:
ContextConfigurable.settings.context.displayName.ContextConfigurable.ID.KiloSettingsSelection.kt probably needs no code changes because child IDs already share the root prefix.
File: packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle.properties
Add base strings near the other settings strings:
settings.context.displayName=Context
settings.context.description=Configure compaction and file-watcher context behavior.
settings.context.save.pending=Saving context settings...
settings.context.save.failed=Failed to save context settings
settings.context.compaction.title=Compaction
settings.context.compaction.description=Control when Kilo summarizes long sessions to reduce context usage.
settings.context.compaction.auto.title=Auto-compaction
settings.context.compaction.auto.description=Automatically compact long conversations before they exceed the model context window.
settings.context.compaction.threshold.title=Compaction threshold
settings.context.compaction.threshold.description=Percent of the context window to use before auto-compaction starts. Leave blank to use the default.
settings.context.compaction.threshold.invalid=Enter a number from 0 to 100, or leave the field blank.
settings.context.compaction.prune.title=Prune on compaction
settings.context.compaction.prune.description=Drop older raw conversation details after compaction to keep the session context smaller.
settings.context.watcher.title=Watcher ignore patterns
settings.context.watcher.description=Glob patterns Kilo should ignore when watching repository file changes.
settings.context.watcher.add=Add pattern
settings.context.watcher.empty=No ignore patterns configured.
settings.context.watcher.placeholder=e.g. **/dist/**
settings.context.watcher.remove=Remove {0}
If resource-bundle tests require every key in every locale bundle, copy English values into the localized bundles and leave translation work for a later i18n pass.
Add: packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/context/ContextSettingsStateTest.kt
Cover:
ConfigDto.watcher and ConfigDto.compaction.false and true correctly.threshold_percent.clear = listOf("threshold_percent").ignore list, including empty list.Add: packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/context/ContextSettingsUiTest.kt
Use ModelsSettingsUiTest as the main pattern:
BasePlatformTestCase.FakeAppRpcApi.KiloAppService.flushUntil helpers.rpc.configPatches after user interaction.settings.context.save.failed.Update FakeAppRpcApi:
packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/testing/FakeAppRpcApi.ktpatch.watcher and patch.compaction to fake config state.false.compaction.clear by setting cleared fields to null.Update: packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/cli/KiloCliDataParserTest.kt
Add exact JSON tests for:
parseConfig reads watcher and compaction fields.buildConfigPatch emits watcher ignore arrays.buildConfigPatch emits auto=false and prune=false.buildConfigPatch emits numeric threshold_percent.buildConfigPatch emits explicit threshold_percent:null when clear includes the field.Update: packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/app/KiloBackendAppServiceTest.kt
Add a test similar to the existing model config update test:
updateConfig(ConfigPatchDto(watcher = ..., compaction = ...)).MockCliServer.lastConfigPatchBody exactly matches the expected nested JSON.ConfigDto includes the saved Context values.Update: packages/kilo-jetbrains/frontend/src/test/kotlin/ai/kilocode/client/settings/KiloSettingsConfigurableTest.kt
Add:
ContextConfigurable.ID == "ai.kilocode.jetbrains.settings.context".Run from packages/kilo-jetbrains/:
./gradlew typecheck
./gradlew test
Focused checks while iterating:
./gradlew :shared:test --tests '*ContextSettingsStateTest'
./gradlew :frontend:test --tests '*ContextSettingsUiTest'
./gradlew :backend:test --tests '*KiloCliDataParserTest'
./gradlew :backend:test --tests '*KiloBackendAppServiceTest'
If the exact Gradle module test selectors differ, run the package-level ./gradlew test before marking the implementation ready.
Manual verification:
./gradlew runIde from packages/kilo-jetbrains/.Settings -> Tools -> Kilo Code -> Context.Open: global ... action if needed.snapshot separately unless product asks to combine it with Context.kilo-code/JetBrains according to repo release guidance.