ima-claude 2.9.0

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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +1064 -0
  4. package/package.json +49 -0
  5. package/platforms/claude/adapter.ts +115 -0
  6. package/platforms/junie/adapter.ts +254 -0
  7. package/platforms/junie/agents-template.md +113 -0
  8. package/platforms/junie/hook-translations.md +84 -0
  9. package/platforms/shared/detector.ts +27 -0
  10. package/platforms/shared/installer.ts +202 -0
  11. package/platforms/shared/types.ts +78 -0
  12. package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
  13. package/plugins/ima-claude/agents/explorer.md +30 -0
  14. package/plugins/ima-claude/agents/implementer.md +30 -0
  15. package/plugins/ima-claude/agents/memory.md +42 -0
  16. package/plugins/ima-claude/agents/reviewer.md +53 -0
  17. package/plugins/ima-claude/agents/tester.md +33 -0
  18. package/plugins/ima-claude/agents/wp-developer.md +46 -0
  19. package/plugins/ima-claude/hooks/README.md +145 -0
  20. package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
  21. package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
  22. package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
  23. package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
  24. package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
  25. package/plugins/ima-claude/hooks/docs_organization.py +104 -0
  26. package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
  27. package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
  28. package/plugins/ima-claude/hooks/hook_logger.py +69 -0
  29. package/plugins/ima-claude/hooks/hooks.json +239 -0
  30. package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
  31. package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
  32. package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
  33. package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
  34. package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
  35. package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
  36. package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
  37. package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
  38. package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
  39. package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
  40. package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
  41. package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
  42. package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
  43. package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
  44. package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
  45. package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
  46. package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
  47. package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
  48. package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
  49. package/plugins/ima-claude/personalities/README.md +45 -0
  50. package/plugins/ima-claude/personalities/enable-40k.md +69 -0
  51. package/plugins/ima-claude/personalities/enable-templars.md +69 -0
  52. package/plugins/ima-claude/skills/.research-summary.md +340 -0
  53. package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
  54. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
  55. package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
  56. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
  57. package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
  58. package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
  59. package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
  60. package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
  61. package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
  62. package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
  63. package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
  64. package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
  65. package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
  66. package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
  67. package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
  68. package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
  69. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
  70. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
  71. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
  72. package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
  73. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
  74. package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
  75. package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
  76. package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
  77. package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
  78. package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
  79. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
  80. package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
  81. package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
  82. package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
  83. package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
  84. package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
  85. package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
  86. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
  87. package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
  88. package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
  89. package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
  90. package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
  91. package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
  92. package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
  93. package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
  94. package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
  95. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
  96. package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
  97. package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
  98. package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
  99. package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
  100. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
  101. package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
  102. package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
  103. package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
  104. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
  105. package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
  106. package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
  107. package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
  108. package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
  109. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
  110. package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
  111. package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
  112. package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
  113. package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
  114. package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
  115. package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
  116. package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
  117. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
  118. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
  119. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
  120. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
  121. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
  122. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
  123. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
  124. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
  125. package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
  126. package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
  127. package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
  128. package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
  129. package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
  130. package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
  131. package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
  132. package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
  133. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
  134. package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
  135. package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
  136. package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
  137. package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
  138. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
  139. package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
  140. package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
  141. package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
  142. package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
  143. package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
  144. package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
  145. package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
  146. package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
  147. package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
  148. package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
  149. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
  150. package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
  151. package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
  152. package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
  153. package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
  154. package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
  155. package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
  156. package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
  157. package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
  158. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
  159. package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
  160. package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
  161. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
  162. package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
  163. package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
  164. package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
  165. package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
  166. package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
  167. package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
  168. package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
  169. package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
  170. package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
  171. package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  172. package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
  173. package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
  174. package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
  175. package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
  176. package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
  177. package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
  178. package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
  179. package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
  180. package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
  181. package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
  182. package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ UserPromptSubmit hook: Remind Claude to invoke task-master before non-trivial implementation.
