@amsterdamdatalabs/enact-extensions 0.1.0 → 0.1.3

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 (245) hide show
  1. package/README.md +96 -21
  2. package/dist/index.d.ts +5 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/install.d.ts +171 -1
  7. package/dist/install.d.ts.map +1 -1
  8. package/dist/install.js +402 -49
  9. package/dist/install.js.map +1 -1
  10. package/dist/internal/codex.d.ts.map +1 -1
  11. package/dist/internal/codex.js +7 -1
  12. package/dist/internal/codex.js.map +1 -1
  13. package/dist/internal/platform.d.ts +8 -0
  14. package/dist/internal/platform.d.ts.map +1 -1
  15. package/dist/internal/platform.js +46 -2
  16. package/dist/internal/platform.js.map +1 -1
  17. package/dist/provision.d.ts +30 -0
  18. package/dist/provision.d.ts.map +1 -0
  19. package/dist/provision.js +202 -0
  20. package/dist/provision.js.map +1 -0
  21. package/dist/validate/index.d.ts +44 -0
  22. package/dist/validate/index.d.ts.map +1 -1
  23. package/dist/validate/index.js +157 -0
  24. package/dist/validate/index.js.map +1 -1
  25. package/extensions/cmux/.agents/plugin.json +37 -0
  26. package/extensions/cmux/skills/cmux/SKILL.md +82 -0
  27. package/extensions/cmux/skills/cmux/agents/openai.yaml +4 -0
  28. package/extensions/cmux/skills/cmux/references/handles-and-identify.md +35 -0
  29. package/extensions/cmux/skills/cmux/references/panes-surfaces.md +37 -0
  30. package/extensions/cmux/skills/cmux/references/trigger-flash-and-health.md +23 -0
  31. package/extensions/cmux/skills/cmux/references/windows-workspaces.md +31 -0
  32. package/extensions/cmux/skills/cmux-vm-monitor/SKILL.md +122 -0
  33. package/extensions/cmux/skills/cmux-vm-monitor/agents/openai.yaml +4 -0
  34. package/extensions/cmux/skills/cmux-vm-monitor/references/cmux-commands.md +66 -0
  35. package/extensions/cmux/skills/cmux-vm-monitor/scripts/codex_vm_monitor.sh +45 -0
  36. package/extensions/cmux/skills/cmux-workspace/SKILL.md +93 -0
  37. package/extensions/dev-state/.agents/plugin.json +35 -0
  38. package/extensions/dev-state/skills/dev-state-plan-graduation/SKILL.md +194 -0
  39. package/extensions/dev-state/skills/dev-state-plan-graduation/agents/openai.yaml +4 -0
  40. package/extensions/dev-state/skills/dev-state-plan-graduation/references/reference.md +130 -0
  41. package/extensions/devops/.agents/plugin.json +36 -0
  42. package/extensions/devops/skills/azure-devops-cli/SKILL.md +431 -0
  43. package/extensions/devops/skills/azure-devops-cli/agents/openai.yaml +4 -0
  44. package/extensions/devops/skills/ci-pipeline-strategy/SKILL.md +217 -0
  45. package/extensions/devops/skills/ci-pipeline-strategy/agents/openai.yaml +4 -0
  46. package/extensions/enact-context/.agents/plugin.json +40 -0
  47. package/extensions/enact-context/.mcp.json +8 -0
  48. package/extensions/enact-context/README.md +25 -0
  49. package/extensions/enact-context/assets/icon.png +0 -0
  50. package/extensions/enact-context/assets/logo.png +0 -0
  51. package/extensions/enact-context/hooks/hooks.json +115 -0
  52. package/extensions/enact-context/skills/enact-context/SKILL.md +149 -0
  53. package/extensions/enact-context/skills/enact-context/scripts/install.sh +69 -0
  54. package/extensions/enact-factory/.agents/plugin.json +42 -0
  55. package/extensions/enact-factory/.mcp.json +8 -0
  56. package/extensions/enact-factory/assets/icon.png +0 -0
  57. package/extensions/enact-factory/assets/logo.png +0 -0
  58. package/extensions/enact-factory/hooks/user-prompt-submit.mjs +67 -0
  59. package/extensions/enact-factory/skills/testing-strategy/SKILL.md +167 -0
  60. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +22 -0
  61. package/extensions/enact-operator/.agents/plugin.json +57 -0
  62. package/extensions/enact-operator/.app.json +3 -0
  63. package/extensions/enact-operator/.mcp.json +10 -0
  64. package/extensions/enact-operator/_taxonomy.md +86 -0
  65. package/extensions/enact-operator/agents/README.md +5 -0
  66. package/extensions/enact-operator/agents/architect.toml +25 -0
  67. package/extensions/enact-operator/agents/code-reviewer.toml +24 -0
  68. package/extensions/enact-operator/agents/critic.toml +30 -0
  69. package/extensions/enact-operator/agents/executor.toml +24 -0
  70. package/extensions/enact-operator/agents/explore.toml +23 -0
  71. package/extensions/enact-operator/agents/planner.toml +24 -0
  72. package/extensions/enact-operator/agents/verifier.toml +24 -0
  73. package/extensions/enact-operator/assets/icon.png +0 -0
  74. package/extensions/enact-operator/assets/logo.png +0 -0
  75. package/extensions/enact-operator/commands/doctor.md +39 -0
  76. package/extensions/enact-operator/commands/setup.md +51 -0
  77. package/extensions/enact-operator/hooks/hooks.json +146 -0
  78. package/extensions/enact-operator/skills/_variants.md +44 -0
  79. package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +50 -0
  80. package/extensions/enact-operator/skills/analyze/SKILL.md +91 -0
  81. package/extensions/enact-operator/skills/ask/SKILL.md +47 -0
  82. package/extensions/enact-operator/skills/autopilot/SKILL.md +170 -0
  83. package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +79 -0
  84. package/extensions/enact-operator/skills/cancel/SKILL.md +99 -0
  85. package/extensions/enact-operator/skills/configure-notifications/SKILL.md +77 -0
  86. package/extensions/enact-operator/skills/deep-interview/SKILL.md +80 -0
  87. package/extensions/enact-operator/skills/doctor/SKILL.md +48 -0
  88. package/extensions/enact-operator/skills/hud/SKILL.md +49 -0
  89. package/extensions/enact-operator/skills/hyperplan/SKILL.md +47 -0
  90. package/extensions/enact-operator/skills/plan/SKILL.md +78 -0
  91. package/extensions/enact-operator/skills/ralph/SKILL.md +201 -0
  92. package/extensions/enact-operator/skills/ralph/gemini.md +18 -0
  93. package/extensions/enact-operator/skills/ralplan/SKILL.md +151 -0
  94. package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +45 -0
  95. package/extensions/enact-operator/skills/research/SKILL.md +74 -0
  96. package/extensions/enact-operator/skills/review/SKILL.md +58 -0
  97. package/extensions/enact-operator/skills/security-research/SKILL.md +54 -0
  98. package/extensions/enact-operator/skills/setup/SKILL.md +91 -0
  99. package/extensions/enact-operator/skills/setup/scripts/install.sh +50 -0
  100. package/extensions/enact-operator/skills/skill/SKILL.md +82 -0
  101. package/extensions/enact-operator/skills/tdd/SKILL.md +59 -0
  102. package/extensions/enact-operator/skills/team/SKILL.md +199 -0
  103. package/extensions/enact-operator/skills/trace/SKILL.md +41 -0
  104. package/extensions/enact-operator/skills/ultragoal/SKILL.md +99 -0
  105. package/extensions/enact-operator/skills/ultraqa/SKILL.md +113 -0
  106. package/extensions/enact-operator/skills/ultrawork/SKILL.md +145 -0
  107. package/extensions/enact-operator/skills/ultrawork/planner.md +28 -0
  108. package/extensions/enact-operator/skills/wiki/SKILL.md +41 -0
  109. package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +51 -0
  110. package/extensions/enact-wiki/.agents/plugin.json +42 -0
  111. package/extensions/enact-wiki/.mcp.json +15 -0
  112. package/extensions/enact-wiki/README.md +44 -0
  113. package/extensions/enact-wiki/assets/icon.png +0 -0
  114. package/extensions/enact-wiki/assets/logo.png +0 -0
  115. package/extensions/enact-wiki/skills/document-parser/SKILL.md +17 -0
  116. package/extensions/enact-wiki/skills/document-parser/scripts/parse.sh +60 -0
  117. package/extensions/enact-wiki/skills/document-parser/skill.json +9 -0
  118. package/extensions/enact-wiki/skills/enact-wiki/SKILL.md +30 -0
  119. package/extensions/enact-wiki/skills/enact-wiki/references/ingest.md +62 -0
  120. package/extensions/enact-wiki/skills/enact-wiki/references/manage.md +34 -0
  121. package/extensions/enact-wiki/skills/enact-wiki/references/query.md +59 -0
  122. package/extensions/enact-wiki/skills/search-lab/SKILL.md +57 -0
  123. package/extensions/enact-wiki/skills/search-lab/scripts/analyze.ts +23 -0
  124. package/{plugins/net-revenue-management/.codex-plugin → extensions/net-revenue-management/.agents}/plugin.json +10 -6
  125. package/extensions/plugin-dev/.agents/plugin.json +42 -0
  126. package/extensions/plugin-dev/.mcp.json +3 -0
  127. package/extensions/plugin-dev/agents/agent-creator.md +199 -0
  128. package/extensions/plugin-dev/agents/plugin-validator.md +91 -0
  129. package/extensions/plugin-dev/agents/skill-reviewer.md +212 -0
  130. package/extensions/plugin-dev/commands/_archive/create-marketplace.md +427 -0
  131. package/extensions/plugin-dev/commands/_archive/plugin-dev-guide.md +12 -0
  132. package/extensions/plugin-dev/commands/create-plugin.md +498 -0
  133. package/extensions/plugin-dev/commands/start.md +81 -0
  134. package/extensions/plugin-dev/hooks/hooks.json +3 -0
  135. package/extensions/plugin-dev/skills/agent-development/SKILL.md +641 -0
  136. package/extensions/plugin-dev/skills/agent-development/examples/agent-creation-prompt.md +250 -0
  137. package/extensions/plugin-dev/skills/agent-development/examples/complete-agent-examples.md +461 -0
  138. package/extensions/plugin-dev/skills/agent-development/references/advanced-agent-fields.md +246 -0
  139. package/extensions/plugin-dev/skills/agent-development/references/agent-creation-system-prompt.md +216 -0
  140. package/extensions/plugin-dev/skills/agent-development/references/permission-modes-rules.md +226 -0
  141. package/extensions/plugin-dev/skills/agent-development/references/system-prompt-design.md +464 -0
  142. package/extensions/plugin-dev/skills/agent-development/references/triggering-examples.md +474 -0
  143. package/extensions/plugin-dev/skills/agent-development/scripts/create-agent-skeleton.sh +176 -0
  144. package/extensions/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh +227 -0
  145. package/extensions/plugin-dev/skills/agent-development/scripts/validate-agent.sh +227 -0
  146. package/extensions/plugin-dev/skills/command-development/SKILL.md +763 -0
  147. package/extensions/plugin-dev/skills/command-development/examples/plugin-commands.md +612 -0
  148. package/extensions/plugin-dev/skills/command-development/examples/simple-commands.md +527 -0
  149. package/extensions/plugin-dev/skills/command-development/references/advanced-workflows.md +762 -0
  150. package/extensions/plugin-dev/skills/command-development/references/documentation-patterns.md +769 -0
  151. package/extensions/plugin-dev/skills/command-development/references/frontmatter-reference.md +508 -0
  152. package/extensions/plugin-dev/skills/command-development/references/interactive-commands.md +966 -0
  153. package/extensions/plugin-dev/skills/command-development/references/marketplace-considerations.md +943 -0
  154. package/extensions/plugin-dev/skills/command-development/references/plugin-features-reference.md +637 -0
  155. package/extensions/plugin-dev/skills/command-development/references/plugin-integration.md +191 -0
  156. package/extensions/plugin-dev/skills/command-development/references/skill-tool.md +447 -0
  157. package/extensions/plugin-dev/skills/command-development/references/testing-strategies.md +723 -0
  158. package/extensions/plugin-dev/skills/command-development/scripts/check-frontmatter.sh +234 -0
  159. package/extensions/plugin-dev/skills/command-development/scripts/validate-command.sh +160 -0
  160. package/extensions/plugin-dev/skills/hook-development/SKILL.md +861 -0
  161. package/extensions/plugin-dev/skills/hook-development/examples/load-context.sh +55 -0
  162. package/extensions/plugin-dev/skills/hook-development/examples/validate-bash.sh +57 -0
  163. package/extensions/plugin-dev/skills/hook-development/examples/validate-write.sh +48 -0
  164. package/extensions/plugin-dev/skills/hook-development/references/advanced.md +871 -0
  165. package/extensions/plugin-dev/skills/hook-development/references/hook-input-schemas.md +145 -0
  166. package/extensions/plugin-dev/skills/hook-development/references/migration.md +392 -0
  167. package/extensions/plugin-dev/skills/hook-development/references/patterns.md +430 -0
  168. package/extensions/plugin-dev/skills/hook-development/scripts/README.md +181 -0
  169. package/extensions/plugin-dev/skills/hook-development/scripts/hook-linter.sh +153 -0
  170. package/extensions/plugin-dev/skills/hook-development/scripts/test-hook.sh +276 -0
  171. package/extensions/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh +159 -0
  172. package/extensions/plugin-dev/skills/mcp-integration/SKILL.md +775 -0
  173. package/extensions/plugin-dev/skills/mcp-integration/examples/http-server.json +20 -0
  174. package/extensions/plugin-dev/skills/mcp-integration/examples/sse-server.json +19 -0
  175. package/extensions/plugin-dev/skills/mcp-integration/examples/stdio-server.json +38 -0
  176. package/extensions/plugin-dev/skills/mcp-integration/examples/ws-server.json +26 -0
  177. package/extensions/plugin-dev/skills/mcp-integration/references/authentication.md +601 -0
  178. package/extensions/plugin-dev/skills/mcp-integration/references/server-discovery.md +190 -0
  179. package/extensions/plugin-dev/skills/mcp-integration/references/server-types.md +572 -0
  180. package/extensions/plugin-dev/skills/mcp-integration/references/tool-usage.md +623 -0
  181. package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +222 -0
  182. package/extensions/plugin-dev/skills/plugin-structure/SKILL.md +705 -0
  183. package/extensions/plugin-dev/skills/plugin-structure/examples/advanced-plugin.md +774 -0
  184. package/extensions/plugin-dev/skills/plugin-structure/examples/minimal-plugin.md +83 -0
  185. package/extensions/plugin-dev/skills/plugin-structure/examples/standard-plugin.md +611 -0
  186. package/extensions/plugin-dev/skills/plugin-structure/references/advanced-topics.md +289 -0
  187. package/extensions/plugin-dev/skills/plugin-structure/references/component-patterns.md +592 -0
  188. package/extensions/plugin-dev/skills/plugin-structure/references/github-actions.md +233 -0
  189. package/extensions/plugin-dev/skills/plugin-structure/references/headless-ci-mode.md +193 -0
  190. package/extensions/plugin-dev/skills/plugin-structure/references/manifest-reference.md +625 -0
  191. package/extensions/plugin-dev/skills/plugin-structure/references/output-styles.md +116 -0
  192. package/extensions/plugin-dev/skills/skill-development/SKILL.md +564 -0
  193. package/extensions/plugin-dev/skills/skill-development/examples/complete-skill.md +465 -0
  194. package/extensions/plugin-dev/skills/skill-development/examples/frontmatter-templates.md +167 -0
  195. package/extensions/plugin-dev/skills/skill-development/examples/minimal-skill.md +111 -0
  196. package/extensions/plugin-dev/skills/skill-development/references/advanced-frontmatter.md +225 -0
  197. package/extensions/plugin-dev/skills/skill-development/references/commands-vs-skills.md +39 -0
  198. package/extensions/plugin-dev/skills/skill-development/references/skill-creation-workflow.md +379 -0
  199. package/extensions/plugin-dev/skills/skill-development/references/skill-creator-original.md +210 -0
  200. package/package.json +8 -11
  201. package/scripts/enact-extensions.mjs +823 -21
  202. package/scripts/hooks/session-start-drift-check.mjs +58 -0
  203. package/scripts/lib/build-index.mjs +50 -0
  204. package/scripts/lib/bundle-hash.mjs +137 -0
  205. package/scripts/lib/hooks.mjs +741 -0
  206. package/scripts/lib/ledger.mjs +163 -0
  207. package/scripts/lib/list-bundles.mjs +70 -0
  208. package/scripts/lib/outdated.mjs +144 -0
  209. package/scripts/lib/provision-mcp.mjs +16 -0
  210. package/scripts/lib/resolve-bundle.mjs +121 -0
  211. package/scripts/lib/run-install.mjs +402 -38
  212. package/scripts/lib/run-prune.mjs +73 -0
  213. package/scripts/lib/run-sync.mjs +9 -1
  214. package/scripts/lib/run-uninstall.mjs +244 -0
  215. package/scripts/lib/run-update.mjs +152 -0
  216. package/scripts/lib/run-validate.mjs +21 -18
  217. package/scripts/lib/serve.mjs +472 -0
  218. package/scripts/postinstall.mjs +63 -0
  219. package/scripts/setup-enact-context.sh +2 -2
  220. package/scripts/version-bump.sh +463 -0
  221. package/spec/codex.json +1 -11
  222. package/spec/index.json +59 -0
  223. package/web/assets/README.md +111 -0
  224. package/web/assets/logo-full.png +0 -0
  225. package/web/assets/logo-slim.png +0 -0
  226. package/web/assets/tokens/base.css +45 -0
  227. package/web/assets/tokens/colors.css +248 -0
  228. package/web/assets/tokens/effects.css +24 -0
  229. package/web/assets/tokens/fonts.css +8 -0
  230. package/web/assets/tokens/index.css +18 -0
  231. package/web/assets/tokens/spacing.css +50 -0
  232. package/web/index.html +1188 -0
  233. package/.agents/plugins/marketplace.json +0 -20
  234. package/catalog/enact-context.json +0 -9
  235. package/catalog/enact-factory.json +0 -7
  236. package/catalog/enact-operator.json +0 -7
  237. package/catalog/enact-wiki.json +0 -7
  238. package/catalog/net-revenue-management.json +0 -8
  239. package/scripts/rename-supervisor-to-operator.pl +0 -66
  240. package/scripts/sync-manifests.mjs +0 -23
  241. package/scripts/validate-catalog.mjs +0 -37
  242. package/scripts/validate-plugin.mjs +0 -10
  243. /package/{plugins → extensions}/net-revenue-management/.mcp.json +0 -0
  244. /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-risks/SKILL.md +0 -0
  245. /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-scenario/SKILL.md +0 -0
