specweave 0.4.0 → 0.4.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 (62) hide show
  1. package/CLAUDE.md +501 -28
  2. package/README.md +99 -57
  3. package/bin/specweave.js +16 -0
  4. package/dist/adapters/adapter-base.d.ts +21 -0
  5. package/dist/adapters/adapter-base.d.ts.map +1 -1
  6. package/dist/adapters/adapter-base.js +28 -0
  7. package/dist/adapters/adapter-base.js.map +1 -1
  8. package/dist/adapters/adapter-interface.d.ts +41 -0
  9. package/dist/adapters/adapter-interface.d.ts.map +1 -1
  10. package/dist/adapters/claude/adapter.d.ts +36 -0
  11. package/dist/adapters/claude/adapter.d.ts.map +1 -1
  12. package/dist/adapters/claude/adapter.js +135 -0
  13. package/dist/adapters/claude/adapter.js.map +1 -1
  14. package/dist/adapters/copilot/adapter.d.ts +25 -0
  15. package/dist/adapters/copilot/adapter.d.ts.map +1 -1
  16. package/dist/adapters/copilot/adapter.js +112 -0
  17. package/dist/adapters/copilot/adapter.js.map +1 -1
  18. package/dist/adapters/cursor/adapter.d.ts +36 -0
  19. package/dist/adapters/cursor/adapter.d.ts.map +1 -1
  20. package/dist/adapters/cursor/adapter.js +140 -0
  21. package/dist/adapters/cursor/adapter.js.map +1 -1
  22. package/dist/adapters/generic/adapter.d.ts +25 -0
  23. package/dist/adapters/generic/adapter.d.ts.map +1 -1
  24. package/dist/adapters/generic/adapter.js +111 -0
  25. package/dist/adapters/generic/adapter.js.map +1 -1
  26. package/dist/cli/commands/init.d.ts.map +1 -1
  27. package/dist/cli/commands/init.js +48 -1
  28. package/dist/cli/commands/init.js.map +1 -1
  29. package/dist/cli/commands/plugin.d.ts +37 -0
  30. package/dist/cli/commands/plugin.d.ts.map +1 -0
  31. package/dist/cli/commands/plugin.js +296 -0
  32. package/dist/cli/commands/plugin.js.map +1 -0
  33. package/dist/core/plugin-detector.d.ts +96 -0
  34. package/dist/core/plugin-detector.d.ts.map +1 -0
  35. package/dist/core/plugin-detector.js +349 -0
  36. package/dist/core/plugin-detector.js.map +1 -0
  37. package/dist/core/plugin-loader.d.ts +111 -0
  38. package/dist/core/plugin-loader.d.ts.map +1 -0
  39. package/dist/core/plugin-loader.js +319 -0
  40. package/dist/core/plugin-loader.js.map +1 -0
  41. package/dist/core/plugin-manager.d.ts +144 -0
  42. package/dist/core/plugin-manager.d.ts.map +1 -0
  43. package/dist/core/plugin-manager.js +393 -0
  44. package/dist/core/plugin-manager.js.map +1 -0
  45. package/dist/core/schemas/plugin-manifest.schema.json +253 -0
  46. package/dist/core/types/plugin.d.ts +252 -0
  47. package/dist/core/types/plugin.d.ts.map +1 -0
  48. package/dist/core/types/plugin.js +48 -0
  49. package/dist/core/types/plugin.js.map +1 -0
  50. package/dist/integrations/jira/jira-mapper.d.ts +2 -2
  51. package/dist/integrations/jira/jira-mapper.js +2 -2
  52. package/package.json +13 -9
  53. package/src/adapters/adapter-base.ts +33 -0
  54. package/src/adapters/adapter-interface.ts +46 -0
  55. package/src/adapters/claude/adapter.ts +164 -0
  56. package/src/adapters/copilot/adapter.ts +138 -0
  57. package/src/adapters/cursor/adapter.ts +170 -0
  58. package/src/adapters/generic/adapter.ts +137 -0
  59. package/src/commands/specweave.increment.md +48 -4
  60. package/src/hooks/post-increment-plugin-detect.sh +142 -0
  61. package/src/hooks/post-task-completion.sh +53 -11
  62. package/src/hooks/pre-task-plugin-detect.sh +96 -0
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Plugin System Type Definitions
3
+ *
4
+ * Defines interfaces and types for the SpecWeave plugin architecture.
5
+ * Plugins are modular, domain-specific extensions that enhance SpecWeave's capabilities.
6
+ *
7
+ * @module core/types/plugin
8
+ * @version 0.4.0
9
+ */
10
+ /**
11
+ * Plugin Manifest - Metadata describing a plugin
12
+ *
13
+ * Loaded from .claude-plugin/manifest.json in each plugin directory.
14
+ * Follows JSON Schema defined in src/core/schemas/plugin-manifest.schema.json
15
+ */
16
+ export interface PluginManifest {
17
+ /** Unique plugin name (must start with 'specweave-') */
18
+ name: string;
19
+ /** Semantic version (e.g., "1.0.0") */
20
+ version: string;
21
+ /** Human-readable description (max 1024 chars) */
22
+ description: string;
23
+ /** Plugin author */
24
+ author?: string;
25
+ /** License identifier (e.g., "MIT", "Apache-2.0") */
26
+ license?: string;
27
+ /** Required SpecWeave core version (e.g., ">=0.4.0") */
28
+ specweave_core_version: string;
29
+ /** Plugin dependencies */
30
+ dependencies?: {
31
+ /** Other plugins this plugin requires */
32
+ plugins?: string[];
33
+ };
34
+ /** Auto-detection rules for suggesting this plugin */
35
+ auto_detect?: {
36
+ /** File/directory patterns to detect (e.g., "kubernetes/", ".git/") */
37
+ files?: string[];
38
+ /** NPM package dependencies to detect */
39
+ packages?: string[];
40
+ /** Environment variables to detect */
41
+ env_vars?: string[];
42
+ /** Git remote pattern (e.g., "github\\.com") */
43
+ git_remote_pattern?: string;
44
+ };
45
+ /** What this plugin provides */
46
+ provides: {
47
+ /** Skill names provided by this plugin */
48
+ skills: string[];
49
+ /** Agent names provided by this plugin */
50
+ agents: string[];
51
+ /** Command names provided by this plugin */
52
+ commands: string[];
53
+ };
54
+ /** Keywords that trigger plugin suggestions in specs/tasks */
55
+ triggers?: string[];
56
+ /** Attribution for forked/borrowed plugins */
57
+ credits?: {
58
+ /** Upstream source URL if forked */
59
+ based_on?: string | null;
60
+ /** Original author name */
61
+ original_author?: string;
62
+ /** List of contributors */
63
+ contributors?: string[];
64
+ /** Modifications made for SpecWeave */
65
+ modifications?: string[];
66
+ };
67
+ }
68
+ /**
69
+ * Skill - Auto-activating capability
70
+ */
71
+ export interface Skill {
72
+ /** Skill name (unique within plugin) */
73
+ name: string;
74
+ /** Path to SKILL.md file */
75
+ path: string;
76
+ /** Description from SKILL.md frontmatter */
77
+ description: string;
78
+ /** Test cases for this skill */
79
+ testCases?: TestCase[];
80
+ }
81
+ /**
82
+ * Agent - Specialized role with isolated context
83
+ */
84
+ export interface Agent {
85
+ /** Agent name (unique within plugin) */
86
+ name: string;
87
+ /** Path to AGENT.md file */
88
+ path: string;
89
+ /** System prompt from AGENT.md */
90
+ systemPrompt: string;
91
+ /** Agent capabilities */
92
+ capabilities: string[];
93
+ }
94
+ /**
95
+ * Command - Slash command (e.g., /specweave.github.sync)
96
+ */
97
+ export interface Command {
98
+ /** Command name (e.g., "github-sync") */
99
+ name: string;
100
+ /** Path to command.md file */
101
+ path: string;
102
+ /** Description of what the command does */
103
+ description: string;
104
+ /** Command prompt/template */
105
+ prompt: string;
106
+ }
107
+ /**
108
+ * Test Case - YAML-based test case for skills
109
+ */
110
+ export interface TestCase {
111
+ /** Test case ID (e.g., "TC-001") */
112
+ id: string;
113
+ /** Test description */
114
+ description: string;
115
+ /** Input for the skill */
116
+ input: string;
117
+ /** Expected output pattern */
118
+ expected: string;
119
+ /** Path to test case file */
120
+ path: string;
121
+ }
122
+ /**
123
+ * Plugin - Complete plugin with all components loaded
124
+ */
125
+ export interface Plugin {
126
+ /** Plugin manifest (metadata) */
127
+ manifest: PluginManifest;
128
+ /** Absolute path to plugin directory */
129
+ path: string;
130
+ /** Skills provided by this plugin */
131
+ skills: Skill[];
132
+ /** Agents provided by this plugin */
133
+ agents: Agent[];
134
+ /** Commands provided by this plugin */
135
+ commands: Command[];
136
+ }
137
+ /**
138
+ * Plugin Info - Lightweight plugin metadata (for listing)
139
+ */
140
+ export interface PluginInfo {
141
+ /** Plugin name */
142
+ name: string;
143
+ /** Plugin version */
144
+ version: string;
145
+ /** Description */
146
+ description: string;
147
+ /** Path to plugin directory */
148
+ path: string;
149
+ /** Is this plugin currently enabled? */
150
+ enabled: boolean;
151
+ /** Skill count */
152
+ skillCount: number;
153
+ /** Agent count */
154
+ agentCount: number;
155
+ /** Command count */
156
+ commandCount: number;
157
+ }
158
+ /**
159
+ * Validation Result - Result of manifest validation
160
+ */
161
+ export interface ValidationResult {
162
+ /** Is the manifest valid? */
163
+ valid: boolean;
164
+ /** Validation errors (if any) */
165
+ errors: string[];
166
+ /** Warnings (non-fatal issues) */
167
+ warnings: string[];
168
+ }
169
+ /**
170
+ * Detection Result - Result of plugin auto-detection
171
+ */
172
+ export interface DetectionResult {
173
+ /** Detected plugin name */
174
+ pluginName: string;
175
+ /** Detection confidence (0-1) */
176
+ confidence: number;
177
+ /** Reason for detection */
178
+ reason: string;
179
+ /** What triggered detection (file, package, env var, etc.) */
180
+ trigger: string;
181
+ }
182
+ /**
183
+ * Plugin Config - User's plugin configuration
184
+ *
185
+ * Stored in .specweave/config.yaml
186
+ */
187
+ export interface PluginConfig {
188
+ /** List of enabled plugin names */
189
+ enabled: string[];
190
+ /** Plugin-specific settings */
191
+ settings?: {
192
+ [pluginName: string]: Record<string, any>;
193
+ };
194
+ }
195
+ /**
196
+ * Plugin Load Options - Options for loading a plugin
197
+ */
198
+ export interface PluginLoadOptions {
199
+ /** Force reload even if already loaded */
200
+ force?: boolean;
201
+ /** Skip dependency checking */
202
+ skipDependencies?: boolean;
203
+ /** Validate plugin integrity */
204
+ validate?: boolean;
205
+ }
206
+ /**
207
+ * Plugin Unload Options - Options for unloading a plugin
208
+ */
209
+ export interface PluginUnloadOptions {
210
+ /** Remove plugin files (vs. just marking as disabled) */
211
+ remove?: boolean;
212
+ /** Force unload even if other plugins depend on it */
213
+ force?: boolean;
214
+ }
215
+ /**
216
+ * Plugin Dependency - Dependency information
217
+ */
218
+ export interface PluginDependency {
219
+ /** Plugin name */
220
+ name: string;
221
+ /** Version requirement (e.g., ">=1.0.0") */
222
+ version?: string;
223
+ /** Is this dependency optional? */
224
+ optional?: boolean;
225
+ }
226
+ /**
227
+ * Plugin Error - Custom error for plugin operations
228
+ */
229
+ export declare class PluginError extends Error {
230
+ pluginName?: string | undefined;
231
+ code?: string | undefined;
232
+ constructor(message: string, pluginName?: string | undefined, code?: string | undefined);
233
+ }
234
+ /**
235
+ * Plugin Manifest Validation Error
236
+ */
237
+ export declare class ManifestValidationError extends PluginError {
238
+ constructor(message: string, pluginName?: string);
239
+ }
240
+ /**
241
+ * Plugin Not Found Error
242
+ */
243
+ export declare class PluginNotFoundError extends PluginError {
244
+ constructor(pluginName: string);
245
+ }
246
+ /**
247
+ * Plugin Dependency Error
248
+ */
249
+ export declare class PluginDependencyError extends PluginError {
250
+ constructor(message: string, pluginName?: string);
251
+ }
252
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/core/types/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Plugin System Type Definitions
3
+ *
4
+ * Defines interfaces and types for the SpecWeave plugin architecture.
5
+ * Plugins are modular, domain-specific extensions that enhance SpecWeave's capabilities.
6
+ *
7
+ * @module core/types/plugin
8
+ * @version 0.4.0
9
+ */
10
+ /**
11
+ * Plugin Error - Custom error for plugin operations
12
+ */
13
+ export class PluginError extends Error {
14
+ constructor(message, pluginName, code) {
15
+ super(message);
16
+ this.pluginName = pluginName;
17
+ this.code = code;
18
+ this.name = 'PluginError';
19
+ }
20
+ }
21
+ /**
22
+ * Plugin Manifest Validation Error
23
+ */
24
+ export class ManifestValidationError extends PluginError {
25
+ constructor(message, pluginName) {
26
+ super(message, pluginName, 'MANIFEST_INVALID');
27
+ this.name = 'ManifestValidationError';
28
+ }
29
+ }
30
+ /**
31
+ * Plugin Not Found Error
32
+ */
33
+ export class PluginNotFoundError extends PluginError {
34
+ constructor(pluginName) {
35
+ super(`Plugin '${pluginName}' not found`, pluginName, 'PLUGIN_NOT_FOUND');
36
+ this.name = 'PluginNotFoundError';
37
+ }
38
+ }
39
+ /**
40
+ * Plugin Dependency Error
41
+ */
42
+ export class PluginDependencyError extends PluginError {
43
+ constructor(message, pluginName) {
44
+ super(message, pluginName, 'DEPENDENCY_ERROR');
45
+ this.name = 'PluginDependencyError';
46
+ }
47
+ }
48
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/core/types/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4RH;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YACE,OAAe,EACR,UAAmB,EACnB,IAAa;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,eAAU,GAAV,UAAU,CAAS;QACnB,SAAI,GAAJ,IAAI,CAAS;QAGpB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,WAAW;IACtD,YAAY,OAAe,EAAE,UAAmB;QAC9C,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IAClD,YAAY,UAAkB;QAC5B,KAAK,CAAC,WAAW,UAAU,aAAa,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,YAAY,OAAe,EAAE,UAAmB;QAC9C,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF"}
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * Syncs with:
10
10
  * - .specweave/increments/{id}/ - Increment folder
