From e83b25e8d93ee9c236514e4562f828b2e5f858e4 Mon Sep 17 00:00:00 2001 From: kirillk Date: Wed, 5 Aug 2026 09:52:59 -0400 Subject: [PATCH] fix(cli): stop eager file watchers on JetBrains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JetBrains backend eagerly warmed the v2 location stack for every instance, which starts a native @parcel/watcher subscription that lives for the whole session. On macOS FSEvents watches the entire subtree recursively (the ignore list is only a userspace filter), so this always-on watcher burns CPU and leaks native memory while the IDE is idle — the cause of the 150%+ CPU and multi-GB RSS growth reported in `kilo serve` on macOS. The watcher's only consumer is the CLI/TUI sidebar branch label via the vcs.branch.updated event. JetBrains, like VS Code, has its own git integration and does not consume that event, so eager watchers are pure overhead for it. Extend the existing VS Code gate to also exclude jetbrains; the standalone CLI/TUI stays eager, and editor clients still build the stack lazily if a real file/pty route needs it. Fixes #12721 --- .changeset/quiet-jetbrains-watchers.md | 5 +++++ packages/opencode/src/kilocode/watcher.ts | 11 ++++++++++- .../test/kilocode/instance-vcs-watcher.test.ts | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .changeset/quiet-jetbrains-watchers.md diff --git a/.changeset/quiet-jetbrains-watchers.md b/.changeset/quiet-jetbrains-watchers.md new file mode 100644 index 0000000000..3e07e6c698 --- /dev/null +++ b/.changeset/quiet-jetbrains-watchers.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Fix high CPU and runaway memory growth in the JetBrains background `kilo serve` process on macOS by no longer eagerly starting native file watchers, matching the VS Code backend. diff --git a/packages/opencode/src/kilocode/watcher.ts b/packages/opencode/src/kilocode/watcher.ts index 6553d3e105..fd88764e24 100644 --- a/packages/opencode/src/kilocode/watcher.ts +++ b/packages/opencode/src/kilocode/watcher.ts @@ -15,8 +15,17 @@ export namespace KilocodeWatcher { export class Service extends Context.Service()("@kilocode/Watcher") {} + // Embedded editor clients (VS Code, JetBrains) have their own file watching + // and git integration and do not consume the CLI's vcs.branch.updated event, + // so they must not eagerly warm the location stack — that starts a native + // @parcel/watcher subscription per instance that lives for the whole session. + // On macOS FSEvents watches the entire subtree recursively (the ignore list + // is only a userspace filter), so an always-on, consumer-less watcher on a + // churny workspace burns CPU and leaks native memory while idle. The + // standalone CLI/TUI stays eager because its sidebar branch label is the only + // consumer and no request-driven route would otherwise build the stack. export function eager(client = Flag.KILO_CLIENT) { - return client !== "vscode" + return client !== "vscode" && client !== "jetbrains" } export const layer = Layer.effect( diff --git a/packages/opencode/test/kilocode/instance-vcs-watcher.test.ts b/packages/opencode/test/kilocode/instance-vcs-watcher.test.ts index e3861069e9..cf8f7b5386 100644 --- a/packages/opencode/test/kilocode/instance-vcs-watcher.test.ts +++ b/packages/opencode/test/kilocode/instance-vcs-watcher.test.ts @@ -34,6 +34,10 @@ describe("KilocodeWatcher.eager", () => { expect(KilocodeWatcher.eager("vscode")).toBe(false) }) + test("skips eager location watchers for JetBrains", () => { + expect(KilocodeWatcher.eager("jetbrains")).toBe(false) + }) + test("keeps eager location watchers for the standalone CLI", () => { expect(KilocodeWatcher.eager("cli")).toBe(true) expect(KilocodeWatcher.eager(undefined)).toBe(true)