@@ -0,0 +1,153 @@
1
+ #!/bin/bash
2
+ # Hook Linter
3
+ # Checks hook scripts for common issues and best practices
4
+
5
+ set -euo pipefail
6
+
7
+ # Usage
8
+ if [ $# -eq 0 ]; then
9
+ echo "Usage: $0 <hook-script.sh> [hook-script2.sh ...]"
10
+ echo ""
11
+ echo "Checks hook scripts for:"
12
+ echo " - Shebang presence"
13
+ echo " - set -euo pipefail usage"
14
+ echo " - Input reading from stdin"
15
+ echo " - Proper error handling"
16
+ echo " - Variable quoting"
17
+ echo " - Exit code usage"
18
+ echo " - Hardcoded paths"
19
+ echo " - Timeout considerations"
20
+ exit 1
21
+ fi
22
+
23
+ check_script() {
24
+ local script="$1"
25
+ local warnings=0
26
+ local errors=0
27
+
28
+ echo "🔍 Linting: $script"
29
+ echo ""
30
+
31
+ if [ ! -f "$script" ]; then
32
+ echo "❌ Error: File not found"
33
+ return 1
34
+ fi
35
+
36
+ # Check 1: Executable
37
+ if [ ! -x "$script" ]; then
38
+ echo "⚠️ Not executable (chmod +x $script)"
39
+ ((warnings++))
40
+ fi
41
+
42
+ # Check 2: Shebang
43
+ first_line=$(head -1 "$script")
44
+ if [[ ! "$first_line" =~ ^#!/ ]]; then
45
+ echo "❌ Missing shebang (#!/bin/bash)"
46
+ ((errors++))
47
+ fi
48
+
49
+ # Check 3: set -euo pipefail
50
+ if ! grep -q "set -euo pipefail" "$script"; then
51
+ echo "⚠️ Missing 'set -euo pipefail' (recommended for safety)"
52
+ ((warnings++))
53
+ fi
54
+
55
+ # Check 4: Reads from stdin
56
+ if ! grep -Eq "cat|read" "$script"; then
57
+ echo "⚠️ Doesn't appear to read input from stdin"
58
+ ((warnings++))
59
+ fi
60
+
61
+ # Check 5: Uses jq for JSON parsing
62
+ if grep -Eq "tool_input|tool_name" "$script" && ! grep -q "jq" "$script"; then
63
+ echo "⚠️ Parses hook input but doesn't use jq"
64
+ ((warnings++))
65
+ fi
66
+
67
+ # Check 6: Unquoted variables
68
+ if grep -E '\$[A-Za-z_][A-Za-z0-9_]*[^"]' "$script" | grep -v '#' | grep -q .; then
69
+ echo "⚠️ Potentially unquoted variables detected (injection risk)"
70
+ echo " Always use double quotes: \"\$variable\" not \$variable"
71
+ ((warnings++))
72
+ fi
73
+
74
+ # Check 7: Hardcoded paths
75
+ if grep -E '^[^#]*/home/|^[^#]*/usr/|^[^#]*/opt/' "$script" | grep -q .; then
76
+ echo "⚠️ Hardcoded absolute paths detected"
77
+ echo " Use \$CLAUDE_PROJECT_DIR or \$CLAUDE_PLUGIN_ROOT"
78
+ ((warnings++))
79
+ fi
80
+
81
+ # Check 8: Uses CLAUDE_PLUGIN_ROOT
82
+ if ! grep -Eq "CLAUDE_PLUGIN_ROOT|CLAUDE_PROJECT_DIR" "$script"; then
83
+ echo "💡 Tip: Use \$CLAUDE_PLUGIN_ROOT for plugin-relative paths"
84
+ fi
85
+
86
+ # Check 9: Exit codes
87
+ if ! grep -Eq "exit 0|exit 2" "$script"; then
88
+ echo "⚠️ No explicit exit codes (should exit 0 or 2)"
89
+ ((warnings++))
90
+ fi
91
+
92
+ # Check 10: JSON output for decision hooks
93
+ if grep -Eq "PreToolUse|Stop" "$script"; then
94
+ if ! grep -Eq "permissionDecision|decision" "$script"; then
95
+ echo "💡 Tip: PreToolUse/Stop hooks should output decision JSON"
96
+ fi
97
+ fi
98
+
99
+ # Check 11: Long-running commands
100
+ if grep -E 'sleep [0-9]{3,}|while true' "$script" | grep -v '#' | grep -q .; then
101
+ echo "⚠️ Potentially long-running code detected"
102
+ echo " Hooks should complete quickly (< 60s)"
103
+ ((warnings++))
104
+ fi
105
+
106
+ # Check 12: Error messages to stderr
107
+ if grep -Eq 'echo.*".*error|Error|denied|Denied' "$script"; then
108
+ if ! grep -q '>&2' "$script"; then
109
+ echo "⚠️ Error messages should be written to stderr (>&2)"
110
+ ((warnings++))
111
+ fi
112
+ fi
113
+
114
+ # Check 13: Input validation
115
+ if ! grep -Eq "if.*empty|if.*null|if.*-z" "$script"; then
116
+ echo "💡 Tip: Consider validating input fields aren't empty"
117
+ fi
118
+
119
+ echo ""
120
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
121
+
122
+ if [ $errors -eq 0 ] && [ $warnings -eq 0 ]; then
123
+ echo "✅ No issues found"
124
+ return 0
125
+ elif [ $errors -eq 0 ]; then
126
+ echo "⚠️ Found $warnings warning(s)"
127
+ return 0
128
+ else
129
+ echo "❌ Found $errors error(s) and $warnings warning(s)"
130
+ return 1
131
+ fi
132
+ }
133
+
134
+ echo "🔎 Hook Script Linter"
135
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
136
+ echo ""
137
+
138
+ total_errors=0
139
+
140
+ for script in "$@"; do
141
+ if ! check_script "$script"; then
142
+ ((total_errors++))
143
+ fi
144
+ echo ""
145
+ done
146
+
147
+ if [ $total_errors -eq 0 ]; then
148
+ echo "✅ All scripts passed linting"
149
+ exit 0
150
+ else
151
+ echo "❌ $total_errors script(s) had errors"
152
+ exit 1
153
+ fi
@@ -0,0 +1,276 @@
1
+ #!/bin/bash
2
+ # Hook Testing Helper
3
+ # Tests a hook with sample input and shows output
4
+
5
+ set -euo pipefail
6
+
7
+ # Usage
8
+ show_usage() {
9
+ echo "Usage: $0 [options] <hook-script> <test-input.json>"
10
+ echo ""
11
+ echo "Options:"
12
+ echo " -h, --help Show this help message"
13
+ echo " -v, --verbose Show detailed execution information"
14
+ echo " -t, --timeout N Set timeout in seconds (default: 60)"
15
+ echo ""
16
+ echo "Examples:"
17
+ echo " $0 validate-bash.sh test-input.json"
18
+ echo " $0 -v -t 30 validate-write.sh write-input.json"
19
+ echo ""
20
+ echo "Creates sample test input with:"
21
+ echo " $0 --create-sample <event-type>"
22
+ exit 0
23
+ }
24
+
25
+ # Create sample input
26
+ create_sample() {
27
+ event_type="$1"
28
+
29
+ case "$event_type" in
30
+ PreToolUse)
31
+ cat <<'EOF'
32
+ {
33
+ "session_id": "test-session",
34
+ "transcript_path": "/tmp/transcript.txt",
35
+ "cwd": "/tmp/test-project",
36
+ "permission_mode": "ask",
37
+ "hook_event_name": "PreToolUse",
38
+ "tool_name": "Write",
39
+ "tool_input": {
40
+ "file_path": "/tmp/test.txt",
41
+ "content": "Test content"
42
+ }
43
+ }
44
+ EOF
45
+ ;;
46
+ PostToolUse)
47
+ cat <<'EOF'
48
+ {
49
+ "session_id": "test-session",
50
+ "transcript_path": "/tmp/transcript.txt",
51
+ "cwd": "/tmp/test-project",
52
+ "permission_mode": "ask",
53
+ "hook_event_name": "PostToolUse",
54
+ "tool_name": "Bash",
55
+ "tool_result": "Command executed successfully"
56
+ }
57
+ EOF
58
+ ;;
59
+ Stop|SubagentStop)
60
+ cat <<'EOF'
61
+ {
62
+ "session_id": "test-session",
63
+ "transcript_path": "/tmp/transcript.txt",
64
+ "cwd": "/tmp/test-project",
65
+ "permission_mode": "ask",
66
+ "hook_event_name": "Stop",
67
+ "reason": "Task appears complete"
68
+ }
69
+ EOF
70
+ ;;
71
+ UserPromptSubmit)
72
+ cat <<'EOF'
73
+ {
74
+ "session_id": "test-session",
75
+ "transcript_path": "/tmp/transcript.txt",
76
+ "cwd": "/tmp/test-project",
77
+ "permission_mode": "ask",
78
+ "hook_event_name": "UserPromptSubmit",
79
+ "user_prompt": "Test user prompt"
80
+ }
81
+ EOF
82
+ ;;
83
+ SessionStart|SessionEnd)
84
+ cat <<'EOF'
85
+ {
86
+ "session_id": "test-session",
87
+ "transcript_path": "/tmp/transcript.txt",
88
+ "cwd": "/tmp/test-project",
89
+ "permission_mode": "ask",
90
+ "hook_event_name": "SessionStart"
91
+ }
92
+ EOF
93
+ ;;
94
+ *)
95
+ echo "Unknown event type: $event_type"
96
+ echo "Valid types: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit, SessionStart, SessionEnd"
97
+ exit 1
98
+ ;;
99
+ esac
100
+ }
101
+
102
+ # Parse arguments
103
+ VERBOSE=false
104
+ TIMEOUT=60
105
+
106
+ while [ $# -gt 0 ]; do
107
+ case "$1" in
108
+ -h|--help)
109
+ show_usage
110
+ ;;
111
+ -v|--verbose)
112
+ VERBOSE=true
113
+ shift
114
+ ;;
115
+ -t|--timeout)
116
+ TIMEOUT="$2"
117
+ shift 2
118
+ ;;
119
+ --create-sample)
120
+ create_sample "$2"
121
+ exit 0
122
+ ;;
123
+ *)
124
+ break
125
+ ;;
126
+ esac
127
+ done
128
+
129
+ if [ $# -ne 2 ]; then
130
+ echo "Error: Missing required arguments"
131
+ echo ""
132
+ show_usage
133
+ fi
134
+
135
+ HOOK_SCRIPT="$1"
136
+ TEST_INPUT="$2"
137
+
138
+ # Validate inputs
139
+ if [ ! -f "$HOOK_SCRIPT" ]; then
140
+ echo "❌ Error: Hook script not found: $HOOK_SCRIPT"
141
+ exit 1
142
+ fi
143
+
144
+ # Security: Validate hook script path doesn't contain dangerous characters
145
+ # This prevents potential command injection through maliciously crafted paths
146
+ if [[ "$HOOK_SCRIPT" =~ [\;\|\&\`\$\(\)\{\}\<\>] ]]; then
147
+ echo "❌ Error: Hook script path contains invalid characters"
148
+ echo " Path must not contain: ; | & \` \$ ( ) { } < >"
149
+ exit 1
150
+ fi
151
+
152
+ # Track if we need to invoke with bash explicitly
153
+ HOOK_IS_EXECUTABLE=true
154
+ if [ ! -x "$HOOK_SCRIPT" ]; then
155
+ echo "⚠️ Warning: Hook script is not executable. Attempting to run with bash..."
156
+ HOOK_IS_EXECUTABLE=false
157
+ fi
158
+
159
+ if [ ! -f "$TEST_INPUT" ]; then
160
+ echo "❌ Error: Test input not found: $TEST_INPUT"
161
+ exit 1
162
+ fi
163
+
164
+ # Security: Validate test input path doesn't contain dangerous characters
165
+ # This mirrors the HOOK_SCRIPT validation for defense-in-depth
166
+ if [[ "$TEST_INPUT" =~ [\;\|\&\`\$\(\)\{\}\<\>] ]]; then
167
+ echo "❌ Error: Test input path contains invalid characters"
168
+ echo " Path must not contain: ; | & \` \$ ( ) { } < >"
169
+ exit 1
170
+ fi
171
+
172
+ # Validate test input JSON (with timeout for defensive consistency)
173
+ if ! timeout 5 jq empty "$TEST_INPUT" 2>/dev/null; then
174
+ echo "❌ Error: Test input is not valid JSON"
175
+ exit 1
176
+ fi
177
+
178
+ echo "🧪 Testing hook: $HOOK_SCRIPT"
179
+ echo "📥 Input: $TEST_INPUT"
180
+ echo ""
181
+
182
+ if [ "$VERBOSE" = true ]; then
183
+ echo "Input JSON:"
184
+ jq . "$TEST_INPUT"
185
+ echo ""
186
+ fi
187
+
188
+ # Set up environment
189
+ export CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-/tmp/test-project}"
190
+ export CLAUDE_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(pwd)}"
191
+ export CLAUDE_ENV_FILE="${CLAUDE_ENV_FILE:-/tmp/test-env-$$}"
192
+
193
+ if [ "$VERBOSE" = true ]; then
194
+ echo "Environment:"
195
+ echo " CLAUDE_PROJECT_DIR=$CLAUDE_PROJECT_DIR"
196
+ echo " CLAUDE_PLUGIN_ROOT=$CLAUDE_PLUGIN_ROOT"
197
+ echo " CLAUDE_ENV_FILE=$CLAUDE_ENV_FILE"
198
+ echo ""
199
+ fi
200
+
201
+ # Run the hook
202
+ echo "▶️ Running hook (timeout: ${TIMEOUT}s)..."
203
+ echo ""
204
+
205
+ start_time=$(date +%s)
206
+
207
+ set +e
208
+ # Use proper argument passing to prevent command injection
209
+ # Arguments are passed safely via bash -c's positional parameters
210
+ if [ "$HOOK_IS_EXECUTABLE" = true ]; then
211
+ output=$(timeout "$TIMEOUT" bash -c 'cat "$1" | "$2"' -- "$TEST_INPUT" "$HOOK_SCRIPT" 2>&1)
212
+ else
213
+ output=$(timeout "$TIMEOUT" bash -c 'cat "$1" | bash "$2"' -- "$TEST_INPUT" "$HOOK_SCRIPT" 2>&1)
214
+ fi
215
+ exit_code=$?
216
+ set -e
217
+
218
+ end_time=$(date +%s)
219
+ duration=$((end_time - start_time))
220
+
221
+ # Analyze results
222
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
223
+ echo "Results:"
224
+ echo ""
225
+ echo "Exit Code: $exit_code"
226
+ echo "Duration: ${duration}s"
227
+ echo ""
228
+
229
+ case $exit_code in
230
+ 0)
231
+ echo "✅ Hook approved/succeeded"
232
+ ;;
233
+ 2)
234
+ echo "🚫 Hook blocked/denied"
235
+ ;;
236
+ 124)
237
+ echo "⏱️ Hook timed out after ${TIMEOUT}s"
238
+ ;;
239
+ *)
240
+ echo "⚠️ Hook returned unexpected exit code: $exit_code"
241
+ ;;
242
+ esac
243
+
244
+ echo ""
245
+ echo "Output:"
246
+ if [ -n "$output" ]; then
247
+ echo "$output"
248
+ echo ""
249
+
250
+ # Try to parse as JSON
251
+ if echo "$output" | jq empty 2>/dev/null; then
252
+ echo "Parsed JSON output:"
253
+ echo "$output" | jq .
254
+ fi
255
+ else
256
+ echo "(no output)"
257
+ fi
258
+
259
+ # Check for environment file
260
+ if [ -f "$CLAUDE_ENV_FILE" ]; then
261
+ echo ""
262
+ echo "Environment file created:"
263
+ cat "$CLAUDE_ENV_FILE"
264
+ rm -f "$CLAUDE_ENV_FILE"
265
+ fi
266
+
267
+ echo ""
268
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
269
+
270
+ if [ $exit_code -eq 0 ] || [ $exit_code -eq 2 ]; then
271
+ echo "✅ Test completed successfully"
272
+ exit 0
273
+ else
274
+ echo "❌ Test failed"
275
+ exit 1
276
+ fi
@@ -0,0 +1,159 @@
1
+ #!/bin/bash
2
+ # Hook Schema Validator
3
+ # Validates hooks.json structure and checks for common issues
4
+
5
+ set -euo pipefail
6
+
7
+ # Usage
8
+ if [ $# -eq 0 ]; then
9
+ echo "Usage: $0 <path/to/hooks.json>"
10
+ echo ""
11
+ echo "Validates hook configuration file for:"
12
+ echo " - Valid JSON syntax"
13
+ echo " - Required fields"
14
+ echo " - Hook type validity"
15
+ echo " - Matcher patterns"
16
+ echo " - Timeout ranges"
17
+ exit 1
18
+ fi
19
+
20
+ HOOKS_FILE="$1"
21
+
22
+ if [ ! -f "$HOOKS_FILE" ]; then
23
+ echo "❌ Error: File not found: $HOOKS_FILE"
24
+ exit 1
25
+ fi
26
+
27
+ echo "🔍 Validating hooks configuration: $HOOKS_FILE"
28
+ echo ""
29
+
30
+ # Check 1: Valid JSON
31
+ echo "Checking JSON syntax..."
32
+ if ! jq empty "$HOOKS_FILE" 2>/dev/null; then
33
+ echo "❌ Invalid JSON syntax"
34
+ exit 1
35
+ fi
36
+ echo "✅ Valid JSON"
37
+
38
+ # Check 2: Root structure
39
+ echo ""
40
+ echo "Checking root structure..."
41
+ VALID_EVENTS=("PreToolUse" "PermissionRequest" "PostToolUse" "UserPromptSubmit" "Stop" "SubagentStop" "SessionStart" "SessionEnd" "PreCompact" "Notification")
42
+
43
+ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
44
+ found=false
45
+ for valid_event in "${VALID_EVENTS[@]}"; do
46
+ if [ "$event" = "$valid_event" ]; then
47
+ found=true
48
+ break
49
+ fi
50
+ done
51
+
52
+ if [ "$found" = false ]; then
53
+ echo "⚠️ Unknown event type: $event"
54
+ fi
55
+ done
56
+ echo "✅ Root structure valid"
57
+
58
+ # Check 3: Validate each hook
59
+ echo ""
60
+ echo "Validating individual hooks..."
61
+
62
+ error_count=0
63
+ warning_count=0
64
+
65
+ for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
66
+ hook_count=$(jq -r ".\"$event\" | length" "$HOOKS_FILE")
67
+
68
+ for ((i=0; i<hook_count; i++)); do
69
+ # Check matcher exists
70
+ matcher=$(jq -r ".\"$event\"[$i].matcher // empty" "$HOOKS_FILE")
71
+ if [ -z "$matcher" ]; then
72
+ echo "❌ ${event}[$i]: Missing 'matcher' field"
73
+ ((error_count++))
74
+ continue
75
+ fi
76
+
77
+ # Check hooks array exists
78
+ hooks=$(jq -r ".\"$event\"[$i].hooks // empty" "$HOOKS_FILE")
79
+ if [ -z "$hooks" ] || [ "$hooks" = "null" ]; then
80
+ echo "❌ ${event}[$i]: Missing 'hooks' array"
81
+ ((error_count++))
82
+ continue
83
+ fi
84
+
85
+ # Validate each hook in the array
86
+ hook_array_count=$(jq -r ".\"$event\"[$i].hooks | length" "$HOOKS_FILE")
87
+
88
+ for ((j=0; j<hook_array_count; j++)); do
89
+ hook_type=$(jq -r ".\"$event\"[$i].hooks[$j].type // empty" "$HOOKS_FILE")
90
+
91
+ if [ -z "$hook_type" ]; then
92
+ echo "❌ ${event}[$i].hooks[$j]: Missing 'type' field"
93
+ ((error_count++))
94
+ continue
95
+ fi
96
+
97
+ if [ "$hook_type" != "command" ] && [ "$hook_type" != "prompt" ]; then
98
+ echo "❌ ${event}[$i].hooks[$j]: Invalid type '$hook_type' (must be 'command' or 'prompt')"
99
+ ((error_count++))
100
+ continue
101
+ fi
102
+
103
+ # Check type-specific fields
104
+ if [ "$hook_type" = "command" ]; then
105
+ command=$(jq -r ".\"$event\"[$i].hooks[$j].command // empty" "$HOOKS_FILE")
106
+ if [ -z "$command" ]; then
107
+ echo "❌ ${event}[$i].hooks[$j]: Command hooks must have 'command' field"
108
+ ((error_count++))
109
+ else
110
+ # Check for hardcoded paths
111
+ if [[ "$command" == /* ]] && [[ "$command" != *'${CLAUDE_PLUGIN_ROOT}'* ]]; then
112
+ echo "⚠️ ${event}[$i].hooks[$j]: Hardcoded absolute path detected. Consider using \${CLAUDE_PLUGIN_ROOT}"
113
+ ((warning_count++))
114
+ fi
115
+ fi
116
+ elif [ "$hook_type" = "prompt" ]; then
117
+ prompt=$(jq -r ".\"$event\"[$i].hooks[$j].prompt // empty" "$HOOKS_FILE")
118
+ if [ -z "$prompt" ]; then
119
+ echo "❌ ${event}[$i].hooks[$j]: Prompt hooks must have 'prompt' field"
120
+ ((error_count++))
121
+ fi
122
+
123
+ # Check if prompt-based hooks are used on supported events
124
+ if [ "$event" != "Stop" ] && [ "$event" != "SubagentStop" ] && [ "$event" != "UserPromptSubmit" ] && [ "$event" != "PreToolUse" ]; then
125
+ echo "⚠️ ${event}[$i].hooks[$j]: Prompt hooks may not be fully supported on $event (best on Stop, SubagentStop, UserPromptSubmit, PreToolUse)"
126
+ ((warning_count++))
127
+ fi
128
+ fi
129
+
130
+ # Check timeout
131
+ timeout=$(jq -r ".\"$event\"[$i].hooks[$j].timeout // empty" "$HOOKS_FILE")
132
+ if [ -n "$timeout" ] && [ "$timeout" != "null" ]; then
133
+ if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then
134
+ echo "❌ ${event}[$i].hooks[$j]: Timeout must be a number"
135
+ ((error_count++))
136
+ elif [ "$timeout" -gt 600 ]; then
137
+ echo "⚠️ ${event}[$i].hooks[$j]: Timeout $timeout seconds is very high (max 600s)"
138
+ ((warning_count++))
139
+ elif [ "$timeout" -lt 5 ]; then
140
+ echo "⚠️ ${event}[$i].hooks[$j]: Timeout $timeout seconds is very low"
141
+ ((warning_count++))
142
+ fi
143
+ fi
144
+ done
145
+ done
146
+ done
147
+
148
+ echo ""
149
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
150
+ if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then
151
+ echo "✅ All checks passed!"
152
+ exit 0
153
+ elif [ $error_count -eq 0 ]; then
154
+ echo "⚠️ Validation passed with $warning_count warning(s)"
155
+ exit 0
156
+ else
157
+ echo "❌ Validation failed with $error_count error(s) and $warning_count warning(s)"
158
+ exit 1
159
+ fi