11
- * - .specweave/docs/rfcs/ - RFC documents for detailed specs
12
- * - .specweave/docs/decisions/ - Architecture decisions (ADRs)
11
+ * - .specweave/docs/internal/architecture/rfc/ - RFC documents for detailed specs
12
+ * - .specweave/docs/internal/architecture/adr/ - Architecture decisions (ADRs)
13
13
  */
14
14
  import { JiraClient } from './jira-client';
15
15
  export interface SpecWeaveIncrement {
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * Syncs with:
10
10
  * - .specweave/increments/{id}/ - Increment folder
11
- * - .specweave/docs/rfcs/ - RFC documents for detailed specs
12
- * - .specweave/docs/decisions/ - Architecture decisions (ADRs)
11
+ * - .specweave/docs/internal/architecture/rfc/ - RFC documents for detailed specs
12
+ * - .specweave/docs/internal/architecture/adr/ - Architecture decisions (ADRs)
13
13
  */
14
14
  import * as fs from 'fs';
15
15
  import * as path from 'path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Replace vibe coding with spec-driven development. Smart workflow: /specweave inc auto-closes previous, /specweave build auto-resumes, /specweave progress shows status. PM-led planning, 10 agents, 35+ skills. spec-weave.com",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,16 +14,19 @@
14
14
  "test": "jest",
15
15
  "test:smoke": "bash tests/smoke/e2e-smoke-test.sh",
16
16
  "test:e2e": "playwright test tests/e2e/specweave-smoke.spec.ts",
17
- "test:integration": "npm run test:integration:ado && npm run test:integration:jira",
18
- "test:integration:ado": "ts-node tests/integration/ado-sync/ado-sync.test.ts",
19
- "test:integration:jira": "ts-node tests/integration/jira-sync/jira-sync.test.ts",
20
- "test:sync:jira": "ts-node tests/integration/jira-sync/jira-bidirectional-sync.test.ts",
21
- "test:incremental:jira": "ts-node tests/integration/jira-sync/jira-incremental-sync.test.ts",
22
- "generate:tests": "ts-node scripts/generate-tests.ts",
23
- "generate:tests:skill": "ts-node scripts/generate-tests.ts",
17
+ "test:integration": "npm run test:integration:ado && npm run test:integration:jira && npm run test:integration:ml",
18
+ "test:integration:ado": "npx tsx tests/integration/ado-sync/ado-sync.test.ts",
19
+ "test:integration:jira": "npx tsx tests/integration/jira-sync/jira-sync.test.ts",
20
+ "test:integration:ml": "npx tsx tests/integration/ml-pipeline-workflow/ml-pipeline-soccer-detection.test.ts",
21
+ "test:sync:jira": "npx tsx tests/integration/jira-sync/jira-bidirectional-sync.test.ts",
22
+ "test:incremental:jira": "npx tsx tests/integration/jira-sync/jira-incremental-sync.test.ts",
23
+ "test:ml:pipeline": "npx tsx tests/integration/ml-pipeline-workflow/ml-pipeline-soccer-detection.test.ts",
24
+ "test:ml:real": "npx tsx tests/integration/ml-pipeline-workflow/ml-pipeline-real-video.test.ts",
25
+ "generate:tests": "npx tsx scripts/generate-tests.ts",
26
+ "generate:tests:skill": "npx tsx scripts/generate-tests.ts",
24
27
  "test:all:generated": "bash scripts/run-all-tests.sh",
25
28
  "test:all": "npm test && npm run test:smoke && npm run test:integration",
26
- "generate:skills-index": "ts-node src/utils/generate-skills-index.ts",
29
+ "generate:skills-index": "npx tsx src/utils/generate-skills-index.ts",
27
30
  "prepublishOnly": "npm run build",
28
31
  "install:agents": "bash bin/install-agents.sh",
29
32
  "install:skills": "bash bin/install-skills.sh",
@@ -77,6 +80,7 @@
77
80
  "LICENSE"
78
81
  ],
