fix: exclude generated data from Spotlight indexing (#9833)

This commit is contained in:
Marius
2026-05-04 13:39:32 +00:00
committed by GitHub
parent a5bb938dbd
commit 614bca7cff
6 changed files with 91 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@kilocode/cli": patch
"kilo-code": patch
---
Prevent macOS Spotlight from indexing Kilo-generated data directories.
+5
View File
@@ -4,6 +4,7 @@ import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
import os from "os"
import { Context, Effect, Layer } from "effect"
import { Flock } from "./util/flock"
import { markNoIndex } from "./kilocode/spotlight" // kilocode_change
const app = "kilo" // kilocode_change
// kilocode_change start
@@ -45,6 +46,10 @@ await Promise.all([
fs.mkdir(Path.bin, { recursive: true }),
])
// kilocode_change start - keep generated Kilo data out of macOS Spotlight
await Promise.all([Path.data, Path.cache, Path.state].map(markNoIndex))
// kilocode_change end
export class Service extends Context.Service<Service, Interface>()("@opencode/Global") {}
export interface Interface {
+23
View File
@@ -0,0 +1,23 @@
import fs from "fs/promises"
import path from "path"
const marker = ".metadata_never_index"
function exists(err: unknown): boolean {
if (typeof err !== "object" || err === null) return false
return "code" in err && err.code === "EEXIST"
}
function message(err: unknown): string {
if (err instanceof Error) return err.message
return String(err)
}
export async function markNoIndex(dir: string): Promise<void> {
if (process.platform !== "darwin") return
const file = path.join(dir, marker)
await fs.writeFile(file, "", { flag: "wx" }).catch((err) => {
if (exists(err)) return
process.emitWarning(`Failed to mark ${dir} as Spotlight-excluded: ${message(err)}`)
})
}
@@ -13,6 +13,7 @@ import simpleGit, { type SimpleGit } from "simple-git"
import { generateBranchName, sanitizeBranchName } from "./branch-name"
import { type GitOps, nonInteractiveEnv } from "./GitOps"
import { execWithShellEnv } from "./shell-env"
import { markNoIndex } from "../util/spotlight"
import {
parsePRUrl,
localBranchName,
@@ -424,6 +425,7 @@ export class WorktreeManager {
async discoverWorktrees(): Promise<WorktreeInfo[]> {
await this.ensureMigrated()
if (!fs.existsSync(this.dir)) return []
await markNoIndex(this.dir, this.log)
const entries = await fs.promises.readdir(this.dir, { withFileTypes: true })
this.cleanupOrphanedTempDirs()
@@ -575,6 +577,7 @@ export class WorktreeManager {
if (!fs.existsSync(this.dir)) {
await fs.promises.mkdir(this.dir, { recursive: true })
}
await markNoIndex(this.dir, this.log)
}
private async resolveGitDir(): Promise<string> {
+5
View File
@@ -19,6 +19,7 @@ import { registerCodeActions, registerTerminalActions, KiloCodeActionProvider }
import { registerToggleAutoApprove } from "./commands/toggle-auto-approve"
import { registerHeapSnapshot } from "./commands/heap-snapshot"
import { RemoteStatusService } from "./services/RemoteStatusService"
import { markWorkspace } from "./util/spotlight"
// Activated via "onStartupFinished" (package.json) so that commands, code actions, keybindings,
// autocomplete, commit-message generation, and URI deep links all work immediately — without
@@ -67,6 +68,10 @@ export function activate(context: vscode.ExtensionContext) {
// Prewarm the CLI backend early so autocomplete is ready before first editor use.
ensureBackendForAutocomplete(connectionService)
for (const folder of vscode.workspace.workspaceFolders ?? []) {
void markWorkspace(folder.uri.fsPath, (msg) => console.warn(`[Kilo New] ${msg}`))
}
// Track all open tab panel providers so toolbar button commands can target them.
// NOTE: The editor/title toolbar for tab panels intentionally omits Agent Manager
// and Marketplace buttons (unlike the sidebar). Too many icons causes VS Code to
@@ -0,0 +1,49 @@
import * as fs from "fs"
import * as path from "path"
const marker = ".metadata_never_index"
function exists(err: unknown): boolean {
if (typeof err !== "object" || err === null) return false
return "code" in err && err.code === "EEXIST"
}
function message(err: unknown): string {
if (err instanceof Error) return err.message
return String(err)
}
export async function markNoIndex(dir: string, log: (msg: string) => void): Promise<void> {
if (process.platform !== "darwin") return
const file = path.join(dir, marker)
await fs.promises.writeFile(file, "", { flag: "wx" }).catch((err) => {
if (exists(err)) return
log(`Warning: Failed to mark ${dir} as Spotlight-excluded: ${message(err)}`)
})
}
async function directory(dir: string): Promise<boolean> {
return fs.promises
.stat(dir)
.then((stat) => stat.isDirectory())
.catch(() => false)
}
function parent(dir: string): string | undefined {
const parts = path.resolve(dir).split(path.sep)
for (let i = 0; i < parts.length - 1; i++) {
const hidden = parts[i] === ".kilo" || parts[i] === ".kilocode"
if (hidden && parts[i + 1] === "worktrees") return parts.slice(0, i + 2).join(path.sep) || path.sep
}
return undefined
}
export async function markWorkspace(root: string, log: (msg: string) => void): Promise<void> {
const ancestor = parent(root)
if (ancestor) await markNoIndex(ancestor, log)
for (const name of [".kilo", ".kilocode"]) {
const dir = path.join(root, name, "worktrees")
if (await directory(dir)) await markNoIndex(dir, log)
}
}