From 2b0f53b2beca1536844ec7e3f680591db4efa80e Mon Sep 17 00:00:00 2001 From: Bryan Fawcett Date: Wed, 2 Sep 2026 15:52:47 +0000 Subject: [PATCH 1/2] chore: add a SessionStart hook for Claude Code on the web MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Installs pnpm dependencies (pnpm install) at the start of a remote session so tests and linters work without a manual step. Only runs when CLAUDE_CODE_REMOTE is set, so it's a no-op locally. Carves an exception into .gitignore's blanket .claude/ exclusion for just this hook and its settings.json — everything else under .claude/ (CLAUDE.md, settings.local.json, skills) stays untracked as before. Validated: pnpm install exits 0; a lint (vp lint) and a test (vitest, nyuchi-docs-search) both pass afterwards. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KQPxAPY7KvsN9WLbdLSQED --- .claude/hooks/session-start.sh | 10 ++++++++++ .claude/settings.json | 14 ++++++++++++++ .gitignore | 6 ++++++ 3 files changed, 30 insertions(+) create mode 100755 .claude/hooks/session-start.sh create mode 100644 .claude/settings.json diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh new file mode 100755 index 0000000..e2289fa --- /dev/null +++ b/.claude/hooks/session-start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -euo pipefail + +if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then + exit 0 +fi + +cd "$CLAUDE_PROJECT_DIR" + +pnpm install diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..e06b033 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,14 @@ +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh" + } + ] + } + ] + } +} diff --git a/.gitignore b/.gitignore index ede23db..1997f3b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,5 +25,11 @@ pnpm-debug.log* # CLAUDE.md and .claude/ carry this repo's agent instructions, skills, # hooks and settings. They are deliberately untracked so `main` never # ships them; keep your own local copies for development. +# +# Exception: the SessionStart hook and its settings are tracked, so +# Claude Code on the web can install dependencies without a manual step. CLAUDE.md .claude/ +!.claude/settings.json +!.claude/hooks/ +!.claude/hooks/* From 81b24410b60be53696077bf2ad479df84a794a12 Mon Sep 17 00:00:00 2001 From: Bryan Fawcett Date: Wed, 2 Sep 2026 15:58:17 +0000 Subject: [PATCH 2/2] fix(gitignore): .claude/* instead of .claude/, so the hook exception actually works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit's !.claude/hooks/ negation was silently defeated: .claude/ (trailing slash) is a directory exclusion, and git never descends into an excluded directory to evaluate further patterns for its children. It was committed with `git add -f`, which bypasses the check and papered over the bug — any new file added under .claude/hooks/ later would have needed -f again, every time. Switched to .claude/* (glob one level, not a directory exclusion), so specific children can be re-included. Verified: `git check-ignore` now reports no match for the hook files. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KQPxAPY7KvsN9WLbdLSQED --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1997f3b..fa6e23a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,11 @@ pnpm-debug.log* # # Exception: the SessionStart hook and its settings are tracked, so # Claude Code on the web can install dependencies without a manual step. +# .claude/* (not .claude/): a trailing-slash directory exclusion stops +# git from ever descending into it, silently defeating the negations +# below. CLAUDE.md -.claude/ +.claude/* !.claude/settings.json !.claude/hooks/ !.claude/hooks/*