codeflash-agent/plugin/hooks/session-start.sh
Kevin Turcios cc29a27289
Migrate .codeflash/ to {teammember}/{org}/{project}/ format (#15)
Add team member dimension to case study paths so multiple contributors
can track optimization data independently. Derives member from
git config user.name in session-start hooks.

- Move all case studies under .codeflash/krrt7/
- Rename pypa/pip → python/pip (org grouping)
- Update session-start hooks, docs, scripts, and references
2026-04-14 23:04:34 -05:00

92 lines
3 KiB
Bash
Executable file

#!/usr/bin/env bash
# Plugin SessionStart hook: Set up .codeflash/ session directory.
#
# Two modes:
# Dogfood: Plugin loaded from codeflash-agent/dist/ (--plugin-dir).
# Redirects .codeflash/ → agent repo's .codeflash/{teammember}/{org}/{project}/ via symlink.
# Normal: Plugin installed normally.
# Creates .codeflash/ in the project directory.
cd "$CLAUDE_PROJECT_DIR" 2>/dev/null || exit 0
# Parse org/project from git remote
REMOTE=$(git remote get-url origin 2>/dev/null)
[ -z "$REMOTE" ] && exit 0
PATH_PART=""
if echo "$REMOTE" | grep -qE '^git@'; then
PATH_PART=$(echo "$REMOTE" | sed -E 's/^git@[^:]*://' | sed 's/\.git$//')
elif echo "$REMOTE" | grep -qE '^https?://'; then
PATH_PART=$(echo "$REMOTE" | sed -E 's|^https?://[^/]*/||' | sed 's/\.git$//')
elif echo "$REMOTE" | grep -qE '^ssh://'; then
PATH_PART=$(echo "$REMOTE" | sed -E 's|^ssh://[^/]*/||' | sed 's/\.git$//')
fi
ORG=$(echo "$PATH_PART" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]')
PROJECT=$(echo "$PATH_PART" | cut -d'/' -f2 | tr '[:upper:]' '[:lower:]')
[ -z "$ORG" ] || [ -z "$PROJECT" ] && exit 0
# Derive team member from git user (lowercase, no spaces)
MEMBER=$(git config user.name 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
[ -z "$MEMBER" ] && MEMBER="unknown"
# Detect dogfood mode: CLAUDE_PLUGIN_ROOT's parent has .codeflash/ (the agent repo)
AGENT_REPO=""
if [ -n "$CLAUDE_PLUGIN_ROOT" ]; then
CANDIDATE=$(cd "$CLAUDE_PLUGIN_ROOT/.." 2>/dev/null && pwd)
if [ -d "$CANDIDATE/.codeflash" ]; then
AGENT_REPO="$CANDIDATE"
fi
fi
if [ -n "$AGENT_REPO" ]; then
# --- Dogfood mode ---
TARGET="$AGENT_REPO/.codeflash/$MEMBER/$ORG/$PROJECT"
mkdir -p "$TARGET"
if [ ! -e "$CLAUDE_PROJECT_DIR/.codeflash" ]; then
# No .codeflash yet — create symlink
ln -s "$TARGET" "$CLAUDE_PROJECT_DIR/.codeflash"
elif [ -L "$CLAUDE_PROJECT_DIR/.codeflash" ]; then
# Already a symlink — verify it points to the right place
CURRENT=$(readlink "$CLAUDE_PROJECT_DIR/.codeflash")
if [ "$CURRENT" != "$TARGET" ]; then
rm "$CLAUDE_PROJECT_DIR/.codeflash"
ln -s "$TARGET" "$CLAUDE_PROJECT_DIR/.codeflash"
fi
fi
# If .codeflash is a real directory, leave it alone
DATA_DIR="$TARGET"
else
# --- Normal mode ---
mkdir -p "$CLAUDE_PROJECT_DIR/.codeflash"
DATA_DIR="$CLAUDE_PROJECT_DIR/.codeflash"
fi
# Build session context from existing state
MSG=""
if [ -f "$DATA_DIR/HANDOFF.md" ]; then
MSG="Previous session state found at .codeflash/HANDOFF.md — read it before starting new work."
fi
if [ -f "$DATA_DIR/results.tsv" ]; then
LINES=$(wc -l < "$DATA_DIR/results.tsv" | tr -d ' ')
MSG="${MSG:+$MSG }Experiment history at .codeflash/results.tsv ($LINES entries)."
fi
if [ -f "$DATA_DIR/learnings.md" ]; then
MSG="${MSG:+$MSG }Learnings from previous sessions at .codeflash/learnings.md."
fi
[ -z "$MSG" ] && exit 0
cat <<EOF
{
"systemMessage": "$MSG"
}
EOF
exit 0