79
82
  "dependencies": {
83
+ "ajv": "^8.17.1",
80
84
  "chalk": "^5.3.0",
81
85
  "commander": "^11.1.0",
82
86
  "fs-extra": "^11.2.0",
@@ -16,6 +16,7 @@ import {
16
16
  AutomationLevel
17
17
  } from './adapter-interface.js';
18
18
  import { getDirname } from '../utils/esm-helpers.js';
19
+ import type { Plugin } from '../core/types/plugin.js';
19
20
 
20
21
  const __dirname = getDirname(import.meta.url);
21
22
 
@@ -146,4 +147,36 @@ export abstract class AdapterBase implements IAdapter {
146
147
 
147
148
  return content;
148
149
  }
150
+
151
+ /**
152
+ * Check if this adapter supports plugins
153
+ * Default: No plugin support (override in concrete adapters)
154
+ */
155
+ supportsPlugins(): boolean {
156
+ return false;
157
+ }
158
+
159
+ /**
160
+ * Compile and install a plugin
161
+ * Default: Throw error (override in concrete adapters that support plugins)
162
+ */
163
+ async compilePlugin(plugin: Plugin): Promise<void> {
164
+ throw new Error(`Plugin support not implemented for ${this.name} adapter`);
165
+ }
166
+
167
+ /**
168
+ * Unload a plugin
169
+ * Default: Throw error (override in concrete adapters that support plugins)
170
+ */
171
+ async unloadPlugin(pluginName: string): Promise<void> {
172
+ throw new Error(`Plugin support not implemented for ${this.name} adapter`);
173
+ }
174
+
175
+ /**
176
+ * Get installed plugins
177
+ * Default: Return empty array (override in concrete adapters that support plugins)
178
+ */
179
+ async getInstalledPlugins(): Promise<string[]> {
180
+ return [];
181
+ }
149
182
  }
