@paulduvall/claude-dev-toolkit 0.0.1-alpha.2 → 0.0.1-alpha.21

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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -37
  3. package/bin/claude-commands +307 -65
  4. package/commands/active/xarchitecture.md +393 -0
  5. package/commands/active/xconfig.md +127 -0
  6. package/commands/active/xcontinue.md +92 -0
  7. package/commands/active/xdebug.md +130 -0
  8. package/commands/active/xdocs.md +178 -0
  9. package/commands/active/xexplore.md +94 -0
  10. package/commands/active/xgit.md +149 -0
  11. package/commands/active/xpipeline.md +152 -0
  12. package/commands/active/xquality.md +96 -0
  13. package/commands/active/xrefactor.md +198 -0
  14. package/commands/active/xrelease.md +142 -0
  15. package/commands/active/xsecurity.md +92 -0
  16. package/commands/active/xspec.md +174 -0
  17. package/commands/active/xtdd.md +151 -0
  18. package/commands/active/xtest.md +89 -0
  19. package/commands/active/xverify.md +80 -0
  20. package/commands/experiments/xact.md +742 -0
  21. package/commands/experiments/xanalytics.md +113 -0
  22. package/commands/experiments/xanalyze.md +70 -0
  23. package/commands/experiments/xapi.md +161 -0
  24. package/commands/experiments/xatomic.md +112 -0
  25. package/commands/experiments/xaws.md +85 -0
  26. package/commands/experiments/xcicd.md +337 -0
  27. package/commands/experiments/xcommit.md +122 -0
  28. package/commands/experiments/xcompliance.md +182 -0
  29. package/commands/experiments/xconstraints.md +89 -0
  30. package/commands/experiments/xcoverage.md +90 -0
  31. package/commands/experiments/xdb.md +102 -0
  32. package/commands/experiments/xdesign.md +121 -0
  33. package/commands/experiments/xdevcontainer.md +238 -0
  34. package/commands/experiments/xevaluate.md +111 -0
  35. package/commands/experiments/xfootnote.md +12 -0
  36. package/commands/experiments/xgenerate.md +117 -0
  37. package/commands/experiments/xgovernance.md +149 -0
  38. package/commands/experiments/xgreen.md +66 -0
  39. package/commands/experiments/xiac.md +118 -0
  40. package/commands/experiments/xincident.md +137 -0
  41. package/commands/experiments/xinfra.md +115 -0
  42. package/commands/experiments/xknowledge.md +115 -0
  43. package/commands/experiments/xmaturity.md +120 -0
  44. package/commands/experiments/xmetrics.md +118 -0
  45. package/commands/experiments/xmonitoring.md +128 -0
  46. package/commands/experiments/xnew.md +903 -0
  47. package/commands/experiments/xobservable.md +114 -0
  48. package/commands/experiments/xoidc.md +165 -0
  49. package/commands/experiments/xoptimize.md +115 -0
  50. package/commands/experiments/xperformance.md +112 -0
  51. package/commands/experiments/xplanning.md +131 -0
  52. package/commands/experiments/xpolicy.md +115 -0
  53. package/commands/experiments/xproduct.md +98 -0
  54. package/commands/experiments/xreadiness.md +75 -0
  55. package/commands/experiments/xred.md +55 -0
  56. package/commands/experiments/xrisk.md +128 -0
  57. package/commands/experiments/xrules.md +124 -0
  58. package/commands/experiments/xsandbox.md +120 -0
  59. package/commands/experiments/xscan.md +102 -0
  60. package/commands/experiments/xsetup.md +123 -0
  61. package/commands/experiments/xtemplate.md +116 -0
  62. package/commands/experiments/xtrace.md +212 -0
  63. package/commands/experiments/xux.md +171 -0
  64. package/commands/experiments/xvalidate.md +104 -0
  65. package/commands/experiments/xworkflow.md +113 -0
  66. package/hooks/.smellrc.example.json +19 -0
  67. package/hooks/README.md +263 -0
  68. package/hooks/check-commit-signing.py +127 -0
  69. package/hooks/check-complexity.py +38 -0
  70. package/hooks/check-security.py +37 -0
  71. package/hooks/claude-wrapper.sh +29 -0
  72. package/hooks/config.py +110 -0
  73. package/hooks/file-logger.sh +100 -0
  74. package/hooks/lib/argument-parser.sh +427 -0
  75. package/hooks/lib/config-constants.sh +230 -0
  76. package/hooks/lib/context-manager.sh +560 -0
  77. package/hooks/lib/error-handler.sh +423 -0
  78. package/hooks/lib/execution-engine.sh +444 -0
  79. package/hooks/lib/execution-results.sh +113 -0
  80. package/hooks/lib/execution-simulation.sh +114 -0
  81. package/hooks/lib/field-validators.sh +104 -0
  82. package/hooks/lib/file-utils.sh +398 -0
  83. package/hooks/lib/subagent-discovery.sh +468 -0
  84. package/hooks/lib/subagent-validator.sh +407 -0
  85. package/hooks/lib/validation-reporter.sh +134 -0
  86. package/hooks/on-error-debug.sh +226 -0
  87. package/hooks/pre-commit-quality.sh +204 -0
  88. package/hooks/pre-commit-test-runner.sh +132 -0
  89. package/hooks/pre-write-security.sh +115 -0
  90. package/hooks/prevent-credential-exposure.sh +279 -0
  91. package/hooks/security_bandit.py +177 -0
  92. package/hooks/security_checks.py +97 -0
  93. package/hooks/security_secrets.py +81 -0
  94. package/hooks/security_trojan.py +61 -0
  95. package/hooks/settings.example.json +52 -0
  96. package/hooks/smell_checks.py +238 -0
  97. package/hooks/smell_javascript.py +231 -0
  98. package/hooks/smell_python.py +110 -0
  99. package/hooks/smell_ruff.py +70 -0
  100. package/hooks/smell_types.py +72 -0
  101. package/hooks/subagent-trigger-simple.sh +202 -0
  102. package/hooks/subagent-trigger.sh +253 -0
  103. package/hooks/suppression.py +82 -0
  104. package/hooks/tab-color.sh +70 -0
  105. package/hooks/verify-before-edit.sh +135 -0
  106. package/lib/backup-restore-command.js +140 -0
  107. package/lib/base/base-command.js +252 -0
  108. package/lib/base/command-result.js +184 -0
  109. package/lib/config/constants.js +255 -0
  110. package/lib/config.js +48 -6
  111. package/lib/configure-command.js +428 -0
  112. package/lib/dependency-validator.js +64 -5
  113. package/lib/hook-installer-core.js +2 -2
  114. package/lib/installation-instruction-generator.js +213 -495
  115. package/lib/installer.js +134 -56
  116. package/lib/oidc-command.js +740 -0
  117. package/lib/services/backup-list-service.js +226 -0
  118. package/lib/services/backup-service.js +230 -0
  119. package/lib/services/command-installer-service.js +217 -0
  120. package/lib/services/logger-service.js +201 -0
  121. package/lib/services/package-manager-service.js +319 -0
  122. package/lib/services/platform-instruction-service.js +294 -0
  123. package/lib/services/recovery-instruction-service.js +348 -0
  124. package/lib/services/restore-service.js +221 -0
  125. package/lib/setup-command.js +359 -0
  126. package/lib/setup-wizard.js +155 -262
  127. package/lib/uninstall-command.js +100 -0
  128. package/lib/utils/claude-path-config.js +184 -0
  129. package/lib/utils/file-system-utils.js +152 -0
  130. package/lib/utils.js +8 -4
  131. package/lib/verify-command.js +430 -0
  132. package/package.json +7 -3
  133. package/scripts/postinstall.js +172 -157
  134. package/subagents/debug-specialist.md +7 -0
  135. package/templates/README.md +115 -0
  136. package/templates/basic-settings.json +30 -0
  137. package/templates/comprehensive-settings.json +57 -0
  138. package/templates/global-claude.md +344 -0
  139. package/templates/hybrid-hook-config.yaml +132 -0
  140. package/templates/security-focused-settings.json +62 -0
  141. package/templates/subagent-hooks.yaml +188 -0
  142. package/lib/package-manager-service.js +0 -270
  143. package/subagents/debug-context.md +0 -197
