@paulduvall/claude-dev-toolkit 0.0.1-alpha.1 → 0.0.1-alpha.4
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/README.md +44 -6
- package/bin/claude-commands +20 -0
- package/commands/active/xarchitecture.md +393 -0
- package/commands/active/xconfig.md +127 -0
- package/commands/active/xdebug.md +130 -0
- package/commands/active/xdocs.md +178 -0
- package/commands/active/xgit.md +149 -0
- package/commands/active/xpipeline.md +152 -0
- package/commands/active/xquality.md +96 -0
- package/commands/active/xrefactor.md +198 -0
- package/commands/active/xrelease.md +142 -0
- package/commands/active/xsecurity.md +92 -0
- package/commands/active/xspec.md +174 -0
- package/commands/active/xtdd.md +151 -0
- package/commands/active/xtest.md +89 -0
- package/commands/experiments/xact.md +742 -0
- package/commands/experiments/xanalytics.md +113 -0
- package/commands/experiments/xanalyze.md +70 -0
- package/commands/experiments/xapi.md +161 -0
- package/commands/experiments/xatomic.md +112 -0
- package/commands/experiments/xaws.md +85 -0
- package/commands/experiments/xcicd.md +337 -0
- package/commands/experiments/xcommit.md +122 -0
- package/commands/experiments/xcompliance.md +182 -0
- package/commands/experiments/xconstraints.md +89 -0
- package/commands/experiments/xcoverage.md +90 -0
- package/commands/experiments/xdb.md +102 -0
- package/commands/experiments/xdesign.md +121 -0
- package/commands/experiments/xevaluate.md +111 -0
- package/commands/experiments/xfootnote.md +12 -0
- package/commands/experiments/xgenerate.md +117 -0
- package/commands/experiments/xgovernance.md +149 -0
- package/commands/experiments/xgreen.md +66 -0
- package/commands/experiments/xiac.md +118 -0
- package/commands/experiments/xincident.md +137 -0
- package/commands/experiments/xinfra.md +115 -0
- package/commands/experiments/xknowledge.md +115 -0
- package/commands/experiments/xmaturity.md +120 -0
- package/commands/experiments/xmetrics.md +118 -0
- package/commands/experiments/xmonitoring.md +128 -0
- package/commands/experiments/xnew.md +898 -0
- package/commands/experiments/xobservable.md +114 -0
- package/commands/experiments/xoidc.md +165 -0
- package/commands/experiments/xoptimize.md +115 -0
- package/commands/experiments/xperformance.md +112 -0
- package/commands/experiments/xplanning.md +131 -0
- package/commands/experiments/xpolicy.md +115 -0
- package/commands/experiments/xproduct.md +98 -0
- package/commands/experiments/xreadiness.md +75 -0
- package/commands/experiments/xred.md +55 -0
- package/commands/experiments/xrisk.md +128 -0
- package/commands/experiments/xrules.md +124 -0
- package/commands/experiments/xsandbox.md +120 -0
- package/commands/experiments/xscan.md +102 -0
- package/commands/experiments/xsetup.md +123 -0
- package/commands/experiments/xtemplate.md +116 -0
- package/commands/experiments/xtrace.md +212 -0
- package/commands/experiments/xux.md +171 -0
- package/commands/experiments/xvalidate.md +104 -0
- package/commands/experiments/xworkflow.md +113 -0
- package/hooks/README.md +231 -0
- package/hooks/file-logger.sh +98 -0
- package/hooks/lib/argument-parser.sh +422 -0
- package/hooks/lib/config-constants.sh +230 -0
- package/hooks/lib/context-manager.sh +549 -0
- package/hooks/lib/error-handler.sh +412 -0
- package/hooks/lib/execution-engine.sh +627 -0
- package/hooks/lib/file-utils.sh +375 -0
- package/hooks/lib/subagent-discovery.sh +465 -0
- package/hooks/lib/subagent-validator.sh +597 -0
- package/hooks/on-error-debug.sh +221 -0
- package/hooks/pre-commit-quality.sh +204 -0
- package/hooks/pre-write-security.sh +107 -0
- package/hooks/prevent-credential-exposure.sh +265 -0
- package/hooks/subagent-trigger-simple.sh +193 -0
- package/hooks/subagent-trigger.sh +253 -0
- package/lib/config.js +186 -3
- package/lib/hook-installer-core.js +2 -2
- package/lib/result.js +138 -0
- package/lib/subagent-formatter.js +278 -0
- package/lib/subagents-core.js +237 -0
- package/lib/subagents.js +508 -0
- package/lib/types.d.ts +183 -0
- package/package.json +14 -3
- package/subagents/api-guardian.md +29 -0
- package/subagents/audit-trail-verifier.md +24 -0
- package/subagents/change-scoper.md +23 -0
- package/subagents/ci-pipeline-curator.md +24 -0
- package/subagents/code-review-assistant.md +258 -0
- package/subagents/continuous-release-orchestrator.md +29 -0
- package/subagents/contract-tester.md +24 -0
- package/subagents/data-steward.md +29 -0
- package/subagents/debug-context.md +197 -0
- package/subagents/debug-specialist.md +138 -0
- package/subagents/dependency-steward.md +24 -0
- package/subagents/deployment-strategist.md +29 -0
- package/subagents/documentation-curator.md +29 -0
- package/subagents/environment-guardian.md +29 -0
- package/subagents/license-compliance-guardian.md +29 -0
- package/subagents/observability-engineer.md +25 -0
- package/subagents/performance-guardian.md +29 -0
- package/subagents/product-owner-proxy.md +28 -0
- package/subagents/requirements-reviewer.md +26 -0
- package/subagents/rollback-first-responder.md +24 -0
- package/subagents/sbom-provenance.md +25 -0
- package/subagents/security-auditor.md +29 -0
- package/subagents/style-enforcer.md +23 -0
- package/subagents/test-writer.md +24 -0
- package/subagents/trunk-guardian.md +29 -0
- package/subagents/workflow-coordinator.md +26 -0
- package/templates/README.md +100 -0
- package/templates/basic-settings.json +30 -0
- package/templates/comprehensive-settings.json +206 -0
- package/templates/hybrid-hook-config.yaml +133 -0
- package/templates/security-focused-settings.json +62 -0
- package/templates/subagent-hooks.yaml +188 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Claude Code Hook: Prevent Credential Exposure
|
|
5
|
+
#
|
|
6
|
+
# Purpose: Scan for exposed credentials before any file write/edit operations
|
|
7
|
+
# Trigger: PreToolUse for Edit, Write, MultiEdit tools
|
|
8
|
+
# Blocking: Yes - prevents credential exposure
|
|
9
|
+
#
|
|
10
|
+
# This hook implements enterprise-grade security by detecting and preventing
|
|
11
|
+
# accidental credential exposure in AI-generated or AI-modified code.
|
|
12
|
+
|
|
13
|
+
##################################
|
|
14
|
+
# Configuration
|
|
15
|
+
##################################
|
|
16
|
+
HOOK_NAME="prevent-credential-exposure"
|
|
17
|
+
LOG_FILE="$HOME/.claude/logs/security-hooks.log"
|
|
18
|
+
VIOLATION_LOG="$HOME/.claude/logs/credential-violations.log"
|
|
19
|
+
NOTIFICATION_WEBHOOK="${SECURITY_WEBHOOK_URL:-}"
|
|
20
|
+
|
|
21
|
+
# Ensure log directory exists with secure permissions
|
|
22
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
23
|
+
chmod 700 "$(dirname "$LOG_FILE")"
|
|
24
|
+
|
|
25
|
+
# Create log files with restrictive permissions if they don't exist
|
|
26
|
+
touch "$LOG_FILE" "$VIOLATION_LOG"
|
|
27
|
+
chmod 600 "$LOG_FILE" "$VIOLATION_LOG"
|
|
28
|
+
|
|
29
|
+
##################################
|
|
30
|
+
# Logging Functions
|
|
31
|
+
##################################
|
|
32
|
+
log() {
|
|
33
|
+
echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$HOOK_NAME] $*" | tee -a "$LOG_FILE"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
log_violation() {
|
|
37
|
+
echo "[$(date +'%Y-%m-%d %H:%M:%S')] VIOLATION: $*" | tee -a "$VIOLATION_LOG"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
##################################
|
|
41
|
+
# Notification Functions
|
|
42
|
+
##################################
|
|
43
|
+
notify_security_team() {
|
|
44
|
+
local violation_type="$1"
|
|
45
|
+
local file_path="$2"
|
|
46
|
+
local pattern="$3"
|
|
47
|
+
|
|
48
|
+
if [[ -n "$NOTIFICATION_WEBHOOK" ]]; then
|
|
49
|
+
curl -s -X POST "$NOTIFICATION_WEBHOOK" \
|
|
50
|
+
-H "Content-Type: application/json" \
|
|
51
|
+
-d "{
|
|
52
|
+
\"text\": \"🚨 SECURITY ALERT: Credential exposure prevented\",
|
|
53
|
+
\"attachments\": [{
|
|
54
|
+
\"color\": \"danger\",
|
|
55
|
+
\"fields\": [
|
|
56
|
+
{\"title\": \"Violation Type\", \"value\": \"$violation_type\", \"short\": true},
|
|
57
|
+
{\"title\": \"File\", \"value\": \"$file_path\", \"short\": true},
|
|
58
|
+
{\"title\": \"Pattern\", \"value\": \"$pattern\", \"short\": false},
|
|
59
|
+
{\"title\": \"User\", \"value\": \"$USER\", \"short\": true},
|
|
60
|
+
{\"title\": \"Timestamp\", \"value\": \"$(date)\", \"short\": true}
|
|
61
|
+
]
|
|
62
|
+
}]
|
|
63
|
+
}" 2>/dev/null || log "Failed to send security notification"
|
|
64
|
+
fi
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
##################################
|
|
68
|
+
# Credential Detection Patterns
|
|
69
|
+
##################################
|
|
70
|
+
# High-confidence patterns for common credential types
|
|
71
|
+
declare -A CREDENTIAL_PATTERNS=(
|
|
72
|
+
# API Keys
|
|
73
|
+
["anthropic_api_key"]='sk-ant-[a-zA-Z0-9]{95}'
|
|
74
|
+
["openai_api_key"]='sk-[a-zA-Z0-9]{32,}'
|
|
75
|
+
["github_token"]='gh[po]_[a-zA-Z0-9]{36}'
|
|
76
|
+
["aws_access_key"]='AKIA[0-9A-Z]{16}'
|
|
77
|
+
["azure_key"]='[a-zA-Z0-9/+]{86}=='
|
|
78
|
+
|
|
79
|
+
# Database URLs with credentials
|
|
80
|
+
["database_url_with_password"]='(mysql|postgresql|mongodb)://[^:]+:[^@]+@'
|
|
81
|
+
|
|
82
|
+
# Generic high-entropy patterns
|
|
83
|
+
["generic_api_key"]='["\']?[a-zA-Z0-9_-]*[aA][pP][iI][_-]?[kK][eE][yY]["\']?\s*[:=]\s*["\'][a-zA-Z0-9+/=]{20,}["\']'
|
|
84
|
+
["generic_secret"]='["\']?[a-zA-Z0-9_-]*[sS][eE][cC][rR][eE][tT]["\']?\s*[:=]\s*["\'][a-zA-Z0-9+/=]{20,}["\']'
|
|
85
|
+
["generic_password"]='["\']?[a-zA-Z0-9_-]*[pP][aA][sS][sS][wW][oO][rR][dD]["\']?\s*[:=]\s*["\'][^"\']{8,}["\']'
|
|
86
|
+
|
|
87
|
+
# JWT Tokens
|
|
88
|
+
["jwt_token"]='eyJ[a-zA-Z0-9+/=]{20,}\.[a-zA-Z0-9+/=]{20,}\.[a-zA-Z0-9+/=_-]{20,}'
|
|
89
|
+
|
|
90
|
+
# Private Keys
|
|
91
|
+
["private_key"]='-----BEGIN [A-Z ]*PRIVATE KEY-----'
|
|
92
|
+
["ssh_private_key"]='-----BEGIN OPENSSH PRIVATE KEY-----'
|
|
93
|
+
|
|
94
|
+
# Cloud Provider Specific
|
|
95
|
+
["gcp_service_account_key"]='"type":\s*"service_account"'
|
|
96
|
+
["slack_webhook"]='hooks\.slack\.com/services/[A-Z0-9]{9}/[A-Z0-9]{11}/[a-zA-Z0-9]{24}'
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
##################################
|
|
100
|
+
# Content Analysis Functions
|
|
101
|
+
##################################
|
|
102
|
+
scan_file_content() {
|
|
103
|
+
local file_path="$1"
|
|
104
|
+
local content="$2"
|
|
105
|
+
local violations=()
|
|
106
|
+
|
|
107
|
+
# Skip if file doesn't exist or is binary
|
|
108
|
+
if [[ ! -f "$file_path" ]]; then
|
|
109
|
+
return 0
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Check if file is binary (avoid scanning binary files)
|
|
113
|
+
if file "$file_path" 2>/dev/null | grep -q "binary"; then
|
|
114
|
+
return 0
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
log "Scanning file: $file_path"
|
|
118
|
+
|
|
119
|
+
# Check each credential pattern
|
|
120
|
+
for pattern_name in "${!CREDENTIAL_PATTERNS[@]}"; do
|
|
121
|
+
local pattern="${CREDENTIAL_PATTERNS[$pattern_name]}"
|
|
122
|
+
|
|
123
|
+
if echo "$content" | grep -qiP "$pattern"; then
|
|
124
|
+
log_violation "$pattern_name detected in $file_path"
|
|
125
|
+
violations+=("$pattern_name")
|
|
126
|
+
|
|
127
|
+
# Extract the matched content for logging (but redact it)
|
|
128
|
+
local matched_line=$(echo "$content" | grep -iP "$pattern" | head -1)
|
|
129
|
+
local redacted_line=$(echo "$matched_line" | sed 's/[a-zA-Z0-9+/=]\{10,\}/[REDACTED]/g')
|
|
130
|
+
|
|
131
|
+
log_violation "Pattern: $pattern_name, Line: $redacted_line"
|
|
132
|
+
|
|
133
|
+
# Notify security team
|
|
134
|
+
notify_security_team "$pattern_name" "$file_path" "$redacted_line"
|
|
135
|
+
fi
|
|
136
|
+
done
|
|
137
|
+
|
|
138
|
+
# Return violation count
|
|
139
|
+
echo "${#violations[@]}"
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
check_environment_leakage() {
|
|
143
|
+
local content="$1"
|
|
144
|
+
local violations=0
|
|
145
|
+
|
|
146
|
+
# Check for environment variable exposure patterns
|
|
147
|
+
if echo "$content" | grep -qiP 'process\.env\.[A-Z_]*(?:KEY|SECRET|PASSWORD|TOKEN)'; then
|
|
148
|
+
log_violation "Environment variable credential exposure detected"
|
|
149
|
+
((violations++))
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# Check for hardcoded production URLs with credentials
|
|
153
|
+
if echo "$content" | grep -qiP 'https?://[^:]+:[^@]+@[^/]+'; then
|
|
154
|
+
log_violation "URL with embedded credentials detected"
|
|
155
|
+
((violations++))
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
echo "$violations"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
##################################
|
|
162
|
+
# Dependency Validation
|
|
163
|
+
##################################
|
|
164
|
+
validate_hook_dependencies() {
|
|
165
|
+
local deps=("grep" "file" "sed" "head")
|
|
166
|
+
local missing=()
|
|
167
|
+
|
|
168
|
+
for dep in "${deps[@]}"; do
|
|
169
|
+
if ! command -v "$dep" &> /dev/null; then
|
|
170
|
+
missing+=("$dep")
|
|
171
|
+
fi
|
|
172
|
+
done
|
|
173
|
+
|
|
174
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
175
|
+
log "ERROR: Missing required dependencies: ${missing[*]}"
|
|
176
|
+
echo "Install missing tools and retry"
|
|
177
|
+
exit 1
|
|
178
|
+
fi
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
##################################
|
|
182
|
+
# Main Hook Logic
|
|
183
|
+
##################################
|
|
184
|
+
main() {
|
|
185
|
+
# Validate dependencies first
|
|
186
|
+
validate_hook_dependencies
|
|
187
|
+
local tool_name="${CLAUDE_TOOL:-unknown}"
|
|
188
|
+
local file_path="${CLAUDE_FILE:-}"
|
|
189
|
+
local content=""
|
|
190
|
+
|
|
191
|
+
log "Hook triggered for tool: $tool_name"
|
|
192
|
+
|
|
193
|
+
# Only process file modification tools
|
|
194
|
+
case "$tool_name" in
|
|
195
|
+
"Edit"|"Write"|"MultiEdit")
|
|
196
|
+
;;
|
|
197
|
+
*)
|
|
198
|
+
log "Skipping non-file tool: $tool_name"
|
|
199
|
+
exit 0
|
|
200
|
+
;;
|
|
201
|
+
esac
|
|
202
|
+
|
|
203
|
+
# Get file content to analyze
|
|
204
|
+
if [[ -n "$file_path" ]] && [[ -f "$file_path" ]]; then
|
|
205
|
+
content=$(cat "$file_path" 2>/dev/null || echo "")
|
|
206
|
+
elif [[ -n "$CLAUDE_CONTENT" ]]; then
|
|
207
|
+
content="$CLAUDE_CONTENT"
|
|
208
|
+
file_path="${file_path:-stdin}"
|
|
209
|
+
else
|
|
210
|
+
log "No content to analyze"
|
|
211
|
+
exit 0
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
# Perform security scans
|
|
215
|
+
local credential_violations
|
|
216
|
+
local env_violations
|
|
217
|
+
|
|
218
|
+
credential_violations=$(scan_file_content "$file_path" "$content")
|
|
219
|
+
env_violations=$(check_environment_leakage "$content")
|
|
220
|
+
|
|
221
|
+
local total_violations=$((credential_violations + env_violations))
|
|
222
|
+
|
|
223
|
+
# Block if violations found
|
|
224
|
+
if [[ $total_violations -gt 0 ]]; then
|
|
225
|
+
echo "🚨 SECURITY VIOLATION: Credential exposure detected!"
|
|
226
|
+
echo "File: $file_path"
|
|
227
|
+
echo "Violations: $total_violations"
|
|
228
|
+
echo ""
|
|
229
|
+
echo "The operation has been BLOCKED to prevent credential exposure."
|
|
230
|
+
echo "Please review the file and remove any exposed credentials before proceeding."
|
|
231
|
+
echo ""
|
|
232
|
+
echo "Common fixes:"
|
|
233
|
+
echo "- Move credentials to environment variables"
|
|
234
|
+
echo "- Use a secrets management system"
|
|
235
|
+
echo "- Add files to .gitignore if they contain test data"
|
|
236
|
+
echo "- Use placeholder values in examples"
|
|
237
|
+
echo ""
|
|
238
|
+
echo "For emergency override (NOT RECOMMENDED):"
|
|
239
|
+
echo "export CLAUDE_SECURITY_OVERRIDE=true"
|
|
240
|
+
|
|
241
|
+
log_violation "BLOCKED: $total_violations violations in $file_path"
|
|
242
|
+
|
|
243
|
+
# Check for emergency override
|
|
244
|
+
if [[ "${CLAUDE_SECURITY_OVERRIDE:-false}" == "true" ]]; then
|
|
245
|
+
log "WARNING: Security override used - allowing dangerous operation"
|
|
246
|
+
echo "⚠️ WARNING: Security override enabled - proceeding with credential exposure risk"
|
|
247
|
+
exit 0
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
exit 1
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
log "Security scan passed for $file_path"
|
|
254
|
+
exit 0
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
##################################
|
|
258
|
+
# Error Handling
|
|
259
|
+
##################################
|
|
260
|
+
trap 'log "Hook failed with error on line $LINENO"' ERR
|
|
261
|
+
|
|
262
|
+
##################################
|
|
263
|
+
# Execute Main Function
|
|
264
|
+
##################################
|
|
265
|
+
main "$@"
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Claude Code Hook: Simple Subagent Trigger
|
|
5
|
+
#
|
|
6
|
+
# Purpose: Lightweight trigger for delegating to any subagent
|
|
7
|
+
# Usage: subagent-trigger-simple.sh <subagent-name> [event-type] [context]
|
|
8
|
+
# Approach: Minimal orchestration - gather context and delegate to subagents
|
|
9
|
+
#
|
|
10
|
+
# This is the simplified version of the original 253-line subagent-trigger.sh,
|
|
11
|
+
# focusing on clean delegation rather than complex orchestration.
|
|
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/context-manager.sh"
|
|
22
|
+
source "$LIB_DIR/error-handler.sh"
|
|
23
|
+
|
|
24
|
+
##################################
|
|
25
|
+
# Usage Information
|
|
26
|
+
##################################
|
|
27
|
+
show_usage() {
|
|
28
|
+
cat <<EOF
|
|
29
|
+
Usage: subagent-trigger-simple.sh <subagent-name> [event-type] [additional-context]
|
|
30
|
+
|
|
31
|
+
Lightweight subagent trigger for event-driven AI assistance.
|
|
32
|
+
|
|
33
|
+
Arguments:
|
|
34
|
+
subagent-name Name of the subagent to invoke (required)
|
|
35
|
+
event-type Type of event (default: manual)
|
|
36
|
+
additional-context Additional context information (optional)
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
subagent-trigger-simple.sh security-auditor pre_write
|
|
40
|
+
subagent-trigger-simple.sh style-enforcer pre_commit "Check Python files"
|
|
41
|
+
subagent-trigger-simple.sh debug-specialist on_error "ImportError in main.py"
|
|
42
|
+
|
|
43
|
+
Available Events: ${SUPPORTED_EVENTS[*]}
|
|
44
|
+
EOF
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
##################################
|
|
48
|
+
# Simple Context Gathering
|
|
49
|
+
##################################
|
|
50
|
+
gather_simple_context() {
|
|
51
|
+
local subagent_name="$1"
|
|
52
|
+
local event_type="$2"
|
|
53
|
+
local additional_context="$3"
|
|
54
|
+
|
|
55
|
+
# Create lightweight context - much simpler than the original
|
|
56
|
+
local context_data
|
|
57
|
+
context_data=$(cat <<EOF
|
|
58
|
+
{
|
|
59
|
+
"trigger": "simple_subagent_trigger",
|
|
60
|
+
"subagent": "$subagent_name",
|
|
61
|
+
"event": "$event_type",
|
|
62
|
+
"additional_context": "$additional_context",
|
|
63
|
+
"environment": {
|
|
64
|
+
"tool": "${CLAUDE_TOOL:-unknown}",
|
|
65
|
+
"file": "${CLAUDE_FILE:-none}",
|
|
66
|
+
"user": "$USER",
|
|
67
|
+
"working_directory": "$(pwd)",
|
|
68
|
+
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
69
|
+
"session_id": "${CLAUDE_SESSION_ID:-$$}"
|
|
70
|
+
},
|
|
71
|
+
"project": {
|
|
72
|
+
"git_branch": "$(git branch --show-current 2>/dev/null || echo 'not-in-git')"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
EOF
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
echo "$context_data"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
##################################
|
|
82
|
+
# Subagent Validation
|
|
83
|
+
##################################
|
|
84
|
+
validate_subagent_exists() {
|
|
85
|
+
local subagent_name="$1"
|
|
86
|
+
|
|
87
|
+
# Simple existence check - leverage the existing validation if needed
|
|
88
|
+
local common_subagents=("security-auditor" "style-enforcer" "debug-specialist" "test-writer")
|
|
89
|
+
|
|
90
|
+
for known_subagent in "${common_subagents[@]}"; do
|
|
91
|
+
if [[ "$subagent_name" == "$known_subagent" ]]; then
|
|
92
|
+
return 0
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
|
|
96
|
+
# If not a known subagent, still allow but warn
|
|
97
|
+
log_warning "Subagent '$subagent_name' not in known list, proceeding anyway"
|
|
98
|
+
return 0
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
##################################
|
|
102
|
+
# Simple Delegation
|
|
103
|
+
##################################
|
|
104
|
+
delegate_to_subagent() {
|
|
105
|
+
local subagent_name="$1"
|
|
106
|
+
local event_type="$2"
|
|
107
|
+
local context="$3"
|
|
108
|
+
|
|
109
|
+
log_info "Delegating to subagent: $subagent_name for event: $event_type"
|
|
110
|
+
|
|
111
|
+
echo "🤖 SUBAGENT TRIGGER: Invoking $subagent_name"
|
|
112
|
+
echo ""
|
|
113
|
+
echo "Event: $event_type"
|
|
114
|
+
echo "Triggered by: ${CLAUDE_TOOL:-manual}"
|
|
115
|
+
echo "Target: ${CLAUDE_FILE:-general}"
|
|
116
|
+
echo "Time: $(date)"
|
|
117
|
+
echo ""
|
|
118
|
+
echo "Context for $subagent_name:"
|
|
119
|
+
echo "$context" | jq . 2>/dev/null || echo "$context"
|
|
120
|
+
echo ""
|
|
121
|
+
echo "🎯 REQUEST:"
|
|
122
|
+
echo "Please handle this $event_type event with your specialized expertise."
|
|
123
|
+
echo "Analyze the context above and provide appropriate assistance."
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
##################################
|
|
127
|
+
# Input Validation
|
|
128
|
+
##################################
|
|
129
|
+
validate_arguments() {
|
|
130
|
+
local subagent_name="$1"
|
|
131
|
+
local event_type="$2"
|
|
132
|
+
|
|
133
|
+
# Basic argument validation
|
|
134
|
+
if [[ -z "$subagent_name" ]]; then
|
|
135
|
+
echo "ERROR: Subagent name is required" >&2
|
|
136
|
+
show_usage >&2
|
|
137
|
+
return 1
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# Validate event type if provided
|
|
141
|
+
if [[ -n "$event_type" ]] && [[ "$event_type" != "manual" ]]; then
|
|
142
|
+
if ! is_supported_event "$event_type"; then
|
|
143
|
+
log_warning "Event type '$event_type' not in supported list"
|
|
144
|
+
log_info "Supported events: ${SUPPORTED_EVENTS[*]}"
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
return 0
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
##################################
|
|
152
|
+
# Main Logic (Simplified)
|
|
153
|
+
##################################
|
|
154
|
+
main() {
|
|
155
|
+
local subagent_name="${1:-}"
|
|
156
|
+
local event_type="${2:-manual}"
|
|
157
|
+
local additional_context="${3:-}"
|
|
158
|
+
|
|
159
|
+
# Handle help request
|
|
160
|
+
if [[ "$subagent_name" == "--help" ]] || [[ "$subagent_name" == "-h" ]] || [[ -z "$subagent_name" ]]; then
|
|
161
|
+
show_usage
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Initialize minimal error handling
|
|
166
|
+
initialize_error_handling || {
|
|
167
|
+
echo "ERROR: Failed to initialize error handling" >&2
|
|
168
|
+
exit 1
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Validate input arguments
|
|
172
|
+
if ! validate_arguments "$subagent_name" "$event_type"; then
|
|
173
|
+
exit 1
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Validate subagent exists (lenient check)
|
|
177
|
+
validate_subagent_exists "$subagent_name"
|
|
178
|
+
|
|
179
|
+
# Gather context (much simpler than original)
|
|
180
|
+
local context
|
|
181
|
+
context=$(gather_simple_context "$subagent_name" "$event_type" "$additional_context")
|
|
182
|
+
|
|
183
|
+
# Delegate to subagent (no complex execution engine needed)
|
|
184
|
+
delegate_to_subagent "$subagent_name" "$event_type" "$context"
|
|
185
|
+
|
|
186
|
+
log_info "Simple trigger completed for: $subagent_name"
|
|
187
|
+
exit 0
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
##################################
|
|
191
|
+
# Execute (Clean and Simple)
|
|
192
|
+
##################################
|
|
193
|
+
main "$@"
|