authorgravatar for 153842990+yashranaway@users.noreply.github.comAditya Garud <153842990+yashranaway@users.noreply.github.com> 2026-08-15 17:46:44+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-15 12:16:44+00:00
logdb02c6b9c9d5714ae3d519328cdd68c746f4cbad
tree75a1ac13d817846f47e32711d19dc51de7cb6c15
parent21b6fb528d6b2d3b3e333b2bd4455d6cdf7d7a41
signature Signed by PGP key B5690EEEBB952194

Skip user hooks during Claude capability probes (#4466)


2 files changed, 13 insertions(+), 0 deletions(-)

apps/server/src/provider/Layers/ClaudeCapabilitiesProbe.test.ts+9
...@@ -46,6 +46,7 @@ it("isolates Claude capability probes without dropping workspace setting sources...@@ -46,6 +46,7 @@ it("isolates Claude capability probes without dropping workspace setting sources
46 assert.equal(options.strictMcpConfig, true);46 assert.equal(options.strictMcpConfig, true);
47 assert.equal(options.cwd, "/workspace/project");47 assert.equal(options.cwd, "/workspace/project");
48 assert.deepEqual(options.settingSources, [...CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES]);48 assert.deepEqual(options.settingSources, [...CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES]);
49 assert.deepEqual(options.settings, { disableAllHooks: true });
49 assert.deepEqual(options.allowedTools, []);50 assert.deepEqual(options.allowedTools, []);
50 assert.equal(options.persistSession, false);51 assert.equal(options.persistSession, false);
51 assert.equal(options.pathToClaudeCodeExecutable, "/usr/bin/claude");52 assert.equal(options.pathToClaudeCodeExecutable, "/usr/bin/claude");
...@@ -149,6 +150,14 @@ it.layer(NodeServices.layer)("Claude capability probe SDK boundary", (it) => {...@@ -149,6 +150,14 @@ it.layer(NodeServices.layer)("Claude capability probe SDK boundary", (it) => {
149 assert.equal(invocation.mcpConfig, undefined);150 assert.equal(invocation.mcpConfig, undefined);
150151
151 assert.equal(invocation.args.includes("--setting-sources=user,project,local"), true);152 assert.equal(invocation.args.includes("--setting-sources=user,project,local"), true);
153
154 const settingsFlagIndex = invocation.args.indexOf("--settings");
155 assert.notEqual(settingsFlagIndex, -1);
156 // @effect-diagnostics-next-line preferSchemaOverJson:off
157 const flagSettings = JSON.parse(invocation.args[settingsFlagIndex + 1] ?? "{}") as {
158 readonly disableAllHooks?: boolean;
159 };
160 assert.equal(flagSettings.disableAllHooks, true);
152 }).pipe(Effect.scoped),161 }).pipe(Effect.scoped),
153 );162 );
154});163});
apps/server/src/provider/Layers/ClaudeProvider.ts+4
...@@ -594,6 +594,10 @@ export function buildClaudeCapabilitiesProbeQueryOptions(input: {...@@ -594,6 +594,10 @@ export function buildClaudeCapabilitiesProbeQueryOptions(input: {
594 pathToClaudeCodeExecutable: input.executablePath,594 pathToClaudeCodeExecutable: input.executablePath,
595 abortController: input.abortController,595 abortController: input.abortController,
596 settingSources: [...CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES],596 settingSources: [...CLAUDE_CAPABILITIES_PROBE_SETTING_SOURCES],
597 // The probe keeps filesystem setting sources for slash-command discovery,
598 // but must not run the user's hooks: it fires every few minutes, so
599 // SessionStart hooks would run on every health check.
600 settings: { disableAllHooks: true },
597 allowedTools: [],601 allowedTools: [],
598 // Ignore MCP definitions from every filesystem setting source above. The602 // Ignore MCP definitions from every filesystem setting source above. The
599 // SDK combines this empty explicit map with --strict-mcp-config.603 // SDK combines this empty explicit map with --strict-mcp-config.