diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh new file mode 100755 index 000000000..59319b0c9 --- /dev/null +++ b/.claude/hooks/session-start.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# SessionStart hook: install dependencies so tests and linters work in +# Claude Code on the web sessions. Idempotent and non-interactive. +set -euo pipefail + +# Only run in the remote (Claude Code on the web) environment; local sessions +# manage their own virtualenv. +if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then + exit 0 +fi + +cd "$CLAUDE_PROJECT_DIR" + +# Install uv if it isn't already on PATH (the remote image may not ship it). +if ! command -v uv >/dev/null 2>&1; then + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.local/bin:$PATH" + echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$CLAUDE_ENV_FILE" +fi + +# --frozen installs straight from the committed uv.lock without re-resolving or +# rewriting it (mirrors CI). --all-extras pulls in the dev tools (pytest, ruff). +uv sync --all-extras --frozen diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..e06b0338e --- /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 0a6775b2a..73267c09a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,13 @@ graphify-out/ .graphify_*.json .graphify_python .claude/ +# Track the shared SessionStart hook and its settings (activates the repo for +# Claude Code on the web); keep all other local .claude/ state ignored. +!.claude/ +.claude/* +!.claude/hooks/ +!.claude/hooks/session-start.sh +!.claude/settings.json skills/ # The packaged skill bundles under graphify/skills/ are generated, committed # artifacts (rendered by tools/skillgen). Keep them tracked even though the