diff --git a/docs/bash-tool-runtime.md b/docs/bash-tool-runtime.md index 01d9bb2ce..89014abe5 100644 --- a/docs/bash-tool-runtime.md +++ b/docs/bash-tool-runtime.md @@ -16,6 +16,8 @@ There are two different bash execution surfaces in coding-agent: Both eventually use `executeBash()` in `src/exec/bash-executor.ts` for non-PTY execution, but only the tool-call path runs normalization/interception, optional managed background-job handling, and tool renderer logic. +Set `bash.enabled: false` in settings to remove the model-facing `bash` tool from the active tool registry. This does not disable user-initiated bang commands or RPC `bash` requests. + ## End-to-end tool-call pipeline ## 1) Input handling and parameter merge diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 6d813b0b1..a3e29be34 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- Added a `bash.enabled` setting to disable the model-facing bash tool while leaving user-initiated bang/RPC bash commands available. + ## [15.10.7] - 2026-06-08 ### Fixed diff --git a/packages/coding-agent/src/config/settings-schema.ts b/packages/coding-agent/src/config/settings-schema.ts index 664488632..3b55518ce 100644 --- a/packages/coding-agent/src/config/settings-schema.ts +++ b/packages/coding-agent/src/config/settings-schema.ts @@ -2187,6 +2187,12 @@ export const SETTINGS_SCHEMA = { }, }, + "bash.enabled": { + type: "boolean", + default: true, + ui: { tab: "tools", label: "Bash", description: "Enable the bash tool for shell command execution" }, + }, + // Search and AST tools "find.enabled": { type: "boolean", diff --git a/packages/coding-agent/src/tools/index.ts b/packages/coding-agent/src/tools/index.ts index 2fb7d797f..944c764fe 100644 --- a/packages/coding-agent/src/tools/index.ts +++ b/packages/coding-agent/src/tools/index.ts @@ -492,7 +492,7 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P const isToolAllowed = (name: string) => { if (name === "goal") return goalEnabled && goalModeActive; if (name === "lsp") return enableLsp && session.settings.get("lsp.enabled"); - if (name === "bash") return true; + if (name === "bash") return session.settings.get("bash.enabled"); if (name === "eval") return allowEval; if (name === "debug") return session.settings.get("debug.enabled"); if (name === "todo") return !includeYield && session.settings.get("todo.enabled"); diff --git a/packages/coding-agent/test/tools/index.test.ts b/packages/coding-agent/test/tools/index.test.ts index bb1da3042..ffd1754cb 100644 --- a/packages/coding-agent/test/tools/index.test.ts +++ b/packages/coding-agent/test/tools/index.test.ts @@ -202,6 +202,7 @@ describe("createTools", () => { "astGrep.enabled": false, "astEdit.enabled": false, "renderMermaid.enabled": false, + "bash.enabled": false, "web_search.enabled": false, "browser.enabled": false, "inspect_image.enabled": false, @@ -210,6 +211,7 @@ describe("createTools", () => { const tools = await createTools(session); const names = tools.map(t => t.name); + expect(names).not.toContain("bash"); expect(names).not.toContain("find"); expect(names).not.toContain("search"); expect(names).not.toContain("ast_grep"); @@ -218,6 +220,9 @@ describe("createTools", () => { expect(names).not.toContain("web_search"); expect(names).not.toContain("browser"); expect(names).not.toContain("inspect_image"); + + const requestedTools = await createTools(session, ["bash", "read"]); + expect(requestedTools.map(t => t.name)).toEqual(["read", "resolve"]); }); it("always includes resolve regardless of plan-mode setting", async () => {