awesome-slash 2.4.4 → 2.5.1

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 (151) hide show
  1. package/.claude-plugin/marketplace.json +6 -6
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +123 -1
  4. package/README.md +186 -159
  5. package/SECURITY.md +25 -81
  6. package/adapters/codex/install.sh +58 -16
  7. package/adapters/opencode/install.sh +92 -23
  8. package/lib/index.js +47 -4
  9. package/lib/patterns/review-patterns.js +58 -11
  10. package/lib/patterns/slop-patterns.js +154 -147
  11. package/lib/platform/detect-platform.js +99 -350
  12. package/lib/platform/detection-configs.js +93 -0
  13. package/lib/platform/state-dir.js +122 -0
  14. package/lib/platform/verify-tools.js +10 -78
  15. package/lib/schemas/README.md +195 -0
  16. package/lib/schemas/validator.js +247 -0
  17. package/lib/sources/custom-handler.js +199 -0
  18. package/lib/sources/policy-questions.js +239 -0
  19. package/lib/sources/source-cache.js +164 -0
  20. package/lib/state/workflow-state.js +368 -665
  21. package/lib/types/README.md +292 -0
  22. package/lib/types/agent-frontmatter.d.ts +134 -0
  23. package/lib/types/command-frontmatter.d.ts +107 -0
  24. package/lib/types/hook-frontmatter.d.ts +115 -0
  25. package/lib/types/index.d.ts +84 -0
  26. package/lib/types/plugin-manifest.d.ts +102 -0
  27. package/lib/types/skill-frontmatter.d.ts +89 -0
  28. package/lib/utils/cache-manager.js +154 -0
  29. package/lib/utils/context-optimizer.js +5 -36
  30. package/lib/utils/deprecation.js +37 -0
  31. package/lib/utils/shell-escape.js +88 -0
  32. package/mcp-server/index.js +513 -22
  33. package/package.json +6 -2
  34. package/plugins/deslop-around/.claude-plugin/plugin.json +1 -1
  35. package/plugins/deslop-around/lib/index.js +170 -0
  36. package/plugins/deslop-around/lib/patterns/review-patterns.js +58 -11
  37. package/plugins/deslop-around/lib/patterns/slop-patterns.js +169 -129
  38. package/plugins/deslop-around/lib/platform/detect-platform.js +162 -316
  39. package/plugins/deslop-around/lib/platform/detection-configs.js +93 -0
  40. package/plugins/deslop-around/lib/platform/state-dir.js +122 -0
  41. package/plugins/deslop-around/lib/platform/verify-tools.js +10 -78
  42. package/plugins/deslop-around/lib/schemas/README.md +195 -0
  43. package/plugins/deslop-around/lib/schemas/validator.js +247 -0
  44. package/plugins/deslop-around/lib/sources/custom-handler.js +199 -0
  45. package/plugins/deslop-around/lib/sources/policy-questions.js +239 -0
  46. package/plugins/deslop-around/lib/sources/source-cache.js +164 -0
  47. package/plugins/deslop-around/lib/state/workflow-state.js +387 -484
  48. package/plugins/deslop-around/lib/types/README.md +292 -0
  49. package/plugins/deslop-around/lib/types/agent-frontmatter.d.ts +134 -0
  50. package/plugins/deslop-around/lib/types/command-frontmatter.d.ts +107 -0
  51. package/plugins/deslop-around/lib/types/hook-frontmatter.d.ts +115 -0
  52. package/plugins/deslop-around/lib/types/index.d.ts +84 -0
  53. package/plugins/deslop-around/lib/types/plugin-manifest.d.ts +102 -0
  54. package/plugins/deslop-around/lib/types/skill-frontmatter.d.ts +89 -0
  55. package/plugins/deslop-around/lib/utils/cache-manager.js +154 -0
  56. package/plugins/deslop-around/lib/utils/context-optimizer.js +115 -37
  57. package/plugins/deslop-around/lib/utils/deprecation.js +37 -0
  58. package/plugins/deslop-around/lib/utils/shell-escape.js +88 -0
  59. package/plugins/next-task/.claude-plugin/plugin.json +1 -1
  60. package/plugins/next-task/agents/delivery-validator.md +2 -2
  61. package/plugins/next-task/agents/implementation-agent.md +3 -4
  62. package/plugins/next-task/agents/planning-agent.md +77 -19
  63. package/plugins/next-task/agents/review-orchestrator.md +21 -122
  64. package/plugins/next-task/agents/task-discoverer.md +164 -23
  65. package/plugins/next-task/commands/next-task.md +180 -14
  66. package/plugins/next-task/lib/index.js +170 -0
  67. package/plugins/next-task/lib/patterns/review-patterns.js +58 -11
  68. package/plugins/next-task/lib/patterns/slop-patterns.js +169 -129
  69. package/plugins/next-task/lib/platform/detect-platform.js +162 -316
  70. package/plugins/next-task/lib/platform/detection-configs.js +93 -0
  71. package/plugins/next-task/lib/platform/state-dir.js +122 -0
  72. package/plugins/next-task/lib/platform/verify-tools.js +10 -78
  73. package/plugins/next-task/lib/schemas/README.md +195 -0
  74. package/plugins/next-task/lib/schemas/validator.js +247 -0
  75. package/plugins/next-task/lib/sources/custom-handler.js +199 -0
  76. package/plugins/next-task/lib/sources/policy-questions.js +239 -0
  77. package/plugins/next-task/lib/sources/source-cache.js +164 -0
  78. package/plugins/next-task/lib/state/workflow-state.js +387 -484
  79. package/plugins/next-task/lib/types/README.md +292 -0
  80. package/plugins/next-task/lib/types/agent-frontmatter.d.ts +134 -0
  81. package/plugins/next-task/lib/types/command-frontmatter.d.ts +107 -0
  82. package/plugins/next-task/lib/types/hook-frontmatter.d.ts +115 -0
  83. package/plugins/next-task/lib/types/index.d.ts +84 -0
  84. package/plugins/next-task/lib/types/plugin-manifest.d.ts +102 -0
  85. package/plugins/next-task/lib/types/skill-frontmatter.d.ts +89 -0
  86. package/plugins/next-task/lib/utils/cache-manager.js +154 -0
  87. package/plugins/next-task/lib/utils/context-optimizer.js +115 -37
  88. package/plugins/next-task/lib/utils/deprecation.js +37 -0
  89. package/plugins/next-task/lib/utils/shell-escape.js +88 -0
  90. package/plugins/project-review/.claude-plugin/plugin.json +1 -1
  91. package/plugins/project-review/lib/index.js +170 -0
  92. package/plugins/project-review/lib/patterns/review-patterns.js +58 -11
  93. package/plugins/project-review/lib/patterns/slop-patterns.js +169 -129
  94. package/plugins/project-review/lib/platform/detect-platform.js +162 -316
  95. package/plugins/project-review/lib/platform/detection-configs.js +93 -0
  96. package/plugins/project-review/lib/platform/state-dir.js +122 -0
  97. package/plugins/project-review/lib/platform/verify-tools.js +10 -78
  98. package/plugins/project-review/lib/schemas/README.md +195 -0
  99. package/plugins/project-review/lib/schemas/validator.js +247 -0
  100. package/plugins/project-review/lib/sources/custom-handler.js +199 -0
  101. package/plugins/project-review/lib/sources/policy-questions.js +239 -0
  102. package/plugins/project-review/lib/sources/source-cache.js +164 -0
  103. package/plugins/project-review/lib/state/workflow-state.js +387 -484
  104. package/plugins/project-review/lib/types/README.md +292 -0
  105. package/plugins/project-review/lib/types/agent-frontmatter.d.ts +134 -0
  106. package/plugins/project-review/lib/types/command-frontmatter.d.ts +107 -0
  107. package/plugins/project-review/lib/types/hook-frontmatter.d.ts +115 -0
  108. package/plugins/project-review/lib/types/index.d.ts +84 -0
  109. package/plugins/project-review/lib/types/plugin-manifest.d.ts +102 -0
  110. package/plugins/project-review/lib/types/skill-frontmatter.d.ts +89 -0
  111. package/plugins/project-review/lib/utils/cache-manager.js +154 -0
  112. package/plugins/project-review/lib/utils/context-optimizer.js +115 -37
  113. package/plugins/project-review/lib/utils/deprecation.js +37 -0
  114. package/plugins/project-review/lib/utils/shell-escape.js +88 -0
  115. package/plugins/reality-check/.claude-plugin/plugin.json +1 -1
  116. package/plugins/reality-check/agents/code-explorer.md +1 -1
  117. package/plugins/ship/.claude-plugin/plugin.json +1 -1
  118. package/plugins/ship/lib/index.js +170 -0
  119. package/plugins/ship/lib/patterns/review-patterns.js +58 -11
  120. package/plugins/ship/lib/patterns/slop-patterns.js +169 -129
  121. package/plugins/ship/lib/platform/detect-platform.js +162 -316
  122. package/plugins/ship/lib/platform/detection-configs.js +93 -0
  123. package/plugins/ship/lib/platform/state-dir.js +122 -0
  124. package/plugins/ship/lib/platform/verify-tools.js +10 -78
  125. package/plugins/ship/lib/schemas/README.md +195 -0
  126. package/plugins/ship/lib/schemas/validator.js +247 -0
  127. package/plugins/ship/lib/sources/custom-handler.js +199 -0
  128. package/plugins/ship/lib/sources/policy-questions.js +239 -0
  129. package/plugins/ship/lib/sources/source-cache.js +164 -0
  130. package/plugins/ship/lib/state/workflow-state.js +387 -484
  131. package/plugins/ship/lib/types/README.md +292 -0
  132. package/plugins/ship/lib/types/agent-frontmatter.d.ts +134 -0
  133. package/plugins/ship/lib/types/command-frontmatter.d.ts +107 -0
  134. package/plugins/ship/lib/types/hook-frontmatter.d.ts +115 -0
  135. package/plugins/ship/lib/types/index.d.ts +84 -0
  136. package/plugins/ship/lib/types/plugin-manifest.d.ts +102 -0
  137. package/plugins/ship/lib/types/skill-frontmatter.d.ts +89 -0
  138. package/plugins/ship/lib/utils/cache-manager.js +154 -0
  139. package/plugins/ship/lib/utils/context-optimizer.js +115 -37
  140. package/plugins/ship/lib/utils/deprecation.js +37 -0
  141. package/plugins/ship/lib/utils/shell-escape.js +88 -0
  142. package/scripts/install/codex.sh +216 -72
  143. package/scripts/install/opencode.sh +197 -21
  144. package/lib/state/workflow-state.schema.json +0 -282
  145. package/plugins/deslop-around/lib/state/workflow-state.schema.json +0 -282
  146. package/plugins/next-task/agents/policy-selector.md +0 -248
  147. package/plugins/next-task/lib/state/tasks-registry.schema.json +0 -85
  148. package/plugins/next-task/lib/state/workflow-state.schema.json +0 -282
  149. package/plugins/next-task/lib/state/worktree-status.schema.json +0 -219
  150. package/plugins/project-review/lib/state/workflow-state.schema.json +0 -282
  151. package/plugins/ship/lib/state/workflow-state.schema.json +0 -282
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Detection Configurations
3
+ * Centralized config for platform detection logic
4
+ *
5
+ * @module lib/platform/detection-configs
6
+ * @author Avi Fenesh
7
+ * @license MIT
8
+ */
9
+
10
+ /**
11
+ * CI platform detection configuration
12
+ * Order matters - first match wins
13
+ */
14
+ const CI_CONFIGS = [
15
+ { file: '.github/workflows', platform: 'github-actions' },
16
+ { file: '.gitlab-ci.yml', platform: 'gitlab-ci' },
17
+ { file: '.circleci/config.yml', platform: 'circleci' },
18
+ { file: 'Jenkinsfile', platform: 'jenkins' },
19
+ { file: '.travis.yml', platform: 'travis' }
20
+ ];
21
+
22
+ /**
23
+ * Deployment platform detection configuration
24
+ * Order matters - first match wins
25
+ */
26
+ const DEPLOYMENT_CONFIGS = [
27
+ { file: 'railway.json', platform: 'railway' },
28
+ { file: 'railway.toml', platform: 'railway' }, // Legacy Railway marker
29
+ { file: 'vercel.json', platform: 'vercel' },
30
+ { file: 'netlify.toml', platform: 'netlify' },
31
+ { file: '.netlify', platform: 'netlify' }, // Legacy Netlify marker
32
+ { file: 'fly.toml', platform: 'fly' },
33
+ { file: '.platform.app.yaml', platform: 'platformsh' },
34
+ { file: 'render.yaml', platform: 'render' }
35
+ ];
36
+
37
+ /**
38
+ * Project type detection configuration
39
+ * Checks package.json for framework indicators
40
+ */
41
+ const PROJECT_TYPE_CONFIGS = {
42
+ dependencies: [
43
+ { name: 'next', type: 'nextjs' },
44
+ { name: 'react', type: 'react' },
45
+ { name: 'vue', type: 'vue' },
46
+ { name: '@angular/core', type: 'angular' },
47
+ { name: 'svelte', type: 'svelte' },
48
+ { name: 'express', type: 'express' },
49
+ { name: '@nestjs/core', type: 'nestjs' },
50
+ { name: 'gatsby', type: 'gatsby' },
51
+ { name: '@remix-run/react', type: 'remix' },
52
+ { name: 'astro', type: 'astro' }
53
+ ]
54
+ };
55
+
56
+ /**
57
+ * Package manager detection configuration
58
+ * Lock files indicate package manager used
59
+ * Order matters - first match wins (prioritize pnpm > yarn > bun > npm for Node.js)
60
+ */
61
+ const PACKAGE_MANAGER_CONFIGS = [
62
+ { file: 'pnpm-lock.yaml', manager: 'pnpm' },
63
+ { file: 'yarn.lock', manager: 'yarn' },
64
+ { file: 'bun.lockb', manager: 'bun' },
65
+ { file: 'package-lock.json', manager: 'npm' },
66
+ { file: 'poetry.lock', manager: 'poetry' },
67
+ { file: 'Pipfile.lock', manager: 'pipenv' },
68
+ { file: 'Cargo.lock', manager: 'cargo' },
69
+ { file: 'go.sum', manager: 'go' }
70
+ ];
71
+
72
+ /**
73
+ * Branch strategy patterns
74
+ */
75
+ const BRANCH_STRATEGIES = {
76
+ gitflow: ['develop', 'main', 'master'],
77
+ githubflow: ['main'],
78
+ trunkbased: ['main', 'trunk']
79
+ };
80
+
81
+ /**
82
+ * Main branch candidates (in priority order)
83
+ */
84
+ const MAIN_BRANCH_CANDIDATES = ['main', 'master', 'trunk', 'develop'];
85
+
86
+ module.exports = {
87
+ CI_CONFIGS,
88
+ DEPLOYMENT_CONFIGS,
89
+ PROJECT_TYPE_CONFIGS,
90
+ PACKAGE_MANAGER_CONFIGS,
91
+ BRANCH_STRATEGIES,
92
+ MAIN_BRANCH_CANDIDATES
93
+ };
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Platform-aware state directory detection
3
+ *
4
+ * Determines the appropriate state directory based on the AI coding assistant
5
+ * being used (Claude Code, OpenCode, or Codex CLI).
6
+ *
7
+ * @module lib/platform/state-dir
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ /**
14
+ * Cached state directory name (relative, without leading dot handling)
15
+ * @type {string|null}
16
+ */
17
+ let _cachedStateDir = null;
18
+
19
+ /**
20
+ * Detect which AI coding assistant is running and return appropriate state directory
21
+ *
22
+ * Detection order:
23
+ * 1. AI_STATE_DIR env var (user override)
24
+ * 2. OpenCode detection (OPENCODE_CONFIG env or .opencode/ exists)
25
+ * 3. Codex detection (CODEX_HOME env or .codex/ exists)
26
+ * 4. Default to .claude (Claude Code or unknown)
27
+ *
28
+ * @param {string} [basePath=process.cwd()] - Base path to check for project directories
29
+ * @returns {string} State directory name (e.g., '.claude', '.opencode', '.codex')
30
+ */
31
+ function getStateDir(basePath = process.cwd()) {
32
+ // Check user override first
33
+ if (process.env.AI_STATE_DIR) {
34
+ return process.env.AI_STATE_DIR;
35
+ }
36
+
37
+ // Return cached value if available
38
+ if (_cachedStateDir) {
39
+ return _cachedStateDir;
40
+ }
41
+
42
+ // OpenCode detection
43
+ if (process.env.OPENCODE_CONFIG || process.env.OPENCODE_CONFIG_DIR) {
44
+ _cachedStateDir = '.opencode';
45
+ return _cachedStateDir;
46
+ }
47
+
48
+ // Check for .opencode directory in project
49
+ try {
50
+ const opencodePath = path.join(basePath, '.opencode');
51
+ if (fs.existsSync(opencodePath) && fs.statSync(opencodePath).isDirectory()) {
52
+ _cachedStateDir = '.opencode';
53
+ return _cachedStateDir;
54
+ }
55
+ } catch {
56
+ // Ignore errors, continue detection
57
+ }
58
+
59
+ // Codex detection
60
+ if (process.env.CODEX_HOME) {
61
+ _cachedStateDir = '.codex';
62
+ return _cachedStateDir;
63
+ }
64
+
65
+ // Check for .codex directory in project
66
+ try {
67
+ const codexPath = path.join(basePath, '.codex');
68
+ if (fs.existsSync(codexPath) && fs.statSync(codexPath).isDirectory()) {
69
+ _cachedStateDir = '.codex';
70
+ return _cachedStateDir;
71
+ }
72
+ } catch {
73
+ // Ignore errors, continue detection
74
+ }
75
+
76
+ // Default to Claude Code
77
+ _cachedStateDir = '.claude';
78
+ return _cachedStateDir;
79
+ }
80
+
81
+ /**
82
+ * Get the full path to the state directory
83
+ * @param {string} [basePath=process.cwd()] - Base path
84
+ * @returns {string} Full path to state directory
85
+ */
86
+ function getStateDirPath(basePath = process.cwd()) {
87
+ return path.join(basePath, getStateDir(basePath));
88
+ }
89
+
90
+ /**
91
+ * Get the detected platform name
92
+ * @param {string} [basePath=process.cwd()] - Base path
93
+ * @returns {string} Platform name ('claude', 'opencode', 'codex', or 'custom')
94
+ */
95
+ function getPlatformName(basePath = process.cwd()) {
96
+ const stateDir = getStateDir(basePath);
97
+
98
+ if (process.env.AI_STATE_DIR) {
99
+ return 'custom';
100
+ }
101
+
102
+ switch (stateDir) {
103
+ case '.opencode': return 'opencode';
104
+ case '.codex': return 'codex';
105
+ case '.claude': return 'claude';
106
+ default: return 'unknown';
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Clear the cached state directory (useful for testing)
112
+ */
113
+ function clearCache() {
114
+ _cachedStateDir = null;
115
+ }
116
+
117
+ module.exports = {
118
+ getStateDir,
119
+ getStateDirPath,
120
+ getPlatformName,
121
+ clearCache
122
+ };
@@ -10,70 +10,19 @@
10
10
  * @license MIT
11
11
  */
12
12
 
13
- const { execFileSync, spawnSync, spawn } = require('child_process');
13
+ const { spawn } = require('child_process');
14
14
 
15
15
  // Detect Windows platform
16
16
  const isWindows = process.platform === 'win32';
17
17
 
18
18
  /**
19
- * Checks if a tool is available and returns its version (sync)
20
- * Uses safe execution methods to avoid shell injection vulnerabilities
21
- * @param {string} command - Command to check (e.g., 'git', 'node')
22
- * @param {string} versionFlag - Flag to get version (default: '--version')
23
- * @returns {Object} { available: boolean, version: string|null }
24
- */
25
- function checkTool(command, versionFlag = '--version') {
26
- // Validate command contains only safe characters (alphanumeric, underscore, hyphen)
27
- if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
28
- return { available: false, version: null };
29
- }
30
- // Validate versionFlag contains only safe characters
31
- if (!/^[a-zA-Z0-9_-]+$/.test(versionFlag)) {
32
- return { available: false, version: null };
33
- }
34
-
35
- try {
36
- let output;
37
-
38
- if (isWindows) {
39
- // On Windows, use spawnSync with shell to handle .cmd/.bat scripts
40
- // Input is validated above so this is safe
41
- const result = spawnSync(command, [versionFlag], {
42
- encoding: 'utf8',
43
- stdio: ['pipe', 'pipe', 'ignore'],
44
- timeout: 5000,
45
- windowsHide: true,
46
- shell: true
47
- });
48
- if (result.error || result.status !== 0) {
49
- return { available: false, version: null };
50
- }
51
- output = (result.stdout || '').trim();
52
- } else {
53
- // On Unix, use execFileSync (more secure, no shell)
54
- output = execFileSync(command, [versionFlag], {
55
- encoding: 'utf8',
56
- stdio: ['pipe', 'pipe', 'ignore'],
57
- timeout: 5000
58
- }).trim();
59
- }
60
-
61
- // Extract version from first line
62
- const version = output.split('\n')[0];
63
- return { available: true, version };
64
- } catch {
65
- return { available: false, version: null };
66
- }
67
- }
68
-
69
- /**
70
- * Checks if a tool is available and returns its version (async)
19
+ * Checks if a tool is available and returns its version
71
20
  * Uses safe execution methods to avoid shell injection vulnerabilities
72
21
  * @param {string} command - Command to check (e.g., 'git', 'node')
73
22
  * @param {string} versionFlag - Flag to get version (default: '--version')
74
23
  * @returns {Promise<Object>} { available: boolean, version: string|null }
75
24
  */
76
- function checkToolAsync(command, versionFlag = '--version') {
25
+ function checkTool(command, versionFlag = '--version') {
77
26
  return new Promise((resolve) => {
78
27
  // Validate command contains only safe characters (alphanumeric, underscore, hyphen)
79
28
  if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
@@ -87,8 +36,7 @@ function checkToolAsync(command, versionFlag = '--version') {
87
36
  let child;
88
37
 
89
38
  if (isWindows) {
90
- // On Windows, spawn shell directly with command as single argument to avoid deprecation warning
91
- // Input is validated above so this is safe
39
+ // On Windows, spawn shell directly with command as single argument
92
40
  child = spawn('cmd.exe', ['/c', command, versionFlag], {
93
41
  stdio: ['pipe', 'pipe', 'ignore'],
94
42
  windowsHide: true
@@ -178,29 +126,15 @@ const TOOL_DEFINITIONS = [
178
126
  ];
179
127
 
180
128
  /**
181
- * Verifies all development tools (sync)
182
- * @returns {Object} Tool availability map
183
- */
184
- function verifyTools() {
185
- const result = {};
186
- for (const tool of TOOL_DEFINITIONS) {
187
- result[tool.name] = checkTool(tool.name, tool.flag);
188
- }
189
- return result;
190
- }
191
-
192
- /**
193
- * Verifies all development tools (async, parallel)
194
- * Runs all tool checks in parallel for ~10x faster execution
129
+ * Verifies all development tools (parallel execution)
130
+ * Runs all tool checks in parallel for fast execution
195
131
  * @returns {Promise<Object>} Tool availability map
196
132
  */
197
- async function verifyToolsAsync() {
198
- // Run all checks in parallel
133
+ async function verifyTools() {
199
134
  const results = await Promise.all(
200
- TOOL_DEFINITIONS.map(tool => checkToolAsync(tool.name, tool.flag))
135
+ TOOL_DEFINITIONS.map(tool => checkTool(tool.name, tool.flag))
201
136
  );
202
137
 
203
- // Build result object
204
138
  const toolMap = {};
205
139
  TOOL_DEFINITIONS.forEach((tool, index) => {
206
140
  toolMap[tool.name] = results[index];
@@ -209,11 +143,11 @@ async function verifyToolsAsync() {
209
143
  return toolMap;
210
144
  }
211
145
 
212
- // When run directly, output JSON (uses async for better performance)
146
+ // When run directly, output JSON
213
147
  if (require.main === module) {
214
148
  (async () => {
215
149
  try {
216
- const result = await verifyToolsAsync();
150
+ const result = await verifyTools();
217
151
  console.log(JSON.stringify(result, null, 2));
218
152
  } catch (error) {
219
153
  console.error(JSON.stringify({
@@ -228,8 +162,6 @@ if (require.main === module) {
228
162
  // Export for use as module
229
163
  module.exports = {
230
164
  verifyTools,
231
- verifyToolsAsync,
232
165
  checkTool,
233
- checkToolAsync,
234
166
  TOOL_DEFINITIONS
235
167
  };
@@ -0,0 +1,195 @@
1
+ # JSON Schema Definitions
2
+
3
+ JSON Schema validation for plugin manifests and configuration files.
4
+
5
+ ## Overview
6
+
7
+ This directory contains JSON Schema definitions and validators for:
8
+
9
+ - **Plugin Manifest** (`plugin.json`) - Plugin metadata validation
10
+ - Additional schemas can be added for other JSON config files
11
+
12
+ ## Files
13
+
14
+ - `plugin-manifest.schema.json` - JSON Schema for plugin.json
15
+ - `validator.js` - Schema validation utility
16
+ - `README.md` - This file
17
+
18
+ ## Usage
19
+
20
+ ### Command Line
21
+
22
+ Validate a plugin manifest:
23
+
24
+ ```bash
25
+ # Validate default location
26
+ node lib/schemas/validator.js
27
+
28
+ # Validate specific file
29
+ node lib/schemas/validator.js plugins/next-task/.claude-plugin/plugin.json
30
+
31
+ # Output on success:
32
+ # ✓ Manifest is valid
33
+ # Plugin: next-task v2.3.1
34
+ # Author: Avi Fenesh
35
+
36
+ # Output on failure:
37
+ # ✗ Manifest is invalid:
38
+ # - Missing required property: name
39
+ # - version: does not match pattern
40
+ ```
41
+
42
+ ### Programmatic Use
43
+
44
+ ```javascript
45
+ const { validateManifestFile, SchemaValidator } = require('./lib/schemas/validator');
46
+
47
+ // Validate a manifest file
48
+ const result = validateManifestFile('.claude-plugin/plugin.json');
49
+ if (result.valid) {
50
+ console.log('Valid!', result.manifest);
51
+ } else {
52
+ console.error('Errors:', result.errors);
53
+ }
54
+
55
+ // Validate manifest object directly
56
+ const manifest = {
57
+ name: "my-plugin",
58
+ version: "1.0.0",
59
+ description: "My awesome plugin",
60
+ author: { name: "John Doe" },
61
+ license: "MIT"
62
+ };
63
+
64
+ const validation = SchemaValidator.validatePluginManifest(manifest);
65
+ if (!validation.valid) {
66
+ console.error(validation.errors);
67
+ }
68
+ ```
69
+
70
+ ### Integration in Tests
71
+
72
+ ```javascript
73
+ const { validateManifestFile } = require('./lib/schemas/validator');
74
+ const path = require('path');
75
+
76
+ describe('Plugin Manifest', () => {
77
+ it('should be valid', () => {
78
+ const result = validateManifestFile(
79
+ path.join(__dirname, '../.claude-plugin/plugin.json')
80
+ );
81
+ expect(result.valid).toBe(true);
82
+ expect(result.errors).toHaveLength(0);
83
+ });
84
+
85
+ it('should have required fields', () => {
86
+ const result = validateManifestFile(
87
+ path.join(__dirname, '../.claude-plugin/plugin.json')
88
+ );
89
+ expect(result.manifest.name).toBeTruthy();
90
+ expect(result.manifest.version).toMatch(/^\d+\.\d+\.\d+$/);
91
+ });
92
+ });
93
+ ```
94
+
95
+ ## Schema Details
96
+
97
+ ### plugin-manifest.schema.json
98
+
99
+ Validates `plugin.json` files with the following rules:
100
+
101
+ **Required fields:**
102
+ - `name` - Kebab-case identifier (e.g., "awesome-slash")
103
+ - `version` - Semantic version (e.g., "1.0.0")
104
+ - `description` - 10-500 characters
105
+ - `author` - Object with `name` field
106
+ - `license` - SPDX identifier (e.g., "MIT")
107
+
108
+ **Optional fields:**
109
+ - `homepage` - URL to plugin homepage
110
+ - `repository` - URL to source repository
111
+ - `keywords` - Array of search terms (1-20 items)
112
+ - `minClaudeVersion` - Minimum required version
113
+ - `dependencies` - Plugin dependencies
114
+ - `config` - Plugin configuration
115
+
116
+ **Constraints:**
117
+ - `name` must be lowercase, kebab-case
118
+ - `version` must follow semver (X.Y.Z)
119
+ - `keywords` must be unique, 2-50 chars each
120
+ - `author.email` must be valid email format
121
+ - `author.url` must be valid URI format
122
+
123
+ ### Example Valid Manifest
124
+
125
+ ```json
126
+ {
127
+ "name": "awesome-slash",
128
+ "version": "2.4.2",
129
+ "description": "Professional-grade slash commands for Claude Code",
130
+ "author": {
131
+ "name": "Avi Fenesh",
132
+ "email": "[email protected]",
133
+ "url": "https://github.com/avifenesh"
134
+ },
135
+ "homepage": "https://github.com/avifenesh/awesome-slash",
136
+ "repository": "https://github.com/avifenesh/awesome-slash",
137
+ "license": "MIT",
138
+ "keywords": ["workflow", "automation", "productivity"],
139
+ "minClaudeVersion": "1.0.0"
140
+ }
141
+ ```
142
+
143
+ ## Validation Errors
144
+
145
+ Common validation errors and fixes:
146
+
147
+ ### "Missing required property: name"
148
+ **Fix:** Add `name` field to plugin.json
149
+
150
+ ### "name: does not match pattern"
151
+ **Fix:** Use lowercase, kebab-case (e.g., "my-plugin" not "MyPlugin")
152
+
153
+ ### "version: does not match pattern"
154
+ **Fix:** Use semantic version format: "1.0.0" not "v1.0" or "1.0"
155
+
156
+ ### "description: string too short"
157
+ **Fix:** Provide description with at least 10 characters
158
+
159
+ ### "Unexpected property: xyz"
160
+ **Fix:** Remove invalid field or update schema if it's a new field
161
+
162
+ ### "keywords: array too long"
163
+ **Fix:** Use maximum 20 keywords
164
+
165
+ ## Adding New Schemas
166
+
167
+ To add validation for other JSON files:
168
+
169
+ 1. Create `{name}.schema.json` in this directory
170
+ 2. Add validator method to `validator.js`:
171
+ ```javascript
172
+ static validate{Name}(data) {
173
+ const schema = this.loadSchema(path.join(__dirname, '{name}.schema.json'));
174
+ return this.validate(data, schema);
175
+ }
176
+ ```
177
+ 3. Export validation function
178
+ 4. Update this README
179
+
180
+ ## External Tools
181
+
182
+ For more advanced validation, consider using:
183
+
184
+ - [ajv](https://ajv.js.org/) - Production-grade JSON Schema validator
185
+ - [json-schema-validator](https://www.jsonschemavalidator.net/) - Online validator
186
+ - [VSCode JSON Schema](https://code.visualstudio.com/docs/languages/json#_json-schemas) - IDE integration
187
+
188
+ ## Related
189
+
190
+ - **TypeScript Types**: `lib/types/` - TypeScript definitions for same structures
191
+ - **Plugin Manifest Spec**: See `lib/types/README.md` for detailed type documentation
192
+
193
+ ## License
194
+
195
+ MIT © Avi Fenesh