@@ -0,0 +1,226 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Claude Code Hook: Error Handling Trigger
5
+ #
6
+ # Purpose: Lightweight trigger for automatic debugging assistance on errors
7
+ # Trigger: Manual invocation or PostToolUse (no OnError hook event exists in Claude Code)
8
+ # Approach: Capture error context and delegate to debug-specialist subagent
9
+ #
10
+ # This hook provides immediate debugging help by gathering error context
11
+ # and connecting users with the debug-specialist subagent.
12
+
13
+ ##################################
14
+ # Load Shared Libraries
15
+ ##################################
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ LIB_DIR="$SCRIPT_DIR/lib"
18
+
19
+ # Load essential modules for error context gathering
20
+ source "$LIB_DIR/config-constants.sh"
21
+ source "$LIB_DIR/context-manager.sh"
22
+ source "$LIB_DIR/error-handler.sh"
23
+ source "$LIB_DIR/file-utils.sh"
24
+
25
+ ##################################
26
+ # Error Context Gathering
27
+ ##################################
28
+ gather_error_context() {
29
+ local error_type="${1:-unknown}"
30
+ local error_message="${2:-No error message provided}"
31
+ local failed_command="${3:-unknown}"
32
+
33
+ log_info "Gathering error context for debugging assistance"
34
+
35
+ # Capture comprehensive error context
36
+ local safe_type safe_msg safe_cmd safe_user safe_wd safe_branch
37
+ safe_type=$(json_escape "$error_type")
38
+ safe_msg=$(json_escape "$error_message")
39
+ safe_cmd=$(json_escape "$failed_command")
40
+ safe_user=$(json_escape "$USER")
41
+ safe_wd=$(json_escape "$(pwd)")
42
+ safe_branch=$(json_escape "$(git branch --show-current 2>/dev/null || echo 'not-in-git')")
43
+
44
+ local context_data
45
+ context_data=$(cat <<EOF
46
+ {
47
+ "trigger": "on_error_debug",
48
+ "error_info": {
49
+ "type": "$safe_type",
50
+ "message": "$safe_msg",
51
+ "failed_command": "$safe_cmd",
52
+ "timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
53
+ },
54
+ "environment": {
55
+ "tool": "${CLAUDE_TOOL:-unknown}",
56
+ "file": "${CLAUDE_FILE:-none}",
57
+ "working_directory": "$safe_wd",
58
+ "user": "$safe_user",
59
+ "shell": "${SHELL##*/}",
60
+ "session_id": "${CLAUDE_SESSION_ID:-$$}"
61
+ },
62
+ "project_context": {
63
+ "git_branch": "$safe_branch",
64
+ "git_status": "$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ') modified files"
65
+ },
66
+ "system_context": {
67
+ "os": "$(uname -s)"
68
+ }
69
+ }
70
+ EOF
71
+ )
72
+
73
+ echo "$context_data"
74
+ }
75
+
76
+ ##################################
77
+ # System Diagnostics
78
+ ##################################
79
+ gather_diagnostic_info() {
80
+ local diagnostic_info=""
81
+
82
+ # Check recent error logs if available
83
+ if [[ -f "$LOG_FILE" ]]; then
84
+ local recent_errors
85
+ recent_errors=$(tail -20 "$LOG_FILE" 2>/dev/null | grep -i error || echo "No recent errors in log")
86
+ diagnostic_info+="\nRecent log errors:\n$recent_errors"
87
+ fi
88
+
89
+ # Check system resources
90
+ if command -v df >/dev/null; then
91
+ local disk_usage
92
+ disk_usage=$(df -h . | tail -1 | awk '{print "Disk: " $4 " available"}')
93
+ diagnostic_info+="\n\nSystem resources:\n$disk_usage"
94
+ fi
95
+
96
+ # Check for common environment issues
97
+ if [[ -f "package.json" ]] && command -v npm >/dev/null; then
98
+ diagnostic_info+="\nNode.js project detected"
99
+ diagnostic_info+="\nNPM version: $(npm --version 2>/dev/null || echo 'npm not available')"
100
+ fi
101
+
102
+ if [[ -f "requirements.txt" ]] && command -v python >/dev/null; then
103
+ diagnostic_info+="\nPython project detected"
104
+ diagnostic_info+="\nPython version: $(python --version 2>/dev/null || echo 'python not available')"
105
+ fi
106
+
107
+ echo "$diagnostic_info"
108
+ }
109
+
110
+ ##################################
111
+ # Subagent Delegation
112
+ ##################################
113
+ delegate_to_debug_subagent() {
114
+ local context="$1"
115
+ local diagnostics="$2"
116
+ local error_message="$3"
117
+
118
+ log_info "Delegating error analysis to debug-specialist subagent"
119
+
120
+ echo "🐛 ERROR DETECTED: Automatic debugging assistance activated"
121
+ echo ""
122
+ echo "Error Details:"
123
+ echo " Message: $error_message"
124
+ echo " Tool: ${CLAUDE_TOOL:-unknown}"
125
+ echo " File: ${CLAUDE_FILE:-none}"
126
+ echo " Time: $(date)"
127
+ echo ""
128
+
129
+ if [[ -n "$diagnostics" ]]; then
130
+ echo "System Diagnostics:"
131
+ echo "$diagnostics"
132
+ echo ""
133
+ fi
134
+
135
+ echo "Context for debug-specialist subagent:"
136
+ echo "$context" | jq . 2>/dev/null || echo "$context"
137
+ echo ""
138
+ echo "🔍 DEBUG REQUEST:"
139
+ echo "Please analyze the error above and provide:"
140
+ echo "- Root cause analysis"
141
+ echo "- Step-by-step troubleshooting approach"
142
+ echo "- Specific commands or fixes to try"
143
+ echo "- Prevention strategies for similar issues"
144
+ echo ""
145
+ echo "Type your analysis or questions about this error."
146
+ }
147
+
148
+ ##################################
149
+ # Quick Error Classification
150
+ ##################################
151
+ classify_error() {
152
+ local error_message="$1"
153
+ local error_type="general"
154
+
155
+ # Basic error pattern matching for better context
156
+ case "$error_message" in
157
+ *"permission denied"*|*"Permission denied"*)
158
+ error_type="permission_error"
159
+ ;;
160
+ *"command not found"*|*"Command not found"*)
161
+ error_type="command_not_found"
162
+ ;;
163
+ *"No such file"*|*"cannot find"*)
164
+ error_type="file_not_found"
165
+ ;;
166
+ *"syntax error"*|*"Syntax error"*)
167
+ error_type="syntax_error"
168
+ ;;
169
+ *"connection"*|*"network"*|*"timeout"*)
170
+ error_type="network_error"
171
+ ;;
172
+ *"import"*|*"module"*|*"package"*)
173
+ error_type="dependency_error"
174
+ ;;
175
+ *)
176
+ error_type="general_error"
177
+ ;;
178
+ esac
179
+
180
+ echo "$error_type"
181
+ }
182
+
183
+ ##################################
184
+ # Main Hook Logic
185
+ ##################################
186
+ main() {
187
+ # Initialize error handling (ironic for an error hook, but important!)
188
+ initialize_error_handling || {
189
+ echo "ERROR: Failed to initialize error handling in error hook" >&2
190
+ exit 1
191
+ }
192
+
193
+ local error_message="${1:-Unknown error occurred}"
194
+ local failed_command="${2:-unknown}"
195
+
196
+ log_info "Error hook triggered: $error_message"
197
+
198
+ # Classify the error type
199
+ local error_type
200
+ error_type=$(classify_error "$error_message")
201
+
202
+ # Gather comprehensive error context
203
+ local context
204
+ context=$(gather_error_context "$error_type" "$error_message" "$failed_command")
205
+
206
+ # Gather additional diagnostic information
207
+ local diagnostics
208
+ diagnostics=$(gather_diagnostic_info)
209
+
210
+ # Delegate to debug-specialist subagent
211
+ delegate_to_debug_subagent "$context" "$diagnostics" "$error_message"
212
+
213
+ log_info "Debug delegation completed for error: $error_type"
214
+ }
215
+
216
+ ##################################
217
+ # Execute Hook
218
+ ##################################
219
+ # Handle both direct invocation and error trap scenarios
220
+ if [[ "${1:-}" == "--trap" ]]; then
221
+ # Called from an error trap
222
+ main "Script error at line ${2:-unknown}" "${3:-unknown command}"
223
+ else
224
+ # Called directly with error information
225
+ main "$@"
226
+ fi
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Claude Code Hook: Pre-Commit Quality Check
5
+ #
6
+ # Purpose: Lightweight trigger for code quality validation before git commits
7
+ # Trigger: Custom hook for pre-commit operations
8
+ # Approach: Quick validation with style-enforcer subagent delegation
9
+ #
10
+ # This hook ensures code quality by leveraging AI analysis rather than
11
+ # running multiple linting tools manually.
12
+
13
+ ##################################
14
+ # Load Shared Libraries
15
+ ##################################
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ LIB_DIR="$SCRIPT_DIR/lib"
18
+
19
+ # Load essential modules for lightweight operation
20
+ source "$LIB_DIR/config-constants.sh"
21
+ source "$LIB_DIR/context-manager.sh"
22
+ source "$LIB_DIR/error-handler.sh"
23
+ source "$LIB_DIR/file-utils.sh"
24
+
25
+ ##################################
26
+ # Git Context Analysis
27
+ ##################################
28
+ analyze_staged_changes() {
29
+ log_info "Analyzing staged changes for quality check"
30
+
31
+ # Check if we're in a git repository
32
+ if ! git rev-parse --git-dir >/dev/null 2>&1; then
33
+ log_debug "Not in a git repository, skipping pre-commit quality check"
34
+ return 0
35
+ fi
36
+
37
+ # Get staged files
38
+ local staged_files
39
+ staged_files=$(git diff --cached --name-only 2>/dev/null || echo "")
40
+
41
+ if [[ -z "$staged_files" ]]; then
42
+ log_info "No staged changes found, skipping quality check"
43
+ return 0
44
+ fi
45
+
46
+ echo "$staged_files"
47
+ }
48
+
49
+ ##################################
50
+ # Quality Context Gathering
51
+ ##################################
52
+ gather_quality_context() {
53
+ local staged_files="$1"
54
+
55
+ # Create context for quality analysis
56
+ local context_data
57
+ context_data=$(cat <<EOF
58
+ {
59
+ "trigger": "pre_commit_quality",
60
+ "staged_files": [$(echo "$staged_files" | sed 's/.*/"&"/' | paste -sd ',' -)],
61
+ "git_info": {
62
+ "branch": "$(git branch --show-current 2>/dev/null || echo 'unknown')",
63
+ "commit_hash": "$(git rev-parse HEAD 2>/dev/null || echo 'initial')",
64
+ "status": "$(git status --porcelain --cached | wc -l | tr -d ' ') files staged"
65
+ },
66
+ "project_info": {
67
+ "working_directory": "$(pwd)",
68
+ "user": "$USER",
69
+ "timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
70
+ },
71
+ "file_analysis": {
72
+ "total_files": $(echo "$staged_files" | wc -l | tr -d ' '),
73
+ "file_types": $(echo "$staged_files" | sed 's/.*\.//' | sort | uniq -c | jq -R -s 'split("\n")[:-1] | map(split(" ")[-1]) | unique')
74
+ }
75
+ }
76
+ EOF
77
+ )
78
+
79
+ echo "$context_data"
80
+ }
81
+
82
+ ##################################
83
+ # Subagent Delegation
84
+ ##################################
85
+ delegate_to_quality_subagent() {
86
+ local context="$1"
87
+ local staged_files="$2"
88
+
89
+ log_info "Delegating quality analysis to style-enforcer subagent"
90
+
91
+ echo "📊 QUALITY CHECK: Analyzing staged changes before commit"
92
+ echo ""
93
+ echo "Staged files for analysis:"
94
+ echo "$staged_files" | sed 's/^/ - /'
95
+ echo ""
96
+ echo "Context for style-enforcer subagent:"
97
+ echo "$context" | jq . 2>/dev/null || echo "$context"
98
+ echo ""
99
+ echo "Please analyze the staged changes for:"
100
+ echo "- Code formatting and style consistency"
101
+ echo "- Import organization and unused imports"
102
+ echo "- Type annotations and documentation"
103
+ echo "- Best practices and code patterns"
104
+ echo "- Performance considerations"
105
+ echo ""
106
+ echo "Provide specific feedback or type 'approved' if quality standards are met."
107
+ }
108
+
109
+ ##################################
110
+ # Quick File Validation
111
+ ##################################
112
+ validate_basic_file_integrity() {
113
+ local staged_files="$1"
114
+
115
+ log_debug "Performing basic file integrity checks"
116
+
117
+ # Check for common issues that can be caught quickly
118
+ local issues=()
119
+
120
+ while IFS= read -r file; do
121
+ [[ -z "$file" ]] && continue
122
+
123
+ # Skip non-existent files (deletions)
124
+ [[ ! -f "$file" ]] && continue
125
+
126
+ # Check for basic syntax issues in common file types
127
+ case "$file" in
128
+ *.json)
129
+ if ! jq . "$file" >/dev/null 2>&1; then
130
+ issues+=("Invalid JSON syntax: $file")
131
+ fi
132
+ ;;
133
+ *.yml|*.yaml)
134
+ if command -v yq >/dev/null && ! yq . "$file" >/dev/null 2>&1; then
135
+ issues+=("Invalid YAML syntax: $file")
136
+ fi
137
+ ;;
138
+ *.sh)
139
+ if ! bash -n "$file" 2>/dev/null; then
140
+ issues+=("Invalid shell syntax: $file")
141
+ fi
142
+ ;;
143
+ esac
144
+
145
+ # Check for potential credential patterns (quick scan)
146
+ if grep -qE "(password|api_key|secret|token)\s*[:=]\s*['\"][^'\"]+['\"]" "$file" 2>/dev/null; then
147
+ issues+=("Potential credential exposure: $file")
148
+ fi
149
+
150
+ done <<< "$staged_files"
151
+
152
+ # Report immediate issues
153
+ if [[ ${#issues[@]} -gt 0 ]]; then
154
+ echo "⚠️ IMMEDIATE ISSUES FOUND:"
155
+ printf '%s\n' "${issues[@]}" | sed 's/^/ - /'
156
+ echo ""
157
+ echo "Please fix these issues before committing."
158
+ return 1
159
+ fi
160
+
161
+ return 0
162
+ }
163
+
164
+ ##################################
165
+ # Main Hook Logic
166
+ ##################################
167
+ main() {
168
+ # Initialize error handling
169
+ initialize_error_handling || {
170
+ echo "ERROR: Failed to initialize error handling" >&2
171
+ exit 1
172
+ }
173
+
174
+ log_info "Pre-commit quality check initiated"
175
+
176
+ # Analyze what's being committed
177
+ local staged_files
178
+ staged_files=$(analyze_staged_changes)
179
+
180
+ # Exit early if no staged changes
181
+ if [[ -z "$staged_files" ]]; then
182
+ exit 0
183
+ fi
184
+
185
+ # Perform quick validation checks
186
+ if ! validate_basic_file_integrity "$staged_files"; then
187
+ log_error "Basic file integrity checks failed"
188
+ exit 1
189
+ fi
190
+
191
+ # Gather context for subagent analysis
192
+ local context
193
+ context=$(gather_quality_context "$staged_files")
194
+
195
+ # Delegate to quality subagent for comprehensive analysis
196
+ delegate_to_quality_subagent "$context" "$staged_files"
197
+
198
+ log_info "Quality check delegation completed"
199
+ }
200
+
201
+ ##################################
202
+ # Execute Hook
203
+ ##################################
204
+ main "$@"
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Claude Code Hook: Pre-Commit Test Runner
5
+ #
6
+ # Description: Auto-detects test framework and runs tests before commits
7
+ # Purpose: Prevent commits with failing tests by validating the full test suite
8
+ # Trigger: PreToolUse
9
+ # Blocking: Yes
10
+ # Tools: Bash
11
+ # Author: Claude Dev Toolkit
12
+ # Version: 1.0.0
13
+ # Category: security
14
+ #
15
+ # This hook validates code quality by running the project's test suite
16
+ # before allowing commit operations to proceed.
17
+
18
+ ##################################
19
+ # Configuration
20
+ ##################################
21
+ HOOK_NAME="pre-commit-test-runner"
22
+ LOG_FILE="$HOME/.claude/logs/pre-commit-test-runner.log"
23
+
24
+ mkdir -p "$(dirname "$LOG_FILE")"
25
+ chmod 700 "$(dirname "$LOG_FILE")"
26
+ touch "$LOG_FILE"
27
+ chmod 600 "$LOG_FILE"
28
+
29
+ ##################################
30
+ # Logging
31
+ ##################################
32
+ log() {
33
+ echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$HOOK_NAME] $*" >> "$LOG_FILE"
34
+ }
35
+
36
+ ##################################
37
+ # Commit Detection
38
+ ##################################
39
+ is_commit_command() {
40
+ local tool="${CLAUDE_TOOL:-}"
41
+ local content="${CLAUDE_CONTENT:-}"
42
+
43
+ if [[ "$tool" != "Bash" ]]; then
44
+ return 1
45
+ fi
46
+
47
+ echo "$content" | grep -qE 'git\s+commit' || return 1
48
+ }
49
+
50
+ ##################################
51
+ # Framework Detection
52
+ ##################################
53
+ detect_framework() {
54
+ if [[ -f "pytest.ini" ]] || { [[ -f "pyproject.toml" ]] && grep -q '\[tool.pytest' pyproject.toml 2>/dev/null; }; then
55
+ echo "pytest"
56
+ elif [[ -f "package.json" ]] && grep -q '"test"' package.json 2>/dev/null; then
57
+ if grep -qE '"(jest|vitest)' package.json 2>/dev/null; then
58
+ echo "jest"
59
+ else
60
+ echo "npm-test"
61
+ fi
62
+ elif [[ -f "go.mod" ]]; then
63
+ echo "go-test"
64
+ elif [[ -f "Cargo.toml" ]]; then
65
+ echo "cargo-test"
66
+ elif [[ -f "mix.exs" ]]; then
67
+ echo "mix-test"
68
+ else
69
+ echo "none"
70
+ fi
71
+ }
72
+
73
+ ##################################
74
+ # Test Execution
75
+ ##################################
76
+ run_tests() {
77
+ local framework="$1"
78
+ log "Running tests with framework: $framework"
79
+
80
+ case "$framework" in
81
+ pytest) python -m pytest --tb=short 2>&1 ;;
82
+ jest) npx jest --ci 2>&1 ;;
83
+ npm-test) npm test 2>&1 ;;
84
+ go-test) go test ./... 2>&1 ;;
85
+ cargo-test) cargo test 2>&1 ;;
86
+ mix-test) mix test 2>&1 ;;
87
+ *) echo "No test framework detected" ;;
88
+ esac
89
+ }
90
+
91
+ ##################################
92
+ # Main Hook Logic
93
+ ##################################
94
+ main() {
95
+ if ! is_commit_command; then
96
+ log "Not a commit command, skipping"
97
+ exit 0
98
+ fi
99
+
100
+ log "Commit detected, checking for test framework"
101
+ local framework
102
+ framework=$(detect_framework)
103
+
104
+ if [[ "$framework" == "none" ]]; then
105
+ log "No test framework detected, allowing commit"
106
+ exit 0
107
+ fi
108
+
109
+ log "Detected framework: $framework"
110
+ local output
111
+ output=$(run_tests "$framework") || {
112
+ local exit_code=$?
113
+ echo "Test validation failed — commit blocked"
114
+ echo "Framework: $framework"
115
+ echo "$output" | tail -10
116
+ log "Tests FAILED (exit $exit_code)"
117
+ exit 1
118
+ }
119
+
120
+ log "Security check passed — all tests green"
121
+ exit 0
122
+ }
123
+
124
+ ##################################
125
+ # Error Handling
126
+ ##################################
127
+ trap 'log "Hook failed with error on line $LINENO"' ERR
128
+
129
+ ##################################
130
+ # Execute
131
+ ##################################
132
+ main "$@"
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Claude Code Hook: Pre-Write Security Check
5
+ #
6
+ # Purpose: Lightweight trigger for security scanning before file modifications
7
+ # Trigger: PreToolUse for Edit, Write, MultiEdit tools
8
+ # Approach: Gather context and delegate complex logic to security-auditor subagent
9
+ #
10
+ # This hook provides immediate security feedback by leveraging AI reasoning
11
+ # rather than complex bash pattern matching.
12
+
13
+ ##################################
14
+ # Load Shared Libraries
15
+ ##################################
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ LIB_DIR="$SCRIPT_DIR/lib"
18
+
19
+ # Load only essential modules for lightweight operation
20
+ source "$LIB_DIR/config-constants.sh"
21
+ source "$LIB_DIR/file-utils.sh"
22
+ source "$LIB_DIR/context-manager.sh"
23
+ source "$LIB_DIR/error-handler.sh"
24
+
25
+ ##################################
26
+ # Simple Context Gathering
27
+ ##################################
28
+ gather_security_context() {
29
+ local tool="${CLAUDE_TOOL:-unknown}"
30
+ local file="${CLAUDE_FILE:-none}"
31
+
32
+ log_info "Pre-write security check triggered for: $tool on $file"
33
+
34
+ # Create lightweight context for subagent
35
+ local safe_tool safe_file safe_user safe_wd safe_branch
36
+ safe_tool=$(json_escape "$tool")
37
+ safe_file=$(json_escape "$file")
38
+ safe_user=$(json_escape "$USER")
39
+ safe_wd=$(json_escape "$(pwd)")
40
+ safe_branch=$(json_escape "$(git branch --show-current 2>/dev/null || echo 'not-in-git')")
41
+
42
+ local context_data
43
+ context_data=$(cat <<EOF
44
+ {
45
+ "trigger": "pre_write_security",
46
+ "tool": "$safe_tool",
47
+ "file": "$safe_file",
48
+ "timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
49
+ "user": "$safe_user",
50
+ "working_directory": "$safe_wd",
51
+ "git_branch": "$safe_branch",
52
+ "session_id": "${CLAUDE_SESSION_ID:-$$}"
53
+ }
54
+ EOF
55
+ )
56
+
57
+ echo "$context_data"
58
+ }
59
+
60
+ ##################################
61
+ # Subagent Delegation
62
+ ##################################
63
+ delegate_to_security_subagent() {
64
+ local context="$1"
65
+
66
+ # Log the delegation
67
+ log_info "Delegating security analysis to security-auditor subagent"
68
+
69
+ # In the hybrid approach, we provide context and let Claude Code
70
+ # handle the subagent execution through its native mechanisms
71
+ echo "🔒 SECURITY CHECK: Analyzing $CLAUDE_TOOL operation on $CLAUDE_FILE"
72
+ echo ""
73
+ echo "Context for security-auditor subagent:"
74
+ echo "$context" | jq . 2>/dev/null || echo "$context"
75
+ echo ""
76
+ echo "Please review the operation above for:"
77
+ echo "- Credential exposure (API keys, passwords, tokens)"
78
+ echo "- Security vulnerabilities (SQL injection, XSS, etc.)"
79
+ echo "- Sensitive data handling"
80
+ echo "- Access control issues"
81
+ echo ""
82
+ echo "Type 'continue' if the operation is secure, or provide specific security concerns."
83
+ }
84
+
85
+ ##################################
86
+ # Main Hook Logic
87
+ ##################################
88
+ main() {
89
+ # Initialize error handling
90
+ initialize_error_handling || {
91
+ echo "ERROR: Failed to initialize error handling" >&2
92
+ exit 1
93
+ }
94
+
95
+ # Gather context for security analysis
96
+ local context
97
+ context=$(gather_security_context)
98
+
99
+ # Check if this is a security-relevant operation
100
+ case "${CLAUDE_TOOL:-}" in
101
+ Edit|Write|MultiEdit)
102
+ log_debug "Security-relevant tool detected: $CLAUDE_TOOL"
103
+ delegate_to_security_subagent "$context"
104
+ ;;
105
+ *)
106
+ log_debug "Non-security-relevant tool: ${CLAUDE_TOOL:-unknown}"
107
+ exit 0
108
+ ;;
109
+ esac
110
+ }
111
+
112
+ ##################################
113
+ # Execute Hook
114
+ ##################################
115
+ main "$@"