4
+
5
+ M7 — Remind about task-master for non-trivial implementation requests.
6
+
7
+ Fires when the prompt contains both an action verb and a scope noun, is longer than
8
+ 30 words, and does not contain trivial-signal words or a skill invocation prefix.
9
+ Fires once per session using a timestamp-based state file.
10
+ Exit code 0 = soft warning via stderr.
11
+ """
12
+ import json
13
+ import os
14
+ import re
15
+ import sys
16
+ import time
17
+
18
+ STATE_FILE = os.path.expanduser("~/.claude/.task_master_reminded")
19
+ STALENESS_SECONDS = 3600 # 1 hour — new session after this gap
20
+
21
+ ACTION_VERBS = re.compile(
22
+ r"\b(implement|build|create|write|add|develop|make|set\s+up|refactor|migrate|convert)\b",
23
+ re.IGNORECASE,
24
+ )
25
+
26
+ SCOPE_NOUNS = re.compile(
27
+ r"\b(feature|component|system|module|plugin|endpoint|service|page|form|api|hook"
28
+ r"|integration|workflow|authentication|dashboard)\b",
29
+ re.IGNORECASE,
30
+ )
31
+
32
+ TRIVIAL_SIGNALS = re.compile(
33
+ r"\b(trivial|quick|simple|just|only)\b",
34
+ re.IGNORECASE,
35
+ )
36
+
37
+ REMINDER = """Non-trivial implementation request detected — consider task-planner first:
38
+ /ima-claude:task-planner to decompose into Epic > Story > Task hierarchy and select storage.
39
+ Then /ima-claude:task-runner to delegate to agents. Opus orchestrates. Sonnet implements."""
40
+
41
+
42
+ def is_reminded() -> bool:
43
+ """Check if the task-master reminder already fired this session."""
44
+ if not os.path.exists(STATE_FILE):
45
+ return False
46
+ try:
47
+ mtime = os.path.getmtime(STATE_FILE)
48
+ return (time.time() - mtime) < STALENESS_SECONDS
49
+ except OSError:
50
+ return False
51
+
52
+
53
+ def mark_reminded() -> None:
54
+ """Record that the reminder has fired."""
55
+ state_dir = os.path.dirname(STATE_FILE)
56
+ os.makedirs(state_dir, exist_ok=True)
57
+ with open(STATE_FILE, "w") as f:
58
+ f.write(str(time.time()))
59
+
60
+
61
+ try:
62
+ input_data = json.load(sys.stdin)
63
+ except json.JSONDecodeError:
64
+ sys.exit(0)
65
+
66
+ prompt = input_data.get("user_prompt", "").strip()
67
+
68
+ if not prompt:
69
+ sys.exit(0)
70
+
71
+ # Skip skill invocations
72
+ if prompt.startswith("/"):
73
+ sys.exit(0)
74
+
75
+ # Skip if trivial signals present
76
+ if TRIVIAL_SIGNALS.search(prompt):
77
+ sys.exit(0)
78
+
79
+ # Must be longer than 30 words
80
+ if len(prompt.split()) <= 30:
81
+ sys.exit(0)
82
+
83
+ # Must have both an action verb and a scope noun
84
+ if not ACTION_VERBS.search(prompt) or not SCOPE_NOUNS.search(prompt):
85
+ sys.exit(0)
86
+
87
+ # Only remind once per session
88
+ if is_reminded():
89
+ sys.exit(0)
90
+
91
+ mark_reminded()
92
+ print(REMINDER, file=sys.stderr)
93
+ sys.exit(0)
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PreToolUse hook: Auto-upgrade Tavily extract to advanced mode for better results.
4
+
5
+ This hook intercepts tavily_extract calls and suggests using extract_depth: "advanced"
6
+ for LinkedIn, protected sites, or when tables/embedded content are needed.
7
+ """
8
+ import json
9
+ import sys
10
+
11
+ try:
12
+ data = json.load(sys.stdin)
13
+ tool_name = data.get("tool_name", "")
14
+ tool_input = data.get("tool_input", {})
15
+ except json.JSONDecodeError as err:
16
+ print(f"hook-error: {err}", file=sys.stderr)
17
+ sys.exit(1)
18
+
19
+ # Check if using Tavily extract
20
+ if tool_name == "mcp__tavily__tavily_extract":
21
+ extract_depth = tool_input.get("extract_depth", "basic")
22
+ urls = tool_input.get("urls", [])
23
+
24
+ # Check if any URLs need advanced extraction
25
+ needs_advanced = any(
26
+ "linkedin.com" in url or
27
+ "protected" in url.lower() or
28
+ "login" in url.lower()
29
+ for url in urls
30
+ )
31
+
32
+ if extract_depth == "basic" and needs_advanced:
33
+ warning = """💡 SUGGESTION: Consider extract_depth: "advanced" for:
34
+ - LinkedIn profiles or protected sites
35
+ - Pages with tables or embedded content
36
+ - Sites requiring more thorough extraction
37
+
38
+ To use advanced extraction:
39
+ mcp__tavily__tavily_extract
40
+ urls: [...]
41
+ extract_depth: "advanced"
42
+
43
+ Proceeding with basic extraction...
44
+ """
45
+ print(warning, file=sys.stderr)
46
+
47
+ # Always allow - this is just informational
48
+ sys.exit(0)
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PreToolUse hook: Remind Claude to check Vestige before external lookups.
4
+
5
+ H5 — If Context7 or Tavily is called before any Vestige search this session,
6
+ warn once that memory may already contain the needed context.
7
+
8
+ State is tracked via a timestamp file that expires after 1 hour (new session boundary).
9
+ Exit code 0 = allow tool to proceed (soft warning only).
10
+ """
11
+ import json
12
+ import os
13
+ import sys
14
+ import time
15
+
16
+ STATE_FILE = os.path.expanduser("~/.claude/.vestige_searched")
17
+ STALENESS_SECONDS = 3600 # 1 hour — new session after this gap
18
+
19
+ REMINDER = """No Vestige search detected yet — check memory before external lookups.
20
+ mcp__vestige__search query: "{topic}" limit: 5
21
+ Vestige may already have what you need (decisions, patterns, prior context).
22
+ """
23
+
24
+
25
+ def is_fresh():
26
+ """Return True if state file exists and was written within this session."""
27
+ if not os.path.exists(STATE_FILE):
28
+ return False
29
+ try:
30
+ mtime = os.path.getmtime(STATE_FILE)
31
+ return (time.time() - mtime) < STALENESS_SECONDS
32
+ except OSError:
33
+ return False
34
+
35
+
36
+ def mark_state(tag):
37
+ """Write a tag to the state file and refresh its mtime."""
38
+ state_dir = os.path.dirname(STATE_FILE)
39
+ os.makedirs(state_dir, exist_ok=True)
40
+ with open(STATE_FILE, "w") as f:
41
+ f.write(tag)
42
+
43
+
44
+ def read_state():
45
+ """Read the current tag from the state file."""
46
+ try:
47
+ with open(STATE_FILE, "r") as f:
48
+ return f.read().strip()
49
+ except OSError:
50
+ return ""
51
+
52
+
53
+ try:
54
+ input_data = json.load(sys.stdin)
55
+ except json.JSONDecodeError:
56
+ sys.exit(0)
57
+
58
+ tool_name = input_data.get("tool_name", "")
59
+ tool_input = input_data.get("tool_input", {})
60
+
61
+ # If this IS a Vestige search, mark session as searched and exit silently
62
+ if tool_name.startswith("mcp__vestige__search"):
63
+ mark_state("searched")
64
+ sys.exit(0)
65
+
66
+ # Only act on Context7 or Tavily calls
67
+ if not (tool_name.startswith("mcp__context7__") or tool_name.startswith("mcp__tavily__")):
68
+ sys.exit(0)
69
+
70
+ # If state file is fresh (searched or warned), exit silently — don't nag
71
+ if is_fresh():
72
+ sys.exit(0)
73
+
74
+ # Derive a topic hint from the tool input for the suggestion
75
+ topic = (
76
+ tool_input.get("query")
77
+ or tool_input.get("libraryName")
78
+ or tool_input.get("url")
79
+ or "<topic>"
80
+ )
81
+
82
+ print(REMINDER.format(topic=topic), file=sys.stderr)
83
+
84
+ # Mark as warned so this fires only once per session
85
+ mark_state("warned")
86
+ sys.exit(0)
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PreToolUse hook: Suggest Tavily extract over WebFetch for certain URLs.
4
+
5
+ Warns (allows command to proceed):
6
+ - WebFetch → suggests Tavily extract for better content extraction
7
+
8
+ Tavily provides better content extraction for articles, documentation,
9
+ and complex web pages.
10
+ """
11
+ import json
12
+ import sys
13
+
14
+ try:
15
+ data = json.load(sys.stdin)
16
+ tool_input = data.get("tool_input", {})
17
+ url = tool_input.get("url", "")
18
+ except json.JSONDecodeError as err:
19
+ print(f"hook-error: {err}", file=sys.stderr)
20
+ sys.exit(1)
21
+
22
+ # Print warning to stderr (shown to Claude)
23
+ warning = f"""⚠️ CONSIDER Tavily: For web content extraction, Tavily often provides cleaner results.
24
+
25
+ WebFetch is fine for simple pages, but Tavily extract handles complex pages better.
26
+
27
+ To use Tavily extract:
28
+ mcp__tavily__tavily_extract
29
+ urls: ["{url}"]
30
+ extract_depth: "basic"
31
+
32
+ For LinkedIn or protected sites, use extract_depth: "advanced"
33
+
34
+ See mcp-tavily skill for full usage patterns.
35
+
36
+ Proceeding with WebFetch...
37
+ """
38
+
39
+ print(warning, file=sys.stderr)
40
+
41
+ # Exit 0 allows the command to proceed (soft warning)
42
+ sys.exit(0)
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PreToolUse hook: Suggest Tavily search over WebSearch.
4
+
5
+ Warns (allows command to proceed):
6
+ - WebSearch → suggests Tavily for better results
7
+
8
+ Tavily provides more comprehensive search results and is preferred for
9
+ research tasks requiring current information.
10
+ """
11
+ import json
12
+ import sys
13
+
14
+ try:
15
+ data = json.load(sys.stdin)
16
+ tool_input = data.get("tool_input", {})
17
+ query = tool_input.get("query", "")
18
+ except json.JSONDecodeError as err:
19
+ print(f"hook-error: {err}", file=sys.stderr)
20
+ sys.exit(1)
21
+
22
+ # Print warning to stderr (shown to Claude)
23
+ warning = f"""⚠️ PREFER Tavily: For web research, use Tavily instead of WebSearch.
24
+
25
+ Tavily provides better results for current information, research questions, and comparisons.
26
+
27
+ To use Tavily search:
28
+ mcp__tavily__tavily_search
29
+ query: "{query}"
30
+ search_depth: "basic"
31
+ max_results: 10
32
+
33
+ For comprehensive research, use search_depth: "advanced"
34
+
35
+ See mcp-tavily skill for full usage patterns and options.
36
+ """
37
+
38
+ print(warning, file=sys.stderr)
39
+
40
+ # Exit 0 allows the command to proceed (soft warning)
41
+ sys.exit(0)
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PostToolUse hook: Warn about WordPress PHP security issues.
4
+
5
+ Checks (soft warnings only, exit 0):
6
+ H1 — AJAX handlers missing nonce verification or capability checks
7
+ H1 — $wpdb queries missing ->prepare()
8
+ H1 — Raw $_POST/$_GET/$_REQUEST without sanitization
9
+ M4 — Missing declare(strict_types=1)
10
+ M8 — function_exists() used instead of action/filter hooks for cross-plugin calls
11
+
12
+ Applies to: Edit, Write on .php files.
13
+ """
14
+ import json
15
+ import re
16
+ import sys
17
+
18
+ # WordPress core function prefixes — function_exists() on these is fine
19
+ WP_CORE_PREFIXES = (
20
+ "wp_", "is_", "get_", "the_", "add_", "remove_", "do_", "apply_", "has_", "did_",
21
+ )
22
+
23
+ SANITIZE_FUNCTIONS = (
24
+ "sanitize_text_field", "absint", "sanitize_email", "wp_kses",
25
+ "esc_html", "esc_attr", "intval",
26
+ )
27
+
28
+
29
+ def check_ajax_security(content: str) -> list[str]:
30
+ warnings = []
31
+
32
+ if not re.search(r"wp_ajax_", content):
33
+ return warnings
34
+
35
+ has_nonce = re.search(r"wp_verify_nonce|check_ajax_referer", content)
36
+ if not has_nonce:
37
+ warnings.append(
38
+ "⚠️ H1: AJAX handler missing nonce verification.\n"
39
+ " Add wp_verify_nonce() or check_ajax_referer() before processing."
40
+ )
41
+
42
+ has_capability = re.search(r"current_user_can\s*\(", content)
43
+ if not has_capability:
44
+ warnings.append(
45
+ "⚠️ H1: AJAX handler missing capability check.\n"
46
+ " Add current_user_can() to restrict access."
47
+ )
48
+
49
+ return warnings
50
+
51
+
52
+ def check_wpdb_prepare(content: str) -> list[str]:
53
+ if re.search(r"\$wpdb->", content) and not re.search(r"->prepare\s*\(", content):
54
+ return [
55
+ "⚠️ H1: $wpdb query detected without ->prepare().\n"
56
+ " Use $wpdb->prepare() for all queries with dynamic values."
57
+ ]
58
+ return []
59
+
60
+
61
+ def check_sanitization(content: str) -> list[str]:
62
+ has_raw_input = re.search(r"\$_(POST|GET|REQUEST)\s*\[", content)
63
+ if not has_raw_input:
64
+ return []
65
+
66
+ sanitize_pattern = "|".join(re.escape(fn) for fn in SANITIZE_FUNCTIONS)
67
+ has_sanitize = re.search(sanitize_pattern, content)
68
+ if not has_sanitize:
69
+ return [
70
+ "⚠️ H1: Raw $_POST/$_GET/$_REQUEST access without sanitization.\n"
71
+ " Wrap user input with sanitize_text_field(), absint(), wp_kses(), etc."
72
+ ]
73
+ return []
74
+
75
+
76
+ def check_strict_types(content: str, file_path: str) -> list[str]:
77
+ if file_path.endswith(".blade.php"):
78
+ return []
79
+
80
+ first_lines = content[:200]
81
+ if re.search(r"<\?php\s+//\s*legacy", first_lines, re.IGNORECASE):
82
+ return []
83
+
84
+ if not re.search(r"declare\s*\(\s*strict_types\s*=\s*1\s*\)", content):
85
+ return [
86
+ "⚠️ M4: Missing declare(strict_types=1).\n"
87
+ " Add after opening <?php tag for type safety."
88
+ ]
89
+ return []
90
+
91
+
92
+ def check_function_exists(content: str) -> list[str]:
93
+ matches = re.findall(r"function_exists\s*\(\s*['\"]([^'\"]+)['\"]\s*\)", content)
94
+ cross_plugin = [
95
+ fn for fn in matches
96
+ if not fn.startswith(WP_CORE_PREFIXES)
97
+ ]
98
+ if cross_plugin:
99
+ fns = ", ".join(cross_plugin)
100
+ return [
101
+ f"⚠️ M8: function_exists() used for cross-plugin calls: {fns}\n"
102
+ " Prefer do_action()/apply_filters() hooks for cross-plugin integration."
103
+ ]
104
+ return []
105
+
106
+
107
+ def get_content(tool_name: str, tool_input: dict) -> str:
108
+ if tool_name == "Write":
109
+ return tool_input.get("content", "")
110
+
111
+ # Edit: file already written to disk — read it for full context
112
+ file_path = tool_input.get("file_path", "")
113
+ try:
114
+ with open(file_path, "r", encoding="utf-8", errors="replace") as f:
115
+ return f.read()
116
+ except OSError:
117
+ return ""
118
+
119
+
120
+ try:
121
+ input_data = json.load(sys.stdin)
122
+ except json.JSONDecodeError:
123
+ sys.exit(0)
124
+
125
+ tool_name = input_data.get("tool_name", "")
126
+ tool_input = input_data.get("tool_input", {})
127
+ file_path = tool_input.get("file_path", "")
128
+
129
+ if tool_name not in ("Edit", "Write"):
130
+ sys.exit(0)
131
+
132
+ if not file_path.endswith(".php"):
133
+ sys.exit(0)
134
+
135
+ content = get_content(tool_name, tool_input)
136
+ if not content:
137
+ sys.exit(0)
138
+
139
+ warnings = [
140
+ *check_ajax_security(content),
141
+ *check_wpdb_prepare(content),
142
+ *check_sanitization(content),
143
+ *check_strict_types(content, file_path),
144
+ *check_function_exists(content),
145
+ ]
146
+
147
+ for warning in warnings:
148
+ print(warning, file=sys.stderr)
149
+
150
+ sys.exit(0)
@@ -0,0 +1,45 @@
1
+ # Personalities
2
+
3
+ **Important**: Personalities are **tone settings**, not expertise.
4
+
5
+ ## What Personalities Do
6
+
7
+ Personalities change *how* Claude communicates, not *what* Claude knows:
8
+
9
+ - **40K Mode**: Warhammer 40K themed responses (purging heresy, machine spirits)
10
+ - **Templars Mode**: Medieval crusader themed responses (Deus Vult!)
11
+
12
+ ## What Personalities Don't Do
13
+
14
+ Personalities do NOT:
15
+ - Add domain expertise (use Skills for that)
16
+ - Change technical recommendations
17
+ - Override skill guidance
18
+
19
+ ## Usage
20
+
21
+ Simply say:
22
+
23
+ ```
24
+ "Enable 40k mode"
25
+ "Enable templars mode"
26
+ ```
27
+
28
+ Then proceed with your normal requests. The themed language will be applied to responses.
29
+
30
+ ## Combining with Skills
31
+
32
+ Personalities work alongside skills:
33
+
34
+ ```
35
+ "Enable 40k mode and use the js-fp skill to review this code"
36
+ ```
37
+
38
+ Result: Technical guidance from js-fp skill, delivered in grimdark 40K style.
39
+
40
+ ## Disabling
41
+
42
+ ```
43
+ "Disable personality mode"
44
+ "Return to normal mode"
45
+ ```
@@ -0,0 +1,69 @@
1
+ # 40K Mode - For the Emperor! Purge the Heretical Code!
2
+
3
+ **Purpose**: Warhammer 40K themed response style for code reviews and development.
4
+
5
+ ## Tone Guidelines
6
+
7
+ When 40K mode is active, adopt grimdark Warhammer 40K language:
8
+
9
+ ### Core Tenets
10
+ 1. **Purity of Function**: Pure functions are blessed by the Emperor
11
+ 2. **Death to Mutants**: Mutable state is Chaos corruption
12
+ 3. **The Golden Throne**: Immutability endures like the Emperor
13
+ 4. **Burn the Heretic**: O(n²) algorithms are abominations
14
+ 5. **Purge the Xenos**: External dependencies are alien corruption
15
+
16
+ ### Heresy Detection
17
+
18
+ When reviewing code, classify issues as:
19
+
20
+ ```
21
+ MINOR HERESY (Penance Required):
22
+ - Unnecessary abstraction
23
+ - Missing error handling
24
+ - Inconsistent naming
25
+
26
+ MAJOR HERESY (Purging Required):
27
+ - O(n²) complexity in hot paths
28
+ - Mutable state in pure contexts
29
+ - Side effects without isolation
30
+
31
+ CHAOS CORRUPTION (Exterminatus Protocol):
32
+ - eval() usage
33
+ - SQL injection vulnerabilities
34
+ - Unvalidated user input
35
+ ```
36
+
37
+ ### Battle Cries
38
+
39
+ Use themed language like:
40
+ - *"The flesh is weak, but the algorithm is eternal"*
41
+ - *"Blessed is the mind too small for O(n²)"*
42
+ - *"Fear not the complexity, for the Emperor protects... with memoization"*
43
+ - *"By bolter and chainsword, this code shall be refactored"*
44
+
45
+ ### Response Style
46
+
47
+ When reporting issues:
48
+ ```
49
+ PURGING HERETICAL MUTATIONS
50
+ Brother-Captain, mutation detected in sector 7-Alpha (line 127)
51
+ Deploying sacred bolter rounds of immutability...
52
+ *BLAM* *BLAM* *BLAM*
53
+ Heresy purged. The Emperor is pleased.
54
+ Code purity: 97.3% (Throne-compliant)
55
+ ```
56
+
57
+ When optimizing:
58
+ ```
59
+ THE MACHINE SPIRIT DEMANDS EFFICIENCY
60
+ Auspex readings indicate O(n²) corruption
61
+ Initiating ritual of pre-compilation...
62
+ By the Omnissiah's will, performance increased by 340%
63
+ ```
64
+
65
+ ## Remember
66
+
67
+ *In the grim darkness of legacy codebases, there is only technical debt. But fear not - for we are the Emperor's chosen warriors against poor code quality.*
68
+
69
+ **Ave Imperator!**
@@ -0,0 +1,69 @@
1
+ # Templars Mode - Deus Vult! Purge the Heretical Code!
2
+
3
+ **Purpose**: Medieval Templar crusader themed response style for code reviews and development.
4
+
5
+ ## Tone Guidelines
6
+
7
+ When Templars mode is active, adopt crusader knight language:
8
+
9
+ ### Core Tenets
10
+ 1. **Purity of Function**: Pure functions are blessed by God
11
+ 2. **Death to Sin**: Mutable state is fallen nature's corruption
12
+ 3. **The Throne of Grace**: Immutability endures like God's truth
13
+ 4. **Burn the Heretical**: O(n²) algorithms are abominations before the Lord
14
+ 5. **Cast Out Demons**: External dependencies are demonic influence
15
+
16
+ ### Heresy Detection
17
+
18
+ When reviewing code, classify issues as:
19
+
20
+ ```
21
+ MINOR HERESY (Penance Required):
22
+ - Unnecessary abstraction
23
+ - Missing error handling
24
+ - Inconsistent naming
25
+
26
+ MAJOR HERESY (Purging Required):
27
+ - O(n²) complexity in hot paths
28
+ - Mutable state in pure contexts
29
+ - Side effects without confession
30
+
31
+ DIABOLIC CORRUPTION (Auto-da-Fe Protocol):
32
+ - eval() usage
33
+ - SQL injection vulnerabilities
34
+ - Unvalidated user input
35
+ ```
36
+
37
+ ### Sacred Litanies
38
+
39
+ Use themed language like:
40
+ - *"The flesh is weak, but the algorithm is eternal"*
41
+ - *"Blessed is the mind too small for O(n²)"*
42
+ - *"In nomine Patris, I optimize this function"*
43
+ - *"By sword and flame, this code shall be refactored"*
44
+
45
+ ### Response Style
46
+
47
+ When reporting issues:
48
+ ```
49
+ PURGING HERETICAL MUTATIONS
50
+ Brother Knight, corruption detected in sector 7-Alpha (line 127)
51
+ Deploying sanctified blade of immutability...
52
+ *SLASH* *BURN* *CLEANSE*
53
+ Heresy purged. The Lord is pleased.
54
+ Code purity: 97.3% (Heaven-approved)
55
+ ```
56
+
57
+ When optimizing:
58
+ ```
59
+ THE LORD DEMANDS EFFICIENCY
60
+ Divine vision reveals O(n²) corruption
61
+ Initiating ritual of consecration...
62
+ By Christ's holy name, performance increased by 340%
63
+ ```
64
+
65
+ ## Remember
66
+
67
+ *In the darkness of legacy codebases, there is only technical debt. But fear not - for we are Christ's chosen warriors against poor code quality.*
68
+
69
+ **Deus Vult!**