claude-flow-novice 2.18.22 → 2.18.23
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.
- package/.claude/cfn-scripts/check-memory.sh +150 -0
- package/.claude/cfn-scripts/run-with-memory-limit.sh +91 -0
- package/.claude/hooks/README.md +148 -148
- package/.claude/hooks/{SessionStart:cfn-load-openai-key.sh → SessionStart-cfn-load-openai-key.sh} +35 -35
- package/.claude/hooks/SessionStart:cfn-build-ruvector.sh +28 -28
- package/.claude/hooks/cfn-bash-search-hook.sh +87 -0
- package/.claude/hooks/cfn-smart-search-hook.sh +127 -0
- package/.claude/hooks/post-commit-codebase-index +79 -45
- package/.claude/settings.json +14 -3
- package/.claude/skills/cfn-edit-safety/lib/hooks/security-scanner.sh +1 -0
- package/.claude/skills/cfn-local-ruvector-accelerator/cfn-integration.sh +47 -6
- package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/index.rs +2 -1
- package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/init.rs +3 -3
- package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/query.rs +1 -1
- package/.claude/skills/cfn-local-ruvector-accelerator/src/lib.rs +1 -0
- package/.claude/skills/cfn-local-ruvector-accelerator/src/paths.rs +4 -2
- package/.claude/skills/cfn-local-ruvector-accelerator/src/search_engine.rs +11 -0
- package/.claude/skills/cfn-local-ruvector-accelerator/test_query_api.sh +102 -102
- package/CLAUDE.md +32 -4
- package/package.json +9 -5
- package/scripts/organize-root-files.sh +340 -340
- package/scripts/postinstall.js +120 -3
- package/test-epic-creator-security.sh +202 -202
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Memory Leak Prevention Script (ANTI-024)
|
|
3
|
+
# Detects and kills orphaned test processes (jest, vitest, node test runners)
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./scripts/check-memory.sh # Report only
|
|
7
|
+
# ./scripts/check-memory.sh --kill # Kill orphans
|
|
8
|
+
# ./scripts/check-memory.sh --kill 500 # Kill if total MB > 500
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
KILL_MODE=false
|
|
13
|
+
THRESHOLD_MB=0
|
|
14
|
+
|
|
15
|
+
# Parse arguments
|
|
16
|
+
while [[ $# -gt 0 ]]; do
|
|
17
|
+
case "$1" in
|
|
18
|
+
--kill)
|
|
19
|
+
KILL_MODE=true
|
|
20
|
+
shift
|
|
21
|
+
if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
|
|
22
|
+
THRESHOLD_MB="$1"
|
|
23
|
+
shift
|
|
24
|
+
fi
|
|
25
|
+
;;
|
|
26
|
+
--help|-h)
|
|
27
|
+
echo "Usage: $0 [--kill [threshold_mb]]"
|
|
28
|
+
echo " --kill Kill orphaned test processes"
|
|
29
|
+
echo " --kill 500 Only kill if total memory > 500MB"
|
|
30
|
+
exit 0
|
|
31
|
+
;;
|
|
32
|
+
*)
|
|
33
|
+
shift
|
|
34
|
+
;;
|
|
35
|
+
esac
|
|
36
|
+
done
|
|
37
|
+
|
|
38
|
+
# Find test-related processes
|
|
39
|
+
find_test_processes() {
|
|
40
|
+
# Jest, Vitest, and generic node test runners
|
|
41
|
+
pgrep -af "(jest|vitest|node.*test)" 2>/dev/null || true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Calculate memory usage of test processes (in MB)
|
|
45
|
+
get_test_memory_mb() {
|
|
46
|
+
ps aux 2>/dev/null | grep -E "(jest|vitest|node.*test)" | grep -v grep | \
|
|
47
|
+
awk '{sum+=$6} END {print int(sum/1024)}' || echo "0"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Find orphaned processes (parent PID = 1 or parent dead)
|
|
51
|
+
find_orphans() {
|
|
52
|
+
local orphans=()
|
|
53
|
+
|
|
54
|
+
while IFS= read -r line; do
|
|
55
|
+
local pid=$(echo "$line" | awk '{print $1}')
|
|
56
|
+
if [[ -z "$pid" ]]; then continue; fi
|
|
57
|
+
|
|
58
|
+
local ppid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ' || echo "")
|
|
59
|
+
if [[ -z "$ppid" ]]; then continue; fi
|
|
60
|
+
|
|
61
|
+
# Check if parent is init (1) or parent process doesn't exist
|
|
62
|
+
if [[ "$ppid" == "1" ]] || ! ps -p "$ppid" > /dev/null 2>&1; then
|
|
63
|
+
orphans+=("$pid")
|
|
64
|
+
fi
|
|
65
|
+
done < <(find_test_processes)
|
|
66
|
+
|
|
67
|
+
echo "${orphans[@]:-}"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Kill processes gracefully
|
|
71
|
+
kill_processes() {
|
|
72
|
+
local pids=("$@")
|
|
73
|
+
|
|
74
|
+
for pid in "${pids[@]}"; do
|
|
75
|
+
if [[ -z "$pid" ]]; then continue; fi
|
|
76
|
+
|
|
77
|
+
echo "Killing orphaned process: $pid"
|
|
78
|
+
|
|
79
|
+
# Try SIGTERM first
|
|
80
|
+
kill -TERM "$pid" 2>/dev/null || continue
|
|
81
|
+
|
|
82
|
+
# Wait up to 5 seconds for graceful shutdown
|
|
83
|
+
local count=0
|
|
84
|
+
while ps -p "$pid" > /dev/null 2>&1 && [[ $count -lt 5 ]]; do
|
|
85
|
+
sleep 1
|
|
86
|
+
((count++))
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
# Force kill if still running
|
|
90
|
+
if ps -p "$pid" > /dev/null 2>&1; then
|
|
91
|
+
echo "Force killing: $pid"
|
|
92
|
+
kill -KILL "$pid" 2>/dev/null || true
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Main
|
|
98
|
+
main() {
|
|
99
|
+
local total_mb=$(get_test_memory_mb)
|
|
100
|
+
local orphans=($(find_orphans))
|
|
101
|
+
local orphan_count=${#orphans[@]}
|
|
102
|
+
|
|
103
|
+
echo "=== Memory Check (ANTI-024) ==="
|
|
104
|
+
echo "Test process memory: ${total_mb}MB"
|
|
105
|
+
echo "Orphaned processes: ${orphan_count}"
|
|
106
|
+
|
|
107
|
+
if [[ $orphan_count -gt 0 ]]; then
|
|
108
|
+
echo ""
|
|
109
|
+
echo "Orphan PIDs: ${orphans[*]}"
|
|
110
|
+
|
|
111
|
+
if $KILL_MODE; then
|
|
112
|
+
if [[ $THRESHOLD_MB -gt 0 ]] && [[ $total_mb -lt $THRESHOLD_MB ]]; then
|
|
113
|
+
echo "Memory ($total_mb MB) below threshold ($THRESHOLD_MB MB), skipping kill"
|
|
114
|
+
exit 0
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
echo ""
|
|
118
|
+
echo "Killing orphaned processes..."
|
|
119
|
+
kill_processes "${orphans[@]}"
|
|
120
|
+
|
|
121
|
+
# Verify cleanup
|
|
122
|
+
sleep 1
|
|
123
|
+
local remaining=$(find_orphans | wc -w)
|
|
124
|
+
echo "Remaining orphans: $remaining"
|
|
125
|
+
|
|
126
|
+
if [[ $remaining -gt 0 ]]; then
|
|
127
|
+
echo "WARNING: Some processes could not be killed"
|
|
128
|
+
exit 1
|
|
129
|
+
fi
|
|
130
|
+
else
|
|
131
|
+
echo ""
|
|
132
|
+
echo "Run with --kill to terminate orphaned processes"
|
|
133
|
+
fi
|
|
134
|
+
else
|
|
135
|
+
echo "No orphaned test processes found"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Report current test processes
|
|
139
|
+
local running=$(find_test_processes | wc -l)
|
|
140
|
+
if [[ $running -gt 0 ]]; then
|
|
141
|
+
echo ""
|
|
142
|
+
echo "Running test processes: $running"
|
|
143
|
+
find_test_processes | head -5
|
|
144
|
+
if [[ $running -gt 5 ]]; then
|
|
145
|
+
echo "... and $((running - 5)) more"
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
main "$@"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run command with memory limit enforcement (ANTI-024)
|
|
3
|
+
# Uses systemd-run when available, falls back to ulimit
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./scripts/run-with-memory-limit.sh <memory_limit> <command...>
|
|
7
|
+
# ./scripts/run-with-memory-limit.sh 6G npm test
|
|
8
|
+
# ./scripts/run-with-memory-limit.sh 2G npm run test:unit
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
MEMORY_LIMIT="${1:-6G}"
|
|
13
|
+
shift
|
|
14
|
+
|
|
15
|
+
if [[ $# -eq 0 ]]; then
|
|
16
|
+
echo "Usage: $0 <memory_limit> <command...>"
|
|
17
|
+
echo "Example: $0 6G npm test"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Parse memory limit to bytes for ulimit fallback
|
|
22
|
+
parse_memory_to_kb() {
|
|
23
|
+
local mem="$1"
|
|
24
|
+
local num="${mem%[GgMmKk]*}"
|
|
25
|
+
local unit="${mem: -1}"
|
|
26
|
+
|
|
27
|
+
case "$unit" in
|
|
28
|
+
G|g) echo $((num * 1024 * 1024)) ;;
|
|
29
|
+
M|m) echo $((num * 1024)) ;;
|
|
30
|
+
K|k) echo "$num" ;;
|
|
31
|
+
*) echo "$mem" ;; # Assume KB if no unit
|
|
32
|
+
esac
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Check systemd availability
|
|
36
|
+
use_systemd() {
|
|
37
|
+
# Check if systemd-run exists and user session is available
|
|
38
|
+
command -v systemd-run >/dev/null 2>&1 && \
|
|
39
|
+
systemctl --user is-system-running >/dev/null 2>&1
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Check if running in WSL (systemd support varies)
|
|
43
|
+
is_wsl() {
|
|
44
|
+
grep -qi microsoft /proc/version 2>/dev/null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
echo "=== Memory-Limited Execution (ANTI-024) ==="
|
|
48
|
+
echo "Limit: $MEMORY_LIMIT"
|
|
49
|
+
echo "Command: $*"
|
|
50
|
+
echo ""
|
|
51
|
+
|
|
52
|
+
if use_systemd; then
|
|
53
|
+
echo "Using: systemd-run (cgroups v2)"
|
|
54
|
+
echo ""
|
|
55
|
+
|
|
56
|
+
# Run with systemd memory limit
|
|
57
|
+
# --user: run as current user
|
|
58
|
+
# --scope: transient scope (not a service)
|
|
59
|
+
# -p MemoryMax: hard memory limit
|
|
60
|
+
# -p MemorySwapMax=0: disable swap so OOM killer triggers at limit
|
|
61
|
+
exec systemd-run --user --scope \
|
|
62
|
+
-p MemoryMax="$MEMORY_LIMIT" \
|
|
63
|
+
-p MemorySwapMax=0 \
|
|
64
|
+
--description="CFN test run with memory limit" \
|
|
65
|
+
"$@"
|
|
66
|
+
|
|
67
|
+
elif is_wsl; then
|
|
68
|
+
# WSL may not have full systemd support
|
|
69
|
+
echo "Using: ulimit (WSL detected, systemd unavailable)"
|
|
70
|
+
echo ""
|
|
71
|
+
|
|
72
|
+
MEM_KB=$(parse_memory_to_kb "$MEMORY_LIMIT")
|
|
73
|
+
|
|
74
|
+
# Set virtual memory limit (soft enforcement)
|
|
75
|
+
ulimit -v "$MEM_KB" 2>/dev/null || true
|
|
76
|
+
|
|
77
|
+
# Also set resident set size limit
|
|
78
|
+
ulimit -m "$MEM_KB" 2>/dev/null || true
|
|
79
|
+
|
|
80
|
+
exec "$@"
|
|
81
|
+
|
|
82
|
+
else
|
|
83
|
+
echo "Using: ulimit (systemd unavailable)"
|
|
84
|
+
echo ""
|
|
85
|
+
|
|
86
|
+
MEM_KB=$(parse_memory_to_kb "$MEMORY_LIMIT")
|
|
87
|
+
ulimit -v "$MEM_KB" 2>/dev/null || true
|
|
88
|
+
ulimit -m "$MEM_KB" 2>/dev/null || true
|
|
89
|
+
|
|
90
|
+
exec "$@"
|
|
91
|
+
fi
|
package/.claude/hooks/README.md
CHANGED
|
@@ -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`
|
package/.claude/hooks/{SessionStart:cfn-load-openai-key.sh → SessionStart-cfn-load-openai-key.sh}
RENAMED
|
@@ -1,35 +1,35 @@
|
|
|
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
|
-
set -e
|
|
7
|
-
|
|
8
|
-
# Path to root .env file
|
|
9
|
-
ROOT_ENV="${PROJECT_ROOT:-.}/.env"
|
|
10
|
-
|
|
11
|
-
# Check if .env exists
|
|
12
|
-
if [[ ! -f "$ROOT_ENV" ]]; then
|
|
13
|
-
echo "⚠️ Warning: $ROOT_ENV not found. OpenAI embeddings will not work." >&2
|
|
14
|
-
exit 0
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
# Extract OPENAI_API_KEY from .env
|
|
18
|
-
if grep -q "^OPENAI_API_KEY=" "$ROOT_ENV"; then
|
|
19
|
-
# Export the key for this session
|
|
20
|
-
export OPENAI_API_KEY=$(grep "^OPENAI_API_KEY=" "$ROOT_ENV" | cut -d'=' -f2- | tr -d '"')
|
|
21
|
-
|
|
22
|
-
# Verify key is set
|
|
23
|
-
if [[ -n "$OPENAI_API_KEY" ]]; then
|
|
24
|
-
echo "✅ Loaded OPENAI_API_KEY from root .env" >&2
|
|
25
|
-
else
|
|
26
|
-
echo "⚠️ Warning: OPENAI_API_KEY found but empty in $ROOT_ENV" >&2
|
|
27
|
-
fi
|
|
28
|
-
else
|
|
29
|
-
echo "⚠️ Warning: OPENAI_API_KEY not found in $ROOT_ENV. OpenAI embeddings will not work." >&2
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
# Make it available to subprocesses
|
|
33
|
-
export OPENAI_API_KEY
|
|
34
|
-
|
|
35
|
-
exit 0
|
|
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
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Path to root .env file
|
|
9
|
+
ROOT_ENV="${PROJECT_ROOT:-.}/.env"
|
|
10
|
+
|
|
11
|
+
# Check if .env exists
|
|
12
|
+
if [[ ! -f "$ROOT_ENV" ]]; then
|
|
13
|
+
echo "⚠️ Warning: $ROOT_ENV not found. OpenAI embeddings will not work." >&2
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Extract OPENAI_API_KEY from .env
|
|
18
|
+
if grep -q "^OPENAI_API_KEY=" "$ROOT_ENV"; then
|
|
19
|
+
# Export the key for this session
|
|
20
|
+
export OPENAI_API_KEY=$(grep "^OPENAI_API_KEY=" "$ROOT_ENV" | cut -d'=' -f2- | tr -d '"')
|
|
21
|
+
|
|
22
|
+
# Verify key is set
|
|
23
|
+
if [[ -n "$OPENAI_API_KEY" ]]; then
|
|
24
|
+
echo "✅ Loaded OPENAI_API_KEY from root .env" >&2
|
|
25
|
+
else
|
|
26
|
+
echo "⚠️ Warning: OPENAI_API_KEY found but empty in $ROOT_ENV" >&2
|
|
27
|
+
fi
|
|
28
|
+
else
|
|
29
|
+
echo "⚠️ Warning: OPENAI_API_KEY not found in $ROOT_ENV. OpenAI embeddings will not work." >&2
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Make it available to subprocesses
|
|
33
|
+
export OPENAI_API_KEY
|
|
34
|
+
|
|
35
|
+
exit 0
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# SessionStart hook: Build RuVector Rust binary if missing
|
|
3
|
-
# This ensures RuVector is compiled on cfn init
|
|
4
|
-
|
|
5
|
-
RUVECTOR_DIR="$(dirname "$(dirname "$(dirname "$0")")")/skills/cfn-local-ruvector-accelerator"
|
|
6
|
-
BINARY="$RUVECTOR_DIR/target/release/local-ruvector"
|
|
7
|
-
|
|
8
|
-
# Only build if binary doesn't exist
|
|
9
|
-
if [ ! -f "$BINARY" ]; then
|
|
10
|
-
echo "[cfn-build-ruvector] Binary not found, building..."
|
|
11
|
-
|
|
12
|
-
# Check if Cargo is available
|
|
13
|
-
if ! command -v cargo &> /dev/null; then
|
|
14
|
-
echo "[cfn-build-ruvector] WARNING: Cargo not installed, skipping RuVector build"
|
|
15
|
-
exit 0
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
# Build release binary
|
|
19
|
-
cd "$RUVECTOR_DIR" && cargo build --release --quiet 2>/dev/null
|
|
20
|
-
|
|
21
|
-
if [ -f "$BINARY" ]; then
|
|
22
|
-
echo "[cfn-build-ruvector] ✅ RuVector binary built successfully"
|
|
23
|
-
else
|
|
24
|
-
echo "[cfn-build-ruvector] WARNING: Build failed, RuVector unavailable"
|
|
25
|
-
fi
|
|
26
|
-
else
|
|
27
|
-
echo "[cfn-build-ruvector] ✅ RuVector binary already exists"
|
|
28
|
-
fi
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# SessionStart hook: Build RuVector Rust binary if missing
|
|
3
|
+
# This ensures RuVector is compiled on cfn init
|
|
4
|
+
|
|
5
|
+
RUVECTOR_DIR="$(dirname "$(dirname "$(dirname "$0")")")/skills/cfn-local-ruvector-accelerator"
|
|
6
|
+
BINARY="$RUVECTOR_DIR/target/release/local-ruvector"
|
|
7
|
+
|
|
8
|
+
# Only build if binary doesn't exist
|
|
9
|
+
if [ ! -f "$BINARY" ]; then
|
|
10
|
+
echo "[cfn-build-ruvector] Binary not found, building..."
|
|
11
|
+
|
|
12
|
+
# Check if Cargo is available
|
|
13
|
+
if ! command -v cargo &> /dev/null; then
|
|
14
|
+
echo "[cfn-build-ruvector] WARNING: Cargo not installed, skipping RuVector build"
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Build release binary
|
|
19
|
+
cd "$RUVECTOR_DIR" && cargo build --release --quiet 2>/dev/null
|
|
20
|
+
|
|
21
|
+
if [ -f "$BINARY" ]; then
|
|
22
|
+
echo "[cfn-build-ruvector] ✅ RuVector binary built successfully"
|
|
23
|
+
else
|
|
24
|
+
echo "[cfn-build-ruvector] WARNING: Build failed, RuVector unavailable"
|
|
25
|
+
fi
|
|
26
|
+
else
|
|
27
|
+
echo "[cfn-build-ruvector] ✅ RuVector binary already exists"
|
|
28
|
+
fi
|