claude-flow-novice 2.18.22 → 2.18.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.claude/CLAUDE.md +17 -0
  2. package/.claude/cfn-scripts/check-memory.sh +150 -0
  3. package/.claude/cfn-scripts/run-with-memory-limit.sh +91 -0
  4. package/.claude/commands/cfn-loop/cfn-loop-cli.md +9 -0
  5. package/.claude/commands/cfn-loop-task.md +11 -0
  6. package/.claude/commands/cfn-ruvector/cfn-codebase-reindex.md +23 -4
  7. package/.claude/commands/cfn-ruvector/cfn-codebase-search.md +10 -2
  8. package/.claude/commands/cfn-ruvector/cfn-detect-stale-docs.md +22 -4
  9. package/.claude/hooks/README.md +148 -148
  10. package/.claude/hooks/cfn-bash-search-hook.sh +87 -0
  11. package/.claude/hooks/cfn-smart-search-hook.sh +127 -0
  12. package/.claude/hooks/deprecated/cfn-SessionStart-cfn-load-openai-key.sh +48 -0
  13. package/.claude/hooks/post-commit-codebase-index +79 -45
  14. package/.claude/settings.json +20 -11
  15. package/.claude/skills/CLAUDE.md +70 -0
  16. package/.claude/skills/cfn-edit-safety/lib/hooks/security-scanner.sh +1 -0
  17. package/.claude/skills/cfn-local-ruvector-accelerator/SKILL.md +37 -21
  18. package/.claude/skills/cfn-local-ruvector-accelerator/cfn-integration.sh +47 -6
  19. package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/index.rs +2 -1
  20. package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/init.rs +3 -3
  21. package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/query.rs +1 -1
  22. package/.claude/skills/cfn-local-ruvector-accelerator/src/lib.rs +1 -0
  23. package/.claude/skills/cfn-local-ruvector-accelerator/src/paths.rs +4 -2
  24. package/.claude/skills/cfn-local-ruvector-accelerator/src/search_engine.rs +11 -0
  25. package/.claude/skills/cfn-local-ruvector-accelerator/test_query_api.sh +102 -102
  26. package/CLAUDE.md +63 -373
  27. package/docs/CFN_LOOP_CLI_MODE.md +134 -0
  28. package/package.json +9 -5
  29. package/scripts/cfn-init.js +8 -2
  30. package/scripts/organize-root-files.sh +340 -340
  31. package/scripts/postinstall.js +120 -3
  32. package/test-epic-creator-security.sh +202 -202
  33. package/.claude/hooks/SessionStart:cfn-build-ruvector.sh +0 -28
  34. package/.claude/hooks/SessionStart:cfn-load-openai-key.sh +0 -35
  35. /package/.claude/hooks/{SessionStart-cfn-build-ruvector.sh → cfn-SessionStart-cfn-build-ruvector.sh} +0 -0
  36. /package/.claude/hooks/{cfn-load-cerebras-env.sh → deprecated/cfn-load-cerebras-env.sh} +0 -0
@@ -1,148 +1,148 @@
1
- # Claude Code Hooks
2
-
3
- This directory contains hooks that integrate with Claude Code's lifecycle events.
4
-
5
- ## cfn-precompact-enhanced.sh
6
-
7
- Enhanced PreCompact hook that preserves context before conversation compaction (manual or auto).
8
-
9
- ### Features
10
-
11
- **Context Preservation:**
12
- - Captures current git state (branch, status, recent commits)
13
- - Saves uncommitted and staged changes
14
- - Records modified files
15
-
16
- **Session Metrics:**
17
- - Counts recently edited files
18
- - Estimates session duration from git history
19
- - Detects test execution and status
20
- - Tracks tool usage (if transcript available)
21
- - Approximates token usage
22
-
23
- **CFN-Specific Detection:**
24
- - Active CFN Loop tasks
25
- - Running CFN Docker containers
26
- - Redis coordination state
27
- - Recent pre-edit backups
28
-
29
- **Output:**
30
- - Prints structured summary to stdout (injected into Claude's context)
31
- - Saves detailed JSON log to `.artifacts/precompact/session-{timestamp}.json`
32
- - Includes CLAUDE.md reminders for best practices
33
-
34
- ### Configuration
35
-
36
- The hook is configured in `.claude/settings.json`:
37
-
38
- ```json
39
- {
40
- "hooks": {
41
- "PreCompact": [
42
- {
43
- "matcher": "manual",
44
- "hooks": [
45
- {
46
- "type": "command",
47
- "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
48
- }
49
- ]
50
- },
51
- {
52
- "matcher": "auto",
53
- "hooks": [
54
- {
55
- "type": "command",
56
- "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
57
- }
58
- ]
59
- }
60
- ]
61
- }
62
- }
63
- ```
64
-
65
- ### Performance
66
-
67
- - **Timeout Protection**: 9-second overall script timeout
68
- - **Non-Blocking**: Always exits with code 0
69
- - **Optimized for WSL2**: Limits `find` depth and targets specific directories
70
- - **Graceful Degradation**: Continues if git/jq unavailable
71
-
72
- ### Testing
73
-
74
- ```bash
75
- # Test without stdin
76
- ./.claude/hooks/cfn-precompact-enhanced.sh
77
-
78
- # Test with simulated input
79
- echo '{"type": "manual", "compact_type": "manual"}' | \
80
- CLAUDE_PROJECT_DIR=$(pwd) bash .claude/hooks/cfn-precompact-enhanced.sh
81
- ```
82
-
83
- ### Output Example
84
-
85
- ```
86
- === PRE-COMPACT CONTEXT PRESERVATION ===
87
-
88
- Compact Type: manual
89
- Timestamp: 2025-12-10 04:46:26
90
-
91
- Git State:
92
- Branch: feature/auth-system
93
- Uncommitted: 3 files
94
- Modified: 2 files
95
- Staged: 1 files
96
- Last commit: abc123 - "Add JWT validation" (2 hours ago)
97
-
98
- Session Summary:
99
- Recent file edits: 5
100
- Duration: 45 minutes
101
- Tests run: true
102
- Test status: passing
103
- Tools used: 12 (Bash: 8, Edit: 4)
104
- Approx tokens: ~800
105
-
106
- Key Context:
107
- - Working directory: /path/to/project
108
- - Uncommitted changes
109
- - 2 CFN container(s) running
110
-
111
- Full context saved to: .artifacts/precompact/session-1765370786.json
112
-
113
- === CLAUDE.md REMINDERS ===
114
- • Use CFN Loop for multi-step tasks
115
- • Batch operations in single messages
116
- • Pre-edit backup required before edits
117
- • Run tests before commits
118
- • Use service names in Docker networks
119
- ```
120
-
121
- ### Artifacts
122
-
123
- Session data is preserved in:
124
- - `.artifacts/precompact/session-{timestamp}.json` - Full JSON context
125
- - `.artifacts/precompact/{timestamp}-git.diff` - Git diff (if changes exist)
126
- - `.artifacts/precompact/{timestamp}-commits.txt` - Recent commit history
127
- - `.artifacts/precompact/backup-{todo-file}-{timestamp}` - Copied todo files
128
-
129
- ### Environment Variables
130
-
131
- - `CLAUDE_PROJECT_DIR` - Project root (defaults to `pwd`)
132
- - `TRANSCRIPT_PATH` - Path to conversation transcript (optional, for tool usage stats)
133
- - `INPUT` - JSON input from Claude Code (compact_type, custom_instructions)
134
-
135
- ### Troubleshooting
136
-
137
- **Hook times out:**
138
- - Check if running on Windows mount (should be Linux filesystem)
139
- - Verify timeout settings in script (default 9 seconds)
140
- - Reduce `find` depth or target fewer directories
141
-
142
- **No JSON output:**
143
- - Ensure `.artifacts/precompact/` directory exists
144
- - Check for `jq` availability (gracefully degrades if missing)
145
-
146
- **Line ending issues:**
147
- - Convert to Unix line endings: `dos2unix .claude/hooks/cfn-precompact-enhanced.sh`
148
- - Or use: `sed -i 's/\r$//' .claude/hooks/cfn-precompact-enhanced.sh`
1
+ # Claude Code Hooks
2
+
3
+ This directory contains hooks that integrate with Claude Code's lifecycle events.
4
+
5
+ ## cfn-precompact-enhanced.sh
6
+
7
+ Enhanced PreCompact hook that preserves context before conversation compaction (manual or auto).
8
+
9
+ ### Features
10
+
11
+ **Context Preservation:**
12
+ - Captures current git state (branch, status, recent commits)
13
+ - Saves uncommitted and staged changes
14
+ - Records modified files
15
+
16
+ **Session Metrics:**
17
+ - Counts recently edited files
18
+ - Estimates session duration from git history
19
+ - Detects test execution and status
20
+ - Tracks tool usage (if transcript available)
21
+ - Approximates token usage
22
+
23
+ **CFN-Specific Detection:**
24
+ - Active CFN Loop tasks
25
+ - Running CFN Docker containers
26
+ - Redis coordination state
27
+ - Recent pre-edit backups
28
+
29
+ **Output:**
30
+ - Prints structured summary to stdout (injected into Claude's context)
31
+ - Saves detailed JSON log to `.artifacts/precompact/session-{timestamp}.json`
32
+ - Includes CLAUDE.md reminders for best practices
33
+
34
+ ### Configuration
35
+
36
+ The hook is configured in `.claude/settings.json`:
37
+
38
+ ```json
39
+ {
40
+ "hooks": {
41
+ "PreCompact": [
42
+ {
43
+ "matcher": "manual",
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "matcher": "auto",
53
+ "hooks": [
54
+ {
55
+ "type": "command",
56
+ "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
57
+ }
58
+ ]
59
+ }
60
+ ]
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Performance
66
+
67
+ - **Timeout Protection**: 9-second overall script timeout
68
+ - **Non-Blocking**: Always exits with code 0
69
+ - **Optimized for WSL2**: Limits `find` depth and targets specific directories
70
+ - **Graceful Degradation**: Continues if git/jq unavailable
71
+
72
+ ### Testing
73
+
74
+ ```bash
75
+ # Test without stdin
76
+ ./.claude/hooks/cfn-precompact-enhanced.sh
77
+
78
+ # Test with simulated input
79
+ echo '{"type": "manual", "compact_type": "manual"}' | \
80
+ CLAUDE_PROJECT_DIR=$(pwd) bash .claude/hooks/cfn-precompact-enhanced.sh
81
+ ```
82
+
83
+ ### Output Example
84
+
85
+ ```
86
+ === PRE-COMPACT CONTEXT PRESERVATION ===
87
+
88
+ Compact Type: manual
89
+ Timestamp: 2025-12-10 04:46:26
90
+
91
+ Git State:
92
+ Branch: feature/auth-system
93
+ Uncommitted: 3 files
94
+ Modified: 2 files
95
+ Staged: 1 files
96
+ Last commit: abc123 - "Add JWT validation" (2 hours ago)
97
+
98
+ Session Summary:
99
+ Recent file edits: 5
100
+ Duration: 45 minutes
101
+ Tests run: true
102
+ Test status: passing
103
+ Tools used: 12 (Bash: 8, Edit: 4)
104
+ Approx tokens: ~800
105
+
106
+ Key Context:
107
+ - Working directory: /path/to/project
108
+ - Uncommitted changes
109
+ - 2 CFN container(s) running
110
+
111
+ Full context saved to: .artifacts/precompact/session-1765370786.json
112
+
113
+ === CLAUDE.md REMINDERS ===
114
+ • Use CFN Loop for multi-step tasks
115
+ • Batch operations in single messages
116
+ • Pre-edit backup required before edits
117
+ • Run tests before commits
118
+ • Use service names in Docker networks
119
+ ```
120
+
121
+ ### Artifacts
122
+
123
+ Session data is preserved in:
124
+ - `.artifacts/precompact/session-{timestamp}.json` - Full JSON context
125
+ - `.artifacts/precompact/{timestamp}-git.diff` - Git diff (if changes exist)
126
+ - `.artifacts/precompact/{timestamp}-commits.txt` - Recent commit history
127
+ - `.artifacts/precompact/backup-{todo-file}-{timestamp}` - Copied todo files
128
+
129
+ ### Environment Variables
130
+
131
+ - `CLAUDE_PROJECT_DIR` - Project root (defaults to `pwd`)
132
+ - `TRANSCRIPT_PATH` - Path to conversation transcript (optional, for tool usage stats)
133
+ - `INPUT` - JSON input from Claude Code (compact_type, custom_instructions)
134
+
135
+ ### Troubleshooting
136
+
137
+ **Hook times out:**
138
+ - Check if running on Windows mount (should be Linux filesystem)
139
+ - Verify timeout settings in script (default 9 seconds)
140
+ - Reduce `find` depth or target fewer directories
141
+
142
+ **No JSON output:**
143
+ - Ensure `.artifacts/precompact/` directory exists
144
+ - Check for `jq` availability (gracefully degrades if missing)
145
+
146
+ **Line ending issues:**
147
+ - Convert to Unix line endings: `dos2unix .claude/hooks/cfn-precompact-enhanced.sh`
148
+ - Or use: `sed -i 's/\r$//' .claude/hooks/cfn-precompact-enhanced.sh`
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ INPUT=$(timeout 1 cat || echo "{}")
5
+ CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
6
+
7
+ log() { echo "[$(date '+%H:%M:%S')] $*" >> /tmp/ruvector-bash-hook.log; }
8
+
9
+ # Load API key from .env if not set
10
+ load_api_key() {
11
+ if [[ -n "${OPENAI_API_KEY:-}" ]] && [[ "${OPENAI_API_KEY:-}" != "your_"* ]]; then
12
+ return 0
13
+ fi
14
+ local env_file="${CLAUDE_PROJECT_DIR:-.}/.env"
15
+ if [[ -f "$env_file" ]]; then
16
+ local key=$(grep "^OPENAI_API_KEY=" "$env_file" 2>/dev/null | cut -d= -f2- | tr -d '"' | tr -d "'" || true)
17
+ if [[ -n "$key" ]] && [[ "$key" != "your_"* ]]; then
18
+ export OPENAI_API_KEY="$key"
19
+ return 0
20
+ fi
21
+ fi
22
+ return 1
23
+ }
24
+
25
+ log "Bash hook: $CMD"
26
+
27
+ if echo "$CMD" | grep -qE "find\s+/mnt/c"; then
28
+ echo "🔴 BLOCKED: find on /mnt/c forbidden (memory leak). Use Glob tool instead." >&2
29
+ exit 2
30
+ fi
31
+
32
+ if ! echo "$CMD" | grep -qiE "^\s*(grep|rg|find)\s|[|&;]\s*(grep|rg|find)\s"; then
33
+ exit 0
34
+ fi
35
+
36
+ PATTERN=""
37
+
38
+ PATTERN=$(echo "$CMD" | grep -oE '(grep|rg)\s+[^|]+' | grep -oE '"[^"]+"' | head -1 | tr -d '"' || true)
39
+
40
+ if [ -z "$PATTERN" ]; then
41
+ PATTERN=$(echo "$CMD" | grep -oE "(grep|rg)\s+(-[a-zA-Z]+\s+)*([a-zA-Z_][a-zA-Z0-9_]*)" | awk '{print $NF}' || true)
42
+ fi
43
+
44
+ if [ -z "$PATTERN" ]; then
45
+ PATTERN=$(echo "$CMD" | grep -oE '\-name\s+"[^"]+"' | sed 's/-name\s*"//' | tr -d '"' || true)
46
+ fi
47
+
48
+ if [ -z "$PATTERN" ] || [ ${#PATTERN} -lt 3 ] || [[ "$PATTERN" == -* ]]; then
49
+ exit 0
50
+ fi
51
+
52
+ DB_PATH="$HOME/.local/share/ruvector/index_v2.db"
53
+ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
54
+
55
+ CONTEXT=""
56
+
57
+ # Try SQL first (fast, no API key)
58
+ if [ -f "$DB_PATH" ]; then
59
+ SAFE_PATTERN=$(echo "$PATTERN" | sed "s/'/''/g")
60
+ SAFE_ROOT=$(echo "$PROJECT_ROOT" | sed "s/'/''/g")
61
+
62
+ RESULTS=$(timeout 3 sqlite3 -separator ':' "$DB_PATH" \
63
+ "SELECT REPLACE(file_path, '$SAFE_ROOT/', ''), line_number, name FROM entities WHERE project_root = '$SAFE_ROOT' AND (name LIKE '%${SAFE_PATTERN}%' OR file_path LIKE '%${SAFE_PATTERN}%') LIMIT 6" 2>/dev/null || true)
64
+
65
+ if [ -n "$RESULTS" ]; then
66
+ CONTEXT="RuVector indexed matches for '$PATTERN':\n$RESULTS"
67
+ log "SQL context injected for: $PATTERN"
68
+ fi
69
+ fi
70
+
71
+ # Fallback to semantic search if SQL found nothing
72
+ if [ -z "$CONTEXT" ] && command -v local-ruvector >/dev/null 2>&1; then
73
+ if load_api_key; then
74
+ log "SQL returned nothing, trying semantic search for: $PATTERN"
75
+ SEMANTIC=$(timeout 5 local-ruvector query "$PATTERN" --max-results 5 --threshold 0.3 2>/dev/null | sed 's/\x1b\[[0-9;]*m//g' | grep -v "^$" | grep -v "INFO\|ERROR\|WARN" | head -6 || true)
76
+ if [ -n "$SEMANTIC" ]; then
77
+ CONTEXT="RuVector semantic matches for '$PATTERN':\n$SEMANTIC"
78
+ log "Semantic context injected for: $PATTERN"
79
+ fi
80
+ fi
81
+ fi
82
+
83
+ if [ -n "$CONTEXT" ]; then
84
+ echo "{\"additionalContext\":\"$CONTEXT\"}"
85
+ fi
86
+
87
+ exit 0
@@ -0,0 +1,127 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ exec 2>/tmp/ruvector-search-hook.log
4
+
5
+ INPUT=$(timeout 1 cat || echo "{}")
6
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
7
+ PATTERN=$(echo "$INPUT" | jq -r '.tool_input.pattern // empty')
8
+
9
+ log() {
10
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> /tmp/ruvector-search-hook.log
11
+ }
12
+
13
+ # Load API key from .env if not set
14
+ load_api_key() {
15
+ if [[ -n "${OPENAI_API_KEY:-}" ]] && [[ "${OPENAI_API_KEY:-}" != "your_"* ]]; then
16
+ return 0
17
+ fi
18
+ local env_file="${CLAUDE_PROJECT_DIR:-.}/.env"
19
+ if [[ -f "$env_file" ]]; then
20
+ local key=$(grep "^OPENAI_API_KEY=" "$env_file" 2>/dev/null | cut -d= -f2- | tr -d '"' | tr -d "'" || true)
21
+ if [[ -n "$key" ]] && [[ "$key" != "your_"* ]]; then
22
+ export OPENAI_API_KEY="$key"
23
+ log "Loaded OPENAI_API_KEY from .env"
24
+ return 0
25
+ fi
26
+ fi
27
+ return 1
28
+ }
29
+
30
+ log "Hook triggered: tool=$TOOL_NAME pattern='$PATTERN'"
31
+
32
+ # Skip if no pattern or tool not Grep/Glob
33
+ if [[ -z "$PATTERN" || -z "$TOOL_NAME" ]]; then
34
+ log "Missing pattern or tool name, exiting"
35
+ exit 0
36
+ fi
37
+
38
+ # Skip conditions
39
+ if [[ ${#PATTERN} -lt 3 ]]; then
40
+ log "Pattern too short, skipping"
41
+ exit 0
42
+ fi
43
+
44
+ # Skip glob patterns (file discovery, not semantic)
45
+ if [[ "$PATTERN" == *"*"* ]] || [[ "$PATTERN" == *"?"* ]] || [[ "$PATTERN" == *"["* ]]; then
46
+ log "Pattern looks like glob, skipping"
47
+ exit 0
48
+ fi
49
+
50
+ # Skip exact paths (contains / and . extension)
51
+ if [[ "$PATTERN" == *"/"* ]] && [[ "$PATTERN" == *"."* ]]; then
52
+ log "Pattern looks like exact path, skipping"
53
+ exit 0
54
+ fi
55
+
56
+ CONTEXT=""
57
+ UNCOMMITTED=""
58
+
59
+ # Check uncommitted files
60
+ if command -v git >/dev/null 2>&1; then
61
+ UNCOMMITTED=$(timeout 2 git diff --name-only HEAD 2>/dev/null | grep -i "$PATTERN" || true)
62
+ if [[ -n "$UNCOMMITTED" ]]; then
63
+ log "Found uncommitted matches"
64
+ CONTEXT="Uncommitted files matching pattern:
65
+ $UNCOMMITTED
66
+
67
+ "
68
+ fi
69
+ fi
70
+
71
+ # Query RuVector V2 SQL first (no API key needed)
72
+ RUVECTOR_RESULTS=""
73
+ DB_PATH="$HOME/.local/share/ruvector/index_v2.db"
74
+ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
75
+ if [[ -f "$DB_PATH" ]]; then
76
+ log "Querying RuVector SQL for: $PATTERN (project: $PROJECT_ROOT)"
77
+ # Escape pattern for SQL LIKE
78
+ SAFE_PATTERN=$(echo "$PATTERN" | sed "s/'/''/g")
79
+ SAFE_ROOT=$(echo "$PROJECT_ROOT" | sed "s/'/''/g")
80
+ RUVECTOR_RESULTS=$(timeout 3 sqlite3 -separator ':' "$DB_PATH" \
81
+ "SELECT REPLACE(file_path, '$SAFE_ROOT/', ''), line_number, name FROM entities WHERE project_root = '$SAFE_ROOT' AND (name LIKE '%${SAFE_PATTERN}%' OR file_path LIKE '%${SAFE_PATTERN}%') LIMIT 8" 2>/dev/null | head -10 || true)
82
+ if [[ -n "$RUVECTOR_RESULTS" ]]; then
83
+ log "RuVector SQL returned results"
84
+ CONTEXT="${CONTEXT}RuVector indexed matches for '$PATTERN':
85
+ $RUVECTOR_RESULTS
86
+
87
+ "
88
+ fi
89
+ else
90
+ log "RuVector index not found at $DB_PATH"
91
+ fi
92
+
93
+ # Fallback to semantic search if SQL found nothing and API key available
94
+ if [[ -z "$RUVECTOR_RESULTS" ]] && command -v local-ruvector >/dev/null 2>&1; then
95
+ if load_api_key; then
96
+ log "SQL returned nothing, trying semantic search for: $PATTERN"
97
+ # Strip ANSI codes from output
98
+ SEMANTIC_RESULTS=$(timeout 5 local-ruvector query "$PATTERN" --max-results 5 --threshold 0.3 2>/dev/null | sed 's/\x1b\[[0-9;]*m//g' | grep -v "^$" | grep -v "INFO\|ERROR\|WARN" | head -8 || true)
99
+ if [[ -n "$SEMANTIC_RESULTS" ]]; then
100
+ log "Semantic search returned results"
101
+ CONTEXT="${CONTEXT}RuVector semantic matches for '$PATTERN':
102
+ $SEMANTIC_RESULTS
103
+
104
+ "
105
+ else
106
+ log "Semantic search returned no results"
107
+ fi
108
+ else
109
+ log "No API key available for semantic search"
110
+ fi
111
+ fi
112
+
113
+ # Output context if we have any
114
+ if [[ -n "$CONTEXT" ]]; then
115
+ # Try JSON output first
116
+ if command -v jq >/dev/null 2>&1; then
117
+ echo "$INPUT" | jq --arg context "$CONTEXT" '. + {additionalContext: $context}'
118
+ else
119
+ # Fallback to plain text
120
+ echo "$CONTEXT"
121
+ fi
122
+ log "Context injected successfully"
123
+ else
124
+ log "No additional context found"
125
+ fi
126
+
127
+ exit 0
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+
3
+ # SessionStart hook: Load OpenAI API key from root .env file
4
+ # This ensures OPENAI_API_KEY is available for embedding generation
5
+ #
6
+ # IMPORTANT: SessionStart hooks must write to CLAUDE_ENV_FILE to set env vars.
7
+ # JSON output and 'export' do NOT work - only CLAUDE_ENV_FILE persists.
8
+
9
+ set -e
10
+
11
+ # Path to root .env file
12
+ ROOT_ENV="${PROJECT_ROOT:-.}/.env"
13
+
14
+ # Check if CLAUDE_ENV_FILE is available (only in SessionStart hooks)
15
+ if [[ -z "$CLAUDE_ENV_FILE" ]]; then
16
+ echo "⚠️ CLAUDE_ENV_FILE not set - not running as SessionStart hook" >&2
17
+ exit 0
18
+ fi
19
+
20
+ # Check if .env exists
21
+ if [[ ! -f "$ROOT_ENV" ]]; then
22
+ echo "⚠️ Warning: $ROOT_ENV not found. OpenAI embeddings will not work." >&2
23
+ exit 0
24
+ fi
25
+
26
+ # Extract OPENAI_API_KEY from .env
27
+ if grep -q "^OPENAI_API_KEY=" "$ROOT_ENV"; then
28
+ OPENAI_KEY=$(grep "^OPENAI_API_KEY=" "$ROOT_ENV" | cut -d'=' -f2- | tr -d '"' | tr -d "'")
29
+
30
+ # Validate key format
31
+ if [[ -z "$OPENAI_KEY" ]]; then
32
+ echo "⚠️ Warning: OPENAI_API_KEY found but empty in $ROOT_ENV" >&2
33
+ exit 0
34
+ fi
35
+
36
+ if [[ ! "$OPENAI_KEY" =~ ^sk- ]]; then
37
+ echo "⚠️ Warning: OPENAI_API_KEY invalid format (must start with 'sk-')" >&2
38
+ exit 0
39
+ fi
40
+
41
+ # Write to CLAUDE_ENV_FILE - this is how SessionStart hooks set env vars
42
+ echo "export OPENAI_API_KEY=\"$OPENAI_KEY\"" >> "$CLAUDE_ENV_FILE"
43
+ echo "✅ Loaded OPENAI_API_KEY from .env (${OPENAI_KEY:0:10}...)" >&2
44
+ else
45
+ echo "⚠️ Warning: OPENAI_API_KEY not found in $ROOT_ENV. OpenAI embeddings will not work." >&2
46
+ fi
47
+
48
+ exit 0