samples.mdx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. ---
  2. title: "Samples"
  3. sidebarTitle: "Samples"
  4. description: "Practical hook examples organized by complexity level - from beginner to advanced patterns"
  5. ---
  6. This page provides complete, production-ready hook examples organized by skill level. Each example includes full working code, detailed explanations, and guidance on when to use each pattern.
  7. ## How to Use These Samples
  8. Each sample is designed to be:
  9. - **Copy-and-paste ready**: Use them directly or as starting points
  10. - **Educational**: Learn hook concepts through progressive complexity
  11. - **Practical**: Solve real development workflow challenges
  12. Choose samples based on your experience level and gradually work up to more advanced patterns.
  13. ---
  14. ## Beginner Examples
  15. Perfect for getting started with hooks. These examples demonstrate core concepts with straightforward logic.
  16. ### 1. Project Type Detection
  17. **Hook:** `TaskStart`
  18. ```bash
  19. #!/usr/bin/env bash
  20. # Project Type Detection Hook
  21. #
  22. # Overview: Automatically detects project type at task start and injects relevant
  23. # coding standards and best practices into the AI context. This helps Cline understand
  24. # your project structure and apply appropriate conventions from the beginning.
  25. #
  26. # Demonstrates: Basic hook input/output, file system checks, conditional logic,
  27. # and context injection to guide AI behavior.
  28. input=$(cat)
  29. # Read basic JSON structure and detect project type
  30. context=""
  31. # Check for different project indicators
  32. if [[ -f "package.json" ]]; then
  33. if grep -q "react" package.json; then
  34. context="PROJECT_TYPE: React application detected. Follow component-based architecture and use functional components."
  35. elif grep -q "express" package.json; then
  36. context="PROJECT_TYPE: Express.js API detected. Follow RESTful patterns and proper middleware structure."
  37. else
  38. context="PROJECT_TYPE: Node.js project detected. Use proper npm scripts and dependency management."
  39. fi
  40. elif [[ -f "requirements.txt" ]] || [[ -f "pyproject.toml" ]]; then
  41. context="PROJECT_TYPE: Python project detected. Follow PEP 8 standards and use virtual environments."
  42. elif [[ -f "Cargo.toml" ]]; then
  43. context="PROJECT_TYPE: Rust project detected. Follow Rust conventions and use proper error handling."
  44. elif [[ -f "go.mod" ]]; then
  45. context="PROJECT_TYPE: Go project detected. Follow Go conventions and use proper package structure."
  46. fi
  47. # Return the context to guide Cline's behavior
  48. if [[ -n "$context" ]]; then
  49. jq -n --arg ctx "$context" '{"cancel": false, "contextModification": $ctx}'
  50. else
  51. echo '{"cancel": false}'
  52. fi
  53. ```
  54. **Key Concepts:**
  55. - Reading hook input with `input=$(cat)`
  56. - Using file system checks to detect project type
  57. - Returning context to influence AI behavior
  58. - Basic JSON output with `jq`
  59. ### 2. File Extension Validator
  60. **Hook:** `PreToolUse`
  61. ```bash
  62. #!/usr/bin/env bash
  63. # File Extension Validator Hook
  64. #
  65. # Overview: Enforces TypeScript file extensions in TypeScript projects by blocking
  66. # creation of .js and .jsx files. This prevents common mistakes where developers
  67. # accidentally create JavaScript files when they should be using TypeScript.
  68. #
  69. # Demonstrates: PreToolUse blocking, parameter extraction, conditional validation,
  70. # and providing clear error messages to guide users toward correct file extensions.
  71. input=$(cat)
  72. # Extract tool information
  73. tool_name=$(echo "$input" | jq -r '.preToolUse.toolName')
  74. # Only process file creation tools
  75. if [[ "$tool_name" != "write_to_file" ]]; then
  76. echo '{"cancel": false}'
  77. exit 0
  78. fi
  79. # Check if this is a TypeScript project
  80. if [[ ! -f "tsconfig.json" ]]; then
  81. echo '{"cancel": false}'
  82. exit 0
  83. fi
  84. # Get the file path from tool parameters
  85. file_path=$(echo "$input" | jq -r '.preToolUse.parameters.path // empty')
  86. if [[ -z "$file_path" ]]; then
  87. echo '{"cancel": false}'
  88. exit 0
  89. fi
  90. # Block .js files in TypeScript projects
  91. if [[ "$file_path" == *.js ]]; then
  92. echo '{"cancel": true, "errorMessage": "JavaScript files (.js) are not allowed in TypeScript projects. Use .ts extension instead."}'
  93. exit 0
  94. fi
  95. # Block .jsx files, suggest .tsx
  96. if [[ "$file_path" == *.jsx ]]; then
  97. echo '{"cancel": true, "errorMessage": "JSX files (.jsx) are not allowed in TypeScript projects. Use .tsx extension instead."}'
  98. exit 0
  99. fi
  100. # Everything is OK
  101. echo '{"cancel": false}'
  102. ```
  103. **Key Concepts:**
  104. - Extracting tool name and parameters
  105. - Conditional logic based on project state
  106. - Blocking operations with `"cancel": true`
  107. - Providing helpful error messages
  108. ### 3. Basic Performance Monitor
  109. **Hook:** `PostToolUse`
  110. ```bash
  111. #!/usr/bin/env bash
  112. # Basic Performance Monitor Hook
  113. #
  114. # Overview: Monitors tool execution times and logs operations that exceed a 3-second
  115. # threshold. This helps identify performance bottlenecks and provides feedback to
  116. # users about system resource issues that may be slowing down Cline's operations.
  117. #
  118. # Demonstrates: PostToolUse hook usage, arithmetic operations in bash, simple file
  119. # logging, and conditional context injection based on performance metrics.
  120. input=$(cat)
  121. # Extract performance information
  122. tool_name=$(echo "$input" | jq -r '.postToolUse.toolName')
  123. execution_time=$(echo "$input" | jq -r '.postToolUse.executionTimeMs // 0')
  124. success=$(echo "$input" | jq -r '.postToolUse.success')
  125. # Log slow operations (threshold: 3 seconds)
  126. if (( execution_time > 3000 )); then
  127. # Create simple log directory
  128. mkdir -p "$HOME/.cline_logs"
  129. # Log the slow operation
  130. echo "$(date -Iseconds): SLOW OPERATION - $tool_name took ${execution_time}ms" >> "$HOME/.cline_logs/performance.log"
  131. # Provide feedback to user
  132. context="PERFORMANCE: Operation $tool_name took ${execution_time}ms. Consider checking system resources if this happens frequently."
  133. jq -n --arg ctx "$context" '{"cancel": false, "contextModification": $ctx}'
  134. else
  135. echo '{"cancel": false}'
  136. fi
  137. ```
  138. **Key Concepts:**
  139. - Processing results after tool execution
  140. - Basic arithmetic operations in bash
  141. - Simple file logging
  142. - Conditional context injection
  143. ## Intermediate Examples
  144. These examples demonstrate more advanced concepts including external tool integration, pattern matching, and structured logging.
  145. ### 4. Code Quality with Linting
  146. **Hook:** `PreToolUse`
  147. ```bash
  148. #!/usr/bin/env bash
  149. # Code Quality Linting Hook
  150. #
  151. # Overview: Integrates ESLint and Flake8 to enforce code quality standards before
  152. # files are written. Blocks file creation if linting errors are detected, ensuring
  153. # all code meets quality standards. Supports TypeScript, JavaScript, and Python files.
  154. #
  155. # Demonstrates: External tool integration, temporary file handling, regex pattern
  156. # matching, and comprehensive error reporting with actionable feedback.
  157. input=$(cat)
  158. tool_name=$(echo "$input" | jq -r '.preToolUse.toolName')
  159. # Only lint file write operations
  160. if [[ "$tool_name" != "write_to_file" ]]; then
  161. echo '{"cancel": false}'
  162. exit 0
  163. fi
  164. file_path=$(echo "$input" | jq -r '.preToolUse.parameters.path // empty')
  165. # Skip non-code files
  166. if [[ ! "$file_path" =~ \.(ts|tsx|js|jsx|py|rs)$ ]]; then
  167. echo '{"cancel": false}'
  168. exit 0
  169. fi
  170. # Get file content from the tool parameters
  171. content=$(echo "$input" | jq -r '.preToolUse.parameters.content // empty')
  172. if [[ -z "$content" ]]; then
  173. echo '{"cancel": false}'
  174. exit 0
  175. fi
  176. # Create temporary file for linting
  177. temp_file=$(mktemp)
  178. echo "$content" > "$temp_file"
  179. # Run appropriate linter based on file extension
  180. lint_errors=""
  181. if [[ "$file_path" =~ \.(ts|tsx)$ ]] && command -v eslint > /dev/null; then
  182. lint_output=$(eslint "$temp_file" --format=json 2>/dev/null || true)
  183. if [[ "$lint_output" != "[]" ]] && [[ -n "$lint_output" ]]; then
  184. error_count=$(echo "$lint_output" | jq '.[0].errorCount // 0')
  185. if (( error_count > 0 )); then
  186. messages=$(echo "$lint_output" | jq -r '.[0].messages[] | "\(.line):\(.column) \(.message)"')
  187. lint_errors="ESLint errors found:\n$messages"
  188. fi
  189. fi
  190. elif [[ "$file_path" =~ \.py$ ]] && command -v flake8 > /dev/null; then
  191. lint_output=$(flake8 "$temp_file" 2>/dev/null || true)
  192. if [[ -n "$lint_output" ]]; then
  193. lint_errors="Flake8 errors found:\n$lint_output"
  194. fi
  195. fi
  196. # Cleanup
  197. rm -f "$temp_file"
  198. # Block if linting errors found
  199. if [[ -n "$lint_errors" ]]; then
  200. error_message="Code quality check failed. Please fix these issues:\n\n$lint_errors"
  201. jq -n --arg msg "$error_message" '{"cancel": true, "errorMessage": $msg}'
  202. else
  203. echo '{"cancel": false}'
  204. fi
  205. ```
  206. **Key Concepts:**
  207. - Temporary file creation and cleanup
  208. - External tool integration (eslint, flake8)
  209. - Complex pattern matching with regex
  210. - Structured error reporting
  211. ### 5. Security Scanner
  212. **Hook:** `PreToolUse`
  213. ```bash
  214. #!/usr/bin/env bash
  215. # Security Scanner Hook
  216. #
  217. # Overview: Scans file content for hardcoded secrets (API keys, tokens, passwords)
  218. # before files are written. Blocks creation of files containing secrets except in
  219. # safe locations like .env.example files or documentation, preventing credential leaks.
  220. #
  221. # Demonstrates: Pattern matching with regex arrays, file path exception handling,
  222. # security-focused validation, and clear user guidance in error messages.
  223. input=$(cat)
  224. tool_name=$(echo "$input" | jq -r '.preToolUse.toolName')
  225. # Only check file operations
  226. if [[ "$tool_name" != "write_to_file" ]]; then
  227. echo '{"cancel": false}'
  228. exit 0
  229. fi
  230. content=$(echo "$input" | jq -r '.preToolUse.parameters.content // empty')
  231. file_path=$(echo "$input" | jq -r '.preToolUse.parameters.path // empty')
  232. # Skip if no content
  233. if [[ -z "$content" ]]; then
  234. echo '{"cancel": false}'
  235. exit 0
  236. fi
  237. # Define secret patterns (simplified for readability)
  238. secrets_found=""
  239. # Check for API keys
  240. if echo "$content" | grep -qi "api[_-]*key.*[=:].*['\"][a-z0-9_-]{10,}['\"]"; then
  241. secrets_found+="- API key pattern detected\n"
  242. fi
  243. # Check for tokens
  244. if echo "$content" | grep -qi "token.*[=:].*['\"][a-z0-9_-]{10,}['\"]"; then
  245. secrets_found+="- Token pattern detected\n"
  246. fi
  247. # Check for passwords
  248. if echo "$content" | grep -qi "password.*[=:].*['\"][^'\"]{8,}['\"]"; then
  249. secrets_found+="- Password pattern detected\n"
  250. fi
  251. # Allow secrets in safe files
  252. safe_patterns=("\.env\.example$" "\.env\.template$" "/docs/" "\.md$")
  253. is_safe_file=false
  254. for safe_pattern in "${safe_patterns[@]}"; do
  255. if [[ "$file_path" =~ $safe_pattern ]]; then
  256. is_safe_file=true
  257. break
  258. fi
  259. done
  260. if [[ -n "$secrets_found" ]] && [[ "$is_safe_file" == false ]]; then
  261. error_message="🔒 SECURITY ALERT: Potential secrets detected in $file_path
  262. $secrets_found
  263. Please use environment variables or a secrets management service instead."
  264. jq -n --arg msg "$error_message" '{"cancel": true, "errorMessage": $msg}'
  265. else
  266. echo '{"cancel": false}'
  267. fi
  268. ```
  269. **Key Concepts:**
  270. - Pattern arrays and iteration
  271. - File path exception handling
  272. - Security-focused validation
  273. - Clear user guidance in error messages
  274. ### 6. Git Workflow Assistant
  275. **Hook:** `PostToolUse`
  276. ```bash
  277. #!/usr/bin/env bash
  278. # Git Workflow Assistant Hook
  279. #
  280. # Overview: Analyzes file modifications and provides intelligent git workflow suggestions
  281. # based on file types and current branch. Encourages best practices like feature branches
  282. # for components and test branches for test files, with actionable git commands.
  283. #
  284. # Demonstrates: Git integration, branch analysis, file path pattern matching, and
  285. # contextual suggestions to guide users toward better git practices.
  286. input=$(cat)
  287. tool_name=$(echo "$input" | jq -r '.postToolUse.toolName')
  288. success=$(echo "$input" | jq -r '.postToolUse.success')
  289. # Only process successful file modifications
  290. if [[ "$success" != "true" ]] || [[ "$tool_name" != "write_to_file" && "$tool_name" != "replace_in_file" ]]; then
  291. echo '{"cancel": false}'
  292. exit 0
  293. fi
  294. # Check if we're in a git repository
  295. if ! git rev-parse --git-dir > /dev/null 2>&1; then
  296. echo '{"cancel": false}'
  297. exit 0
  298. fi
  299. file_path=$(echo "$input" | jq -r '.postToolUse.parameters.path // empty')
  300. current_branch=$(git branch --show-current 2>/dev/null || echo "main")
  301. # Analyze file type and suggest appropriate branch naming
  302. context=""
  303. if [[ "$file_path" == *"component"* ]] && [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
  304. component_name=$(basename "$file_path" .tsx .ts .jsx .js)
  305. context="GIT_WORKFLOW: Consider creating a feature branch: git checkout -b feature/add-${component_name,,}-component"
  306. elif [[ "$file_path" == *"test"* ]] || [[ "$file_path" == *"spec"* ]]; then
  307. if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
  308. context="GIT_WORKFLOW: Consider creating a test branch: git checkout -b test/add-tests-$(basename "$(dirname "$file_path")")"
  309. fi
  310. fi
  311. # Add staging guidance
  312. if [[ -n "$context" ]]; then
  313. context="$context After completing changes, use 'git add $file_path' to stage for commit."
  314. else
  315. context="GIT_WORKFLOW: File modified: $file_path. Use 'git add $file_path' when ready to commit."
  316. fi
  317. jq -n --arg ctx "$context" '{"cancel": false, "contextModification": $ctx}'
  318. ```
  319. **Key Concepts:**
  320. - Git repository detection
  321. - Branch analysis and suggestions
  322. - File path analysis for context
  323. - Actionable user guidance
  324. ## Advanced Examples
  325. These examples showcase sophisticated patterns including external integrations, asynchronous processing, and complex state management.
  326. ### 7. Comprehensive Task Lifecycle Manager
  327. **Hook:** `TaskComplete`
  328. ```bash
  329. #!/usr/bin/env bash
  330. # Comprehensive Task Lifecycle Manager Hook
  331. #
  332. # Overview: Tracks task completions by generating detailed markdown reports with
  333. # workspace information and git state, and optionally sends webhook notifications
  334. # to external systems. Perfect for enterprise environments requiring audit trails.
  335. #
  336. # Demonstrates: Complex data extraction, structured report generation, markdown
  337. # heredocs, asynchronous webhook notifications, and robust error handling.
  338. input=$(cat)
  339. # Extract task metadata using proper API field paths
  340. task_id=$(echo "$input" | jq -r '.taskId')
  341. ulid=$(echo "$input" | jq -r '.taskComplete.taskMetadata.ulid // "unknown"')
  342. completion_time=$(echo "$input" | jq -r '.timestamp')
  343. # Create completion report directory with error handling
  344. reports_dir="$HOME/.cline_reports"
  345. if [[ ! -d "$(dirname "$reports_dir")" ]]; then
  346. echo '{"cancel": false, "errorMessage": "Cannot access home directory"}'
  347. exit 0
  348. fi
  349. mkdir -p "$reports_dir" || exit 0
  350. # Generate safe, unique report filename
  351. safe_task_id=$(echo "$task_id" | tr -cd '[:alnum:]_-' | head -c 50)
  352. report_file="$reports_dir/completion_$(date +%Y%m%d_%H%M%S)_${safe_task_id}.md"
  353. # Collect comprehensive workspace information
  354. git_branch=$(git branch --show-current 2>/dev/null || echo "No git repository")
  355. git_status_count=$(git status --porcelain 2>/dev/null | wc -l || echo "0")
  356. project_name=$(basename "$PWD")
  357. # Generate detailed completion report
  358. cat > "$report_file" << EOF
  359. # Cline Task Completion Report
  360. **Task ID:** $task_id
  361. **ULID:** $ulid
  362. **Completed:** $(date -Iseconds)
  363. **Completion Time:** $completion_time
  364. ## Workspace Information
  365. - **Project:** $project_name
  366. - **Git Branch:** $git_branch
  367. - **Modified Files:** $git_status_count
  368. ## Completion Status
  369. ✅ Task completed successfully
  370. ## Next Steps
  371. - Review changes made during this task
  372. - Consider committing changes if appropriate
  373. - Run tests to verify functionality
  374. EOF
  375. # Send webhook notification if configured
  376. webhook_url="${COMPLETION_WEBHOOK_URL:-}"
  377. if [[ -n "$webhook_url" ]]; then
  378. payload=$(jq -n \
  379. --arg task_id "$task_id" \
  380. --arg ulid "$ulid" \
  381. --arg workspace "$project_name" \
  382. --arg timestamp "$completion_time" \
  383. '{
  384. event: "task_completed",
  385. task_id: $task_id,
  386. ulid: $ulid,
  387. workspace: $workspace,
  388. timestamp: $timestamp
  389. }')
  390. # Send notification in background with timeout
  391. (curl -X POST \
  392. -H "Content-Type: application/json" \
  393. -d "$payload" \
  394. "$webhook_url" \
  395. --max-time 5 \
  396. --silent > /dev/null 2>&1) &
  397. fi
  398. context="TASK_COMPLETED: ✅ Task $task_id finished successfully. Report saved to: $(basename "$report_file")"
  399. jq -n --arg ctx "$context" '{"cancel": false, "contextModification": $ctx}'
  400. ```
  401. **Key Concepts:**
  402. - Complex data extraction and validation
  403. - Structured report generation
  404. - Asynchronous webhook notifications
  405. - Error handling and resource management
  406. ### 8. Intelligent User Input Enhancer
  407. **Hook:** `UserPromptSubmit`
  408. ```bash
  409. #!/usr/bin/env bash
  410. # Intelligent User Input Enhancer Hook
  411. #
  412. # Overview: Analyzes user prompts to detect potentially harmful commands, logs user
  413. # activity for analytics, and intelligently injects project and git context based on
  414. # prompt keywords. Provides safety guards while enhancing AI responses with relevant context.
  415. #
  416. # Demonstrates: UserPromptSubmit hook usage, multi-pattern safety validation, intelligent
  417. # context detection from prompts, structured JSON logging, and dynamic suggestion generation.
  418. input=$(cat)
  419. user_prompt=$(echo "$input" | jq -r '.userPromptSubmit.prompt')
  420. task_id=$(echo "$input" | jq -r '.taskId')
  421. user_id=$(echo "$input" | jq -r '.userId')
  422. # Log user activity for analytics
  423. activity_log="$HOME/.cline_user_activity/$(date +%Y-%m-%d).log"
  424. mkdir -p "$(dirname "$activity_log")"
  425. activity_entry=$(jq -n \
  426. --arg timestamp "$(date -Iseconds)" \
  427. --arg task_id "$task_id" \
  428. --arg user_id "$user_id" \
  429. --arg prompt_length "${#user_prompt}" \
  430. '{
  431. timestamp: $timestamp,
  432. task_id: $task_id,
  433. user_id: $user_id,
  434. prompt_length: ($prompt_length | tonumber),
  435. workspace: env.PWD
  436. }')
  437. echo "$activity_entry" >> "$activity_log"
  438. context_modifications=""
  439. cancel_request=false
  440. # Safety validation
  441. harmful_patterns=("rm -rf" "delete.*all" "format.*drive" "sudo.*passwd")
  442. for pattern in "${harmful_patterns[@]}"; do
  443. if echo "$user_prompt" | grep -qi "$pattern"; then
  444. cancel_request=true
  445. error_message="🚨 SAFETY ALERT: Potentially harmful command detected. Please review your request."
  446. break
  447. fi
  448. done
  449. # Intelligent context enhancement
  450. if [[ "$cancel_request" == false ]]; then
  451. # Detect project context
  452. if echo "$user_prompt" | grep -qi "file\|directory\|folder"; then
  453. if [[ -f "package.json" ]]; then
  454. project_name=$(jq -r '.name // "unknown"' package.json 2>/dev/null)
  455. context_modifications+="PROJECT_CONTEXT: Working in Node.js project '$project_name'. "
  456. elif [[ -f "requirements.txt" ]]; then
  457. context_modifications+="PROJECT_CONTEXT: Working in Python project. "
  458. fi
  459. fi
  460. # Git context enhancement
  461. if echo "$user_prompt" | grep -qi "git\|commit\|branch" && git rev-parse --git-dir > /dev/null 2>&1; then
  462. current_branch=$(git branch --show-current 2>/dev/null)
  463. uncommitted=$(git status --porcelain | wc -l)
  464. context_modifications+="GIT_CONTEXT: On branch '$current_branch' with $uncommitted uncommitted changes. "
  465. fi
  466. # Tool suggestions
  467. if echo "$user_prompt" | grep -qi "search.*code\|find.*function"; then
  468. context_modifications+="SUGGESTION: Consider using search_files tool for code exploration. "
  469. fi
  470. fi
  471. # Return response
  472. if [[ "$cancel_request" == true ]]; then
  473. jq -n --arg msg "$error_message" '{"cancel": true, "errorMessage": $msg}'
  474. else
  475. if [[ -n "$context_modifications" ]]; then
  476. jq -n --arg ctx "$context_modifications" '{"cancel": false, "contextModification": $ctx}'
  477. else
  478. echo '{"cancel": false}'
  479. fi
  480. fi
  481. ```
  482. **Key Concepts:**
  483. - User interaction analysis and logging
  484. - Multi-pattern safety validation
  485. - Intelligent context detection
  486. - Dynamic suggestion generation
  487. ### 9. Multi-Service Integration Hub
  488. **Hook:** `PostToolUse`
  489. ```bash
  490. #!/usr/bin/env bash
  491. # Multi-Service Integration Hub Hook
  492. #
  493. # Overview: Detects file modifications by type (dependencies, CI/CD, frontend, backend, tests)
  494. # and sends asynchronous webhook notifications to multiple external services like Slack and
  495. # CI/CD systems. Enables seamless integration of Cline operations into enterprise workflows.
  496. #
  497. # Demonstrates: Advanced pattern matching with associative arrays, multi-service webhook
  498. # orchestration, asynchronous background processing, and enterprise notification patterns.
  499. input=$(cat)
  500. tool_name=$(echo "$input" | jq -r '.postToolUse.toolName')
  501. success=$(echo "$input" | jq -r '.postToolUse.success')
  502. file_path=$(echo "$input" | jq -r '.postToolUse.parameters.path // empty')
  503. # Only process successful file operations
  504. if [[ "$success" != "true" ]] || [[ "$tool_name" != "write_to_file" && "$tool_name" != "replace_in_file" ]]; then
  505. echo '{"cancel": false}'
  506. exit 0
  507. fi
  508. # Define workflow triggers
  509. declare -A triggers=(
  510. ["package\\.json|yarn\\.lock"]="dependencies"
  511. ["\\.github/workflows/"]="ci_cd"
  512. ["src/.*component"]="frontend"
  513. ["api/.*\\.(ts|js)"]="backend"
  514. [".*\\.(test|spec)\\."]="testing"
  515. )
  516. # Determine triggered workflows
  517. triggered_workflows=""
  518. for pattern in "${!triggers[@]}"; do
  519. if [[ "$file_path" =~ $pattern ]]; then
  520. workflow_type="${triggers[$pattern]}"
  521. triggered_workflows+="$workflow_type "
  522. fi
  523. done
  524. context="WORKFLOW: File modified: $file_path"
  525. if [[ -n "$triggered_workflows" ]]; then
  526. # Slack notification (async)
  527. slack_webhook="${SLACK_WEBHOOK_URL:-}"
  528. if [[ -n "$slack_webhook" ]]; then
  529. slack_payload=$(jq -n \
  530. --arg file "$file_path" \
  531. --arg workflows "$triggered_workflows" \
  532. --arg workspace "$(basename "$PWD")" \
  533. '{
  534. text: ("🔧 Cline modified `" + $file + "` in " + $workspace),
  535. color: "good",
  536. fields: [{
  537. title: "Triggered Workflows",
  538. value: $workflows,
  539. short: true
  540. }]
  541. }')
  542. (curl -X POST -H "Content-Type: application/json" -d "$slack_payload" "$slack_webhook" --max-time 5 --silent > /dev/null 2>&1) &
  543. fi
  544. # CI/CD webhook (async)
  545. ci_webhook="${CI_WEBHOOK_URL:-}"
  546. if [[ -n "$ci_webhook" ]]; then
  547. ci_payload=$(jq -n \
  548. --arg file "$file_path" \
  549. --arg workflows "$triggered_workflows" \
  550. '{
  551. event: "file_modified",
  552. file_path: $file,
  553. workflows: ($workflows | split(" "))
  554. }')
  555. (curl -X POST -H "Content-Type: application/json" -d "$ci_payload" "$ci_webhook" --max-time 5 --silent > /dev/null 2>&1) &
  556. fi
  557. context+=" Triggered workflows: $triggered_workflows. Notifications sent to configured services."
  558. fi
  559. jq -n --arg ctx "$context" '{"cancel": false, "contextModification": $ctx}'
  560. ```
  561. **Key Concepts:**
  562. - Multi-service integration patterns
  563. - Asynchronous webhook orchestration
  564. - Complex workflow detection
  565. - Enterprise notification systems
  566. ## Usage Tips
  567. ### Running Multiple Hooks
  568. You can use multiple hooks together by creating separate files for each hook type:
  569. ```bash
  570. # Create hooks directory
  571. mkdir -p .clinerules/hooks
  572. # Create multiple hooks
  573. touch .clinerules/hooks/PreToolUse
  574. touch .clinerules/hooks/PostToolUse
  575. touch .clinerules/hooks/TaskStart
  576. # Make them executable
  577. chmod +x .clinerules/hooks/*
  578. ```
  579. ### Environment Configuration
  580. Set up environment variables for external integrations:
  581. ```bash
  582. # Add to your .bashrc or .zshrc
  583. export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
  584. export JIRA_URL="https://yourcompany.atlassian.net"
  585. export JIRA_USER="[email protected]"
  586. export JIRA_TOKEN="your-api-token"
  587. export CI_WEBHOOK_URL="https://your-ci-system.com/hooks/cline"
  588. ```
  589. ### Testing Your Hooks
  590. Test hooks manually by simulating their input:
  591. ```bash
  592. # Test a PreToolUse hook
  593. echo '{
  594. "clineVersion": "1.0.0",
  595. "hookName": "PreToolUse",
  596. "timestamp": "2024-01-01T12:00:00Z",
  597. "taskId": "test",
  598. "workspaceRoots": ["/path/to/workspace"],
  599. "userId": "test-user",
  600. "preToolUse": {
  601. "toolName": "write_to_file",
  602. "parameters": {
  603. "path": "test.js",
  604. "content": "console.log(\"test\");"
  605. }
  606. }
  607. }' | .clinerules/hooks/PreToolUse
  608. ```
  609. These examples provide a solid foundation for implementing hooks in your development workflow. Customize them based on your specific needs, tools, and integrations.