@@ -5,6 +5,8 @@
5
5
  * Enables SpecWeave to work with ANY AI coding tool (Claude, Cursor, Copilot, etc.)
6
6
  */
7
7
 
8
+ import type { Plugin } from '../core/types/plugin.js';
9
+
8
10
  export interface AdapterOptions {
9
11
  projectPath: string;
10
12
  projectName: string;
@@ -117,4 +119,48 @@ export interface IAdapter {
117
119
  * @returns string Markdown-formatted instructions
118
120
  */
119
121
  getInstructions(): string;
122
+
123
+ /**
124
+ * Check if this adapter supports plugins
125
+ *
126
+ * Returns true if the adapter can install and compile plugins
127
+ * (Claude native, Cursor AGENTS.md, Copilot instructions.md)
128
+ * Returns false for generic/manual adapters
129
+ *
130
+ * @returns boolean True if plugins are supported
131
+ */
132
+ supportsPlugins(): boolean;
133
+
134
+ /**
135
+ * Compile and install a plugin for this adapter
136
+ *
137
+ * Transforms plugin content (skills/agents/commands) to tool-specific format:
138
+ * - Claude: Copy to .claude/skills/, .claude/agents/, .claude/commands/
139
+ * - Cursor: Compile to AGENTS.md + team commands JSON
140
+ * - Copilot: Compile to .github/copilot/instructions.md
141
+ * - Generic: Generate manual copy-paste instructions
142
+ *
143
+ * @param plugin Plugin to compile and install
144
+ * @returns Promise<void>
145
+ */
146
+ compilePlugin(plugin: Plugin): Promise<void>;
147
+
148
+ /**
149
+ * Unload (disable) a plugin for this adapter
150
+ *
151
+ * Removes plugin-specific files and restores previous state
152
+ *
153
+ * @param pluginName Name of plugin to unload
154
+ * @returns Promise<void>
155
+ */
156
+ unloadPlugin(pluginName: string): Promise<void>;
157
+
158
+ /**
159
+ * Get plugin installation status
160
+ *
161
+ * Returns information about which plugins are currently installed
162
+ *
163
+ * @returns Promise<string[]> Array of installed plugin names
164
+ */
165
+ getInstalledPlugins(): Promise<string[]>;
120
166
  }
@@ -12,6 +12,7 @@ import * as path from 'path';
12
12
  import fs from 'fs-extra';
13
13
  import { AdapterBase } from '../adapter-base.js';
14
14
  import { AdapterOptions, AdapterFile } from '../adapter-interface.js';
15
+ import type { Plugin } from '../../core/types/plugin.js';
15
16
 
16
17
  export class ClaudeAdapter extends AdapterBase {
17
18
  name = 'claude';
@@ -154,4 +155,167 @@ You're ready to build with SpecWeave on Claude Code!
154
155
  For complete documentation, see: .claude/README.md
155
156
  `;
156
157
  }
158
+
159
+ /**
160
+ * Check if Claude adapter supports plugins
161
+ *
162
+ * Claude Code has FULL plugin support via native .claude/ directory
163
+ *
164
+ * @returns boolean Always true
165
+ */
166
+ supportsPlugins(): boolean {
167
+ return true;
168
+ }
169
+
170
+ /**
171
+ * Compile and install a plugin for Claude Code
172
+ *
173
+ * Claude uses native plugin installation:
174
+ * - Copy skills to .claude/skills/{plugin-name}/{skill-name}/
175
+ * - Copy agents to .claude/agents/{plugin-name}/{agent-name}/
176
+ * - Copy commands to .claude/commands/
177
+ *
178
+ * @param plugin Plugin to install
179
+ */
180
+ async compilePlugin(plugin: Plugin): Promise<void> {
181
+ const projectPath = process.cwd();
182
+ const claudeDir = path.join(projectPath, '.claude');
183
+
184
+ console.log(`\nšŸ“¦ Installing plugin: ${plugin.manifest.name}`);
185
+
186
+ // Ensure base directories exist
187
+ await fs.ensureDir(path.join(claudeDir, 'skills'));
188
+ await fs.ensureDir(path.join(claudeDir, 'agents'));
189
+ await fs.ensureDir(path.join(claudeDir, 'commands'));
190
+
191
+ // Install skills
192
+ for (const skill of plugin.skills) {
193
+ const targetPath = path.join(claudeDir, 'skills', skill.name);
194
+ await fs.ensureDir(targetPath);
195
+
196
+ // Copy SKILL.md
197
+ const skillMdPath = path.join(skill.path, 'SKILL.md');
198
+ if (await fs.pathExists(skillMdPath)) {
199
+ await fs.copy(skillMdPath, path.join(targetPath, 'SKILL.md'));
200
+ }
201
+
202
+ // Copy test cases if they exist
203
+ const testCasesDir = path.join(skill.path, 'test-cases');
204
+ if (await fs.pathExists(testCasesDir)) {
205
+ await fs.copy(testCasesDir, path.join(targetPath, 'test-cases'));
206
+ }
207
+
208
+ console.log(` āœ“ Skill: ${skill.name}`);
209
+ }
210
+
211
+ // Install agents
212
+ for (const agent of plugin.agents) {
213
+ const targetPath = path.join(claudeDir, 'agents', agent.name);
214
+ await fs.ensureDir(targetPath);
215
+
216
+ // Copy AGENT.md
217
+ const agentMdPath = path.join(agent.path, 'AGENT.md');
218
+ if (await fs.pathExists(agentMdPath)) {
219
+ await fs.copy(agentMdPath, path.join(targetPath, 'AGENT.md'));
220
+ }
221
+
222
+ console.log(` āœ“ Agent: ${agent.name}`);
223
+ }
224
+
225
+ // Install commands
226
+ for (const command of plugin.commands) {
227
+ // Commands use their full name as filename
228
+ const fileName = command.name.replace(/\./g, '-') + '.md';
229
+ const targetPath = path.join(claudeDir, 'commands', fileName);
230
+
231
+ if (await fs.pathExists(command.path)) {
232
+ await fs.copy(command.path, targetPath);
233
+ }
234
+
235
+ console.log(` āœ“ Command: /${command.name}`);
236
+ }
237
+
238
+ console.log(`\nāœ… Plugin ${plugin.manifest.name} installed!`);
239
+ }
240
+
241
+ /**
242
+ * Unload a plugin from Claude Code
243
+ *
244
+ * Removes plugin files from .claude/ directory
245
+ *
246
+ * @param pluginName Name of plugin to unload
247
+ */
248
+ async unloadPlugin(pluginName: string): Promise<void> {
249
+ const projectPath = process.cwd();
250
+ const claudeDir = path.join(projectPath, '.claude');
251
+
252
+ console.log(`\nšŸ—‘ļø Unloading plugin: ${pluginName}`);
253
+
254
+ // Read plugin manifest to know what to remove
255
+ const pluginsDir = path.join(projectPath, 'src', 'plugins');
256
+ const pluginPath = path.join(pluginsDir, pluginName);
257
+
258
+ if (!(await fs.pathExists(pluginPath))) {
259
+ console.warn(`āš ļø Plugin ${pluginName} not found`);
260
+ return;
261
+ }
262
+
263
+ // Load plugin to get its components
264
+ const { PluginLoader } = await import('../../core/plugin-loader.js');
265
+ const loader = new PluginLoader();
266
+ const plugin = await loader.loadFromDirectory(pluginPath);
267
+
268
+ // Remove skills
269
+ for (const skill of plugin.skills) {
270
+ const skillPath = path.join(claudeDir, 'skills', skill.name);
271
+ if (await fs.pathExists(skillPath)) {
272
+ await fs.remove(skillPath);
273
+ console.log(` āœ“ Removed skill: ${skill.name}`);
274
+ }
275
+ }
276
+
277
+ // Remove agents
278
+ for (const agent of plugin.agents) {
279
+ const agentPath = path.join(claudeDir, 'agents', agent.name);
280
+ if (await fs.pathExists(agentPath)) {
281
+ await fs.remove(agentPath);
282
+ console.log(` āœ“ Removed agent: ${agent.name}`);
283
+ }
284
+ }
285
+
286
+ // Remove commands
287
+ for (const command of plugin.commands) {
288
+ const fileName = command.name.replace(/\./g, '-') + '.md';
289
+ const commandPath = path.join(claudeDir, 'commands', fileName);
290
+ if (await fs.pathExists(commandPath)) {
291
+ await fs.remove(commandPath);
292
+ console.log(` āœ“ Removed command: /${command.name}`);
293
+ }
294
+ }
295
+
296
+ console.log(`\nāœ… Plugin ${pluginName} unloaded!`);
297
+ }
298
+
299
+ /**
300
+ * Get list of installed plugins
301
+ *
302
+ * Returns plugin names that are currently installed in .claude/
303
+ *
304
+ * @returns Array of installed plugin names
305
+ */
306
+ async getInstalledPlugins(): Promise<string[]> {
307
+ const projectPath = process.cwd();
308
+ const configPath = path.join(projectPath, '.specweave', 'config.yaml');
309
+
310
+ if (!(await fs.pathExists(configPath))) {
311
+ return [];
312
+ }
313
+
314
+ // Read config to get enabled plugins
315
+ const yaml = await import('js-yaml');
316
+ const content = await fs.readFile(configPath, 'utf-8');
317
+ const config = yaml.load(content) as any;
318
+
319
+ return config.plugins?.enabled || [];
320
+ }
157
321
  }