fix(dispatch): suppress user hooks on internal claude text-generation · Entire
fix(dispatch): suppress user hooks on internal claude text-generation
79a1cfa→main
alishakawaguchi·yesterday·2 files·+36 added/-11 removed
Loading user settings for auth (--setting-sources user) also loads any user-level claude hooks. Verified empirically that SessionStart and UserPromptSubmit hooks fire on the internal --print GenerateText call, which undercuts the os.TempDir()/StripGitEnv isolation and could error or cause side effects on every auxiliary generation.
Layer --settings {"disableAllHooks":true} over the user settings so all user hooks are suppressed while auth still resolves (verified: apiKeyHelper, ANTHROPIC_API_KEY, and keychain/subscription all still authenticate; a real subscription dispatch --local still generates). Extend the regression test to assert both flags.
Addresses trail #884 review finding.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_012QYA1kFFwDTbR8cZQQkb8N
Changes
2
cmd/entire/cli/agent/claudecode
Mclaude_test.go+21/-10
Mgenerate.go+15/-1
69 unmodified lines
...
t.Fatalf("unexpected error: %v", err) }
flagValue := func(name string) (string, bool) { for i, a := range gotArgs { if a == name && i+1 < len(gotArgs) { return gotArgs[i+1], true } } return "", false }
// The subprocess must load user settings so API-billing auth (apiKeyHelper / // ANTHROPIC_API_KEY approval in ~/.claude/settings.json) is available. // Loading no sources ("") made claude report "Not logged in" for those users. // See generate.go for the full rationale. var settingSources string found := false for i, a := range gotArgs { if a == "--setting-sources" && i+1 < len(gotArgs) { settingSources = gotArgs[i+1] found = true break } } if !found { settingSources, ok := flagValue("--setting-sources") if !ok { t.Fatalf("--setting-sources flag missing from args: %v", gotArgs) } if settingSources != settingSourcesUser { t.Fatalf("--setting-sources = %q, want %q (empty drops user auth settings)", settingSources, settingSourcesUser) } }
// Loading user settings must not let user-level hooks fire on internal // text-generation calls, so --settings disables them. settings, ok := flagValue("--settings") if !ok { t.Fatalf("--settings flag missing from args: %v", gotArgs) } if settings != disableHooksSettings { t.Fatalf("--settings = %q, want %q (must disable user hooks)", settings, disableHooksSettings) } }
func TestGenerateText_ArrayResponse(t *testing.T) {
Mcmd/entire/cli/agent/claudecode/claude_test.go+21/-10
15 unmodified lines
...
// ~/.claude/settings.json (see the rationale in GenerateText).
const settingSourcesUser = "user"
// disableHooksSettings is layered on top of the user settings via --settings so
// user-level hooks (SessionStart/UserPromptSubmit/Stop) do not fire on these
// internal --print calls (see the rationale in GenerateText).
const disableHooksSettings = {"disableAllHooks":true}
// GenerateText sends a prompt to the Claude CLI and returns the raw text response.
// Implements the agent.TextGenerator interface.
// The model parameter hints which model to use (e.g., "haiku", "sonnet").
25 unmodified lines
...
// their plain `claude -p` worked. Project/local isolation is already
// guaranteed by cmd.Dir = os.TempDir() below, so "user" restores auth
// without reintroducing repo-scoped settings.
//
// Loading user settings also brings in any user-level hooks; --settings
// {"disableAllHooks":true} layers over them so SessionStart/UserPromptSubmit/
// Stop hooks do not fire (and cannot error or cause side effects) on these
// internal text-generation calls. This preserves the isolation intent of the
// os.TempDir()/StripGitEnv setup while keeping auth working. --settings does
// not affect auth resolution (verified: keychain/credentials, ANTHROPIC_API_KEY
// and apiKeyHelper all still authenticate).
cmd := commandRunner(ctx, claudePath,
"--print", "--output-format", "json",
"--model", model, "--setting-sources", settingSourcesUser)
"--model", model, "--setting-sources", settingSourcesUser,
"--settings", disableHooksSettings)
// Isolate from the user's git repo to prevent recursive hook triggers
// and index pollution (matches agent.RunIsolatedTextGeneratorCLI behavior).