Skip to content

fix(claude): stop project SessionStart hook from firing at user scope - #65

Merged
dijonkitchen merged 1 commit into
mainfrom
fix/claude-user-scope-hook-leak
Jun 8, 2026
Merged

fix(claude): stop project SessionStart hook from firing at user scope#65
dijonkitchen merged 1 commit into
mainfrom
fix/claude-user-scope-hook-leak

Conversation

@dijonkitchen

Copy link
Copy Markdown
Owner

Problem

dotfiles/.claude/settings.json did double duty: it was both the dotfiles repo's project settings and, via link-agents.sh, the user/global settings symlinked to ~/.claude/settings.json.

Because the user-scope copy carried a SessionStart hook pointing at the project-relative $CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh, that hook fired in every project and errored in any repo that doesn't ship the script:

/Users/.../dp_customer_data_exchange/.claude/hooks/session-start.sh: No such file or directory

Fix

Split the two roles:

  • .claude/settings.global.json (new) — universal user-scope prefs (permissions, statusLine, editorMode, worktree, verbose), no project-relative paths. link-agents.sh now links this into ~/.claude/settings.json.
  • .claude/settings.json — trimmed to just the SessionStart bootstrap hook; read only as the dotfiles repo's project settings.

Web bootstrap is unchanged: opening the repo still fires the project hook, which runs link-agents.sh.

Result across contexts

  • Local — prefs apply everywhere via user scope; the project hook no-ops locally (CLAUDE_CODE_REMOTE != true). No more error in other repos.
  • Global~/.claude/settings.json is purely universal prefs, zero project paths.
  • Claude Code web — unchanged; project hook fires and materializes globals into ~/.claude.

Tests

  • bats tests/link-agents.bats → 6/6 pass, including a new test asserting the global link resolves to settings.global.json and that global has no CLAUDE_PROJECT_DIR while project keeps the hook.
  • shellcheck clean.
  • Pre-existing bootstrap.bats failures (mise ... not trusted in the sandbox) are unrelated — confirmed identical on a clean tree.

🤖 Generated with Claude Code

The dotfiles .claude/settings.json served two roles: the dotfiles repo's
project settings AND, via link-agents.sh, the user-scope settings symlinked
to ~/.claude/settings.json. Because the user-scope copy carried a
SessionStart hook pointing at the project-relative
$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh, that hook fired in every
project and errored in any repo lacking that script.

Split the roles: settings.global.json holds the universal user-scope prefs
(no project-relative paths) and is what link-agents.sh now links into
~/.claude; settings.json keeps only the SessionStart bootstrap hook and is
read solely as the dotfiles repo's project settings. Web bootstrap is
unchanged -- opening the repo still fires the hook, which runs link-agents.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dijonkitchen
dijonkitchen force-pushed the fix/claude-user-scope-hook-leak branch from 8fb2572 to e5fd39b Compare June 8, 2026 14:57
@dijonkitchen
dijonkitchen merged commit d09cdab into main Jun 8, 2026
3 checks passed
@dijonkitchen
dijonkitchen deleted the fix/claude-user-scope-hook-leak branch June 8, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant