diff --git a/README.md b/README.md
index e77e3fbbf7f..2199ffd41ad 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
- ⚡ Inline autocomplete suggestions
- 🤖 Latest AI models
- 🎁 API keys optional
-- 💡 **Get $20 in bonus credits when you top-up for the first time** Credits can be used with 500+ models like Gemini 3.1 Pro, Claude 4.6 Sonnet & Opus, and GPT-5.2
+- 💡 **Get $20 in bonus credits when you top-up for the first time** Credits can be used with 500+ models like Gemini 3.1 Pro, Claude 4.6 Sonnet & Opus, and GPT-5.4
## Quick Links
@@ -38,7 +38,7 @@
## Get Started in Visual Studio Code
1. Install the Kilo Code extension from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=kilocode.Kilo-Code).
-2. Create your account to access 500+ cutting-edge AI models including Gemini 3 Pro, Claude 4.5 Sonnet & Opus, and GPT-5 – with transparent pricing that matches provider rates exactly.
+2. Create your account to access 500+ cutting-edge AI models including Gemini 3.1 Pro, Claude 4.6 Sonnet & Opus, and GPT-5.4 – with transparent pricing that matches provider rates exactly.
3. Start coding with AI that adapts to your workflow. Watch our quick-start guide to see Kilo in action:
diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts
index 9596d4a3920..481284eec01 100644
--- a/packages/kilo-vscode/src/KiloProvider.ts
+++ b/packages/kilo-vscode/src/KiloProvider.ts
@@ -126,6 +126,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
private cachedMcpStatusMessage: unknown = null
/** Ref-count of in-flight handleUpdateConfig calls; prevents fetchAndSendConfig from sending stale data */
private pending = 0
+ private configWarningsShown = false
/** Cached notificationsLoaded payload */
private cachedNotificationsMessage: unknown = null
private pendingReviewComments: { comments: unknown[]; autoSend: boolean }[] = []
@@ -1055,6 +1056,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
this.postMessage({ type: "connectionState", state })
if (state === "connected") {
+ // Fire config warnings independently so a failure in the
+ // sequential await chain doesn't prevent warnings from being shown
+ void this.checkConfigWarnings("state")
try {
// Profile fetch is best-effort — returns 401 when user isn't logged into gateway.
const sdkClient = this.client
@@ -1130,6 +1134,14 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
}
this.postMessage({ type: "connectionState", state: this.connectionState })
+
+ // connect() can resolve after SSE reaches "connected" but before this
+ // provider subscribes to onStateChange(). In that case the initial
+ // connected callback is missed, so run the warning check here too.
+ if (this.connectionState === "connected") {
+ void this.checkConfigWarnings("init")
+ }
+
await this.syncWebviewState("initializeConnection")
await this.flushPendingSessionRefresh("initializeConnection")
@@ -1965,6 +1977,49 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
}
}
+ /**
+ * Fetch config warnings from the server and display a single consolidated
+ * VS Code warning with a "Show Details" action button.
+ * Only shown once per provider lifecycle (flag resets on dispose/re-create, not on SSE reconnect).
+ */
+ private async checkConfigWarnings(from: string): Promise {
+ if (this.configWarningsShown) {
+ console.log("[Kilo New] KiloProvider: config warnings already shown", { from })
+ return
+ }
+ if (!this.client) {
+ console.log("[Kilo New] KiloProvider: config warnings skipped (no client)", { from })
+ return
+ }
+ try {
+ const dir = this.getWorkspaceDirectory()
+ console.log("[Kilo New] KiloProvider: checking config warnings", { from, dir })
+ const result = await this.client.config.warnings({ directory: dir })
+ const list = result?.data ?? []
+ console.log("[Kilo New] KiloProvider: config warnings fetched", { from, count: list.length })
+ if (list.length === 0) return
+ this.configWarningsShown = true
+
+ const first = list[0]!
+ const summary = list.length === 1 ? first.message : `${first.message} (and ${list.length - 1} more)`
+ console.warn("[Kilo New] KiloProvider: showing config warnings", { from, count: list.length, path: first.path })
+
+ const action = await vscode.window.showWarningMessage(`Config: ${summary}`, "Show Details")
+ if (action === "Show Details") {
+ const lines = list.map((w) => {
+ const base = `${w.path}\n ${w.message}`
+ return w.detail ? `${base}\n ${w.detail}` : base
+ })
+ const channel = vscode.window.createOutputChannel("Kilo Config Warnings")
+ channel.clear()
+ channel.appendLine(lines.join("\n\n"))
+ channel.show()
+ }
+ } catch (err) {
+ console.warn("[Kilo New] KiloProvider: checkConfigWarnings failed:", { from, err })
+ }
+ }
+
/**
* Fetch Kilo news/notifications and send to webview.
* Uses the cached message pattern so the webview gets data immediately on refresh.
diff --git a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
index d70103ab362..3554990404d 100644
--- a/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
+++ b/packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
@@ -695,11 +695,11 @@ export class AgentManagerProvider implements Disposable {
this.pushState()
// Disk removal after state is clean — pollers no longer reference this worktree.
try {
- await manager.removeWorktree(worktree.path, worktree.branch)
+ await manager.removeWorktree(worktree.path, worktree.originalBranch ?? worktree.branch)
} catch (error) {
this.log(`Failed to remove worktree from disk: ${error}`)
}
- this.log(`Deleted worktree ${worktreeId} (${worktree.branch})`)
+ this.log(`Deleted worktree ${worktreeId} (${worktree.originalBranch ?? worktree.branch})`)
return null
}
@@ -1444,12 +1444,20 @@ export class AgentManagerProvider implements Disposable {
const entries = result.worktrees.filter((item) => ids.has(item.worktreeId))
if (entries.length === 0) return
+ // Sync branches from git worktree list (no extra git calls)
+ let branchChanged = false
+ for (const entry of entries) {
+ if (entry.branch && state.updateWorktreeBranch(entry.worktreeId, entry.branch)) {
+ branchChanged = true
+ }
+ }
+
const next = new Set(entries.filter((entry) => entry.missing).map((entry) => entry.worktreeId))
- const changed =
+ const staleChanged =
next.size !== this.staleWorktreeIds.size || [...next].some((worktreeId) => !this.staleWorktreeIds.has(worktreeId))
this.staleWorktreeIds = next
- if (changed) {
+ if (staleChanged || branchChanged) {
this.pushState()
}
}
diff --git a/packages/kilo-vscode/src/agent-manager/GitOps.ts b/packages/kilo-vscode/src/agent-manager/GitOps.ts
index 9aa393513ce..dcd74e95987 100644
--- a/packages/kilo-vscode/src/agent-manager/GitOps.ts
+++ b/packages/kilo-vscode/src/agent-manager/GitOps.ts
@@ -130,14 +130,14 @@ export class GitOps {
}
/** Return the set of worktree paths for the repo, excluding bare entries. */
- async listWorktreePaths(cwd: string): Promise> {
+ async listWorktreePaths(cwd: string): Promise