From c626678d9a28b59bfee0447da7655729ad15c1ab Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:12:58 +0200 Subject: [PATCH 01/11] feat(cli): add bell() utility for terminal attention requests Write ASCII BEL character to stdout when running in a TTY. Causes dock bounce on macOS, taskbar flash on Windows, and urgency hint on Linux. --- packages/opencode/src/kilocode/bell.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/opencode/src/kilocode/bell.ts diff --git a/packages/opencode/src/kilocode/bell.ts b/packages/opencode/src/kilocode/bell.ts new file mode 100644 index 00000000000..d7ae08a78ec --- /dev/null +++ b/packages/opencode/src/kilocode/bell.ts @@ -0,0 +1,6 @@ +// kilocode_change - new file +export function bell() { + if (process.stdout.isTTY) { + process.stdout.write("\x07") + } +} From 0e5941e2eaecb7fbecc78b3865ced83582a16065 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:13:38 +0200 Subject: [PATCH 02/11] feat(cli): ring bell when task completes in TUI Watch session status transitions to idle and write BEL to bounce the dock icon / flash the taskbar. --- .../src/cli/cmd/tui/routes/session/index.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 42c0b59d29c..796a27a8331 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -84,6 +84,7 @@ import { UI } from "@/cli/ui.ts" import { useTuiConfig } from "../../context/tui-config" import { formatMarkdownTables } from "../../util/markdown" // kilocode_change +import { bell } from "@/kilocode/bell" // kilocode_change addDefaultParsers(parsers.parsers) @@ -149,6 +150,17 @@ export function Session() { return messages().findLast((x) => x.role === "assistant") }) + // kilocode_change start - ring terminal bell on task completion + createEffect( + on( + () => sync.data.session_status?.[route.sessionID]?.type, + (type, prev) => { + if (prev && prev !== "idle" && type === "idle") bell() + }, + ), + ) + // kilocode_change end + const dimensions = useTerminalDimensions() const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar", "auto") const [sidebarOpen, setSidebarOpen] = createSignal(false) From 4794d32e9858a9fd0a3a4c3033e93c0c89930161 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:13:58 +0200 Subject: [PATCH 03/11] feat(cli): ring bell on permission and question prompts Alert the user when the agent needs input for a permission request or asks a question. --- .../src/cli/cmd/tui/routes/session/index.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 796a27a8331..ccaaafce822 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -161,6 +161,25 @@ export function Session() { ) // kilocode_change end + // kilocode_change start - ring terminal bell when input is needed + createEffect( + on( + () => permissions().length, + (len, prev) => { + if (prev !== undefined && len > (prev ?? 0)) bell() + }, + ), + ) + createEffect( + on( + () => questions().length, + (len, prev) => { + if (prev !== undefined && len > (prev ?? 0)) bell() + }, + ), + ) + // kilocode_change end + const dimensions = useTerminalDimensions() const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar", "auto") const [sidebarOpen, setSidebarOpen] = createSignal(false) From 271144dd706263b93a08e398de3e578aa514a9fe Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:14:24 +0200 Subject: [PATCH 04/11] feat(cli): ring bell on task completion in kilo run Alert the user when headless mode finishes processing. --- packages/opencode/src/cli/cmd/run.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 8a0df9a569c..ab5c93f8521 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -28,6 +28,7 @@ import { SkillTool } from "../../tool/skill" import { BashTool } from "../../tool/bash" import { TodoWriteTool } from "../../tool/todo" import { Locale } from "../../util/locale" +import { bell } from "../../kilocode/bell" // kilocode_change import { importCloudSession, validateCloudFork } from "@/kilocode/cloud-session" // kilocode_change type ToolProps = { @@ -566,6 +567,7 @@ export const RunCommand = cmd({ event.properties.sessionID === sessionID && event.properties.status.type === "idle" ) { + bell() // kilocode_change break } From 11d8e8663775d49fa333f4a751d2f46c90e2863b Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:27:31 +0200 Subject: [PATCH 05/11] fix(cli): skip bell in kilo run JSON format mode Avoid writing BEL to stdout when --format json is active, matching the guard pattern used by other output in run.ts. --- packages/opencode/src/cli/cmd/run.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index ab5c93f8521..28a4e25e5b7 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -567,7 +567,7 @@ export const RunCommand = cmd({ event.properties.sessionID === sessionID && event.properties.status.type === "idle" ) { - bell() // kilocode_change + if (args.format !== "json") bell() // kilocode_change break } From 929aea38d137d4f3691f36aca5afeba88656fe9e Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:44:13 +0200 Subject: [PATCH 06/11] fix(cli): skip bell on session route change --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index ccaaafce822..eb5800b98ca 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -153,9 +153,10 @@ export function Session() { // kilocode_change start - ring terminal bell on task completion createEffect( on( - () => sync.data.session_status?.[route.sessionID]?.type, - (type, prev) => { - if (prev && prev !== "idle" && type === "idle") bell() + () => [route.sessionID, sync.data.session_status?.[route.sessionID]?.type] as const, + ([id, type], prev) => { + if (!prev || prev[0] !== id) return + if (prev[1] && prev[1] !== "idle" && type === "idle") bell() }, ), ) From 3ce6dd95056d5f06b0738b4891c963550fe02d46 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 14:44:43 +0200 Subject: [PATCH 07/11] fix(cli): skip input bell on route change --- .../src/cli/cmd/tui/routes/session/index.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index eb5800b98ca..1e740880a5e 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -165,17 +165,19 @@ export function Session() { // kilocode_change start - ring terminal bell when input is needed createEffect( on( - () => permissions().length, - (len, prev) => { - if (prev !== undefined && len > (prev ?? 0)) bell() + () => [route.sessionID, permissions().length] as const, + ([id, len], prev) => { + if (!prev || prev[0] !== id) return + if (len > prev[1]) bell() }, ), ) createEffect( on( - () => questions().length, - (len, prev) => { - if (prev !== undefined && len > (prev ?? 0)) bell() + () => [route.sessionID, questions().length] as const, + ([id, len], prev) => { + if (!prev || prev[0] !== id) return + if (len > prev[1]) bell() }, ), ) From 95131dada770f5d9db41c27ebc77e3bc570a9c05 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 15:11:39 +0200 Subject: [PATCH 08/11] fix(cli): remove run bell --- packages/opencode/src/cli/cmd/run.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 28a4e25e5b7..8a0df9a569c 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -28,7 +28,6 @@ import { SkillTool } from "../../tool/skill" import { BashTool } from "../../tool/bash" import { TodoWriteTool } from "../../tool/todo" import { Locale } from "../../util/locale" -import { bell } from "../../kilocode/bell" // kilocode_change import { importCloudSession, validateCloudFork } from "@/kilocode/cloud-session" // kilocode_change type ToolProps = { @@ -567,7 +566,6 @@ export const RunCommand = cmd({ event.properties.sessionID === sessionID && event.properties.status.type === "idle" ) { - if (args.format !== "json") bell() // kilocode_change break } From 1ddaae711a26b98793f036eda173ab503aaa7db6 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 15:12:00 +0200 Subject: [PATCH 09/11] fix(cli): add bell toggle --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 1e740880a5e..7d843ec4b46 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -156,7 +156,7 @@ export function Session() { () => [route.sessionID, sync.data.session_status?.[route.sessionID]?.type] as const, ([id, type], prev) => { if (!prev || prev[0] !== id) return - if (prev[1] && prev[1] !== "idle" && type === "idle") bell() + if (prev[1] && prev[1] !== "idle" && type === "idle" && bellEnabled()) bell() }, ), ) @@ -168,7 +168,7 @@ export function Session() { () => [route.sessionID, permissions().length] as const, ([id, len], prev) => { if (!prev || prev[0] !== id) return - if (len > prev[1]) bell() + if (len > prev[1] && bellEnabled()) bell() }, ), ) @@ -177,7 +177,7 @@ export function Session() { () => [route.sessionID, questions().length] as const, ([id, len], prev) => { if (!prev || prev[0] !== id) return - if (len > prev[1]) bell() + if (len > prev[1] && bellEnabled()) bell() }, ), ) @@ -195,6 +195,7 @@ export function Session() { const [showHeader, setShowHeader] = kv.signal("header_visible", true) const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word") const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true) + const [bellEnabled, setBellEnabled] = kv.signal("bell_enabled", true) const [showGenericToolOutput, setShowGenericToolOutput] = kv.signal("generic_tool_output_visibility", false) const wide = createMemo(() => dimensions().width > 120) From 70d2906149f9af1361411b2dd994a9cae147382c Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 15:12:18 +0200 Subject: [PATCH 10/11] fix(cli): add notifications toggle --- .../opencode/src/cli/cmd/tui/routes/session/index.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 7d843ec4b46..afc6907c0f0 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -679,6 +679,15 @@ export function Session() { dialog.clear() }, }, + { + title: bellEnabled() ? "Disable notifications" : "Enable notifications", + value: "session.toggle.bell", + category: "Session", + onSelect: (dialog) => { + setBellEnabled((prev) => !prev) + dialog.clear() + }, + }, { title: "Page up", value: "session.page.up", From 98dc60c368412eed4bee57ab9059db7c51297fb2 Mon Sep 17 00:00:00 2001 From: Alex Alecu Date: Wed, 18 Mar 2026 15:17:54 +0200 Subject: [PATCH 11/11] fix(cli): show notifications in ctrl+p --- packages/opencode/src/cli/cmd/tui/app.tsx | 9 +++++++++ .../opencode/src/cli/cmd/tui/routes/session/index.tsx | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index e061cb722b9..147078e0170 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -645,6 +645,15 @@ function App() { dialog.clear() }, }, + { + title: kv.get("bell_enabled", true) ? "Disable notifications" : "Enable notifications", + value: "app.toggle.notifications", + category: "System", + onSelect: (dialog) => { + kv.set("bell_enabled", !kv.get("bell_enabled", true)) + dialog.clear() + }, + }, { title: kv.get("animations_enabled", true) ? "Disable animations" : "Enable animations", value: "app.toggle.animations", diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index afc6907c0f0..7d843ec4b46 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -679,15 +679,6 @@ export function Session() { dialog.clear() }, }, - { - title: bellEnabled() ? "Disable notifications" : "Enable notifications", - value: "session.toggle.bell", - category: "Session", - onSelect: (dialog) => { - setBellEnabled((prev) => !prev) - dialog.clear() - }, - }, { title: "Page up", value: "session.page.up",