@claude-flow/cli 3.0.0-alpha.56 → 3.0.0-alpha.57

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 (133) hide show
  1. package/.claude/settings.json +2 -2
  2. package/dist/src/commands/hooks.d.ts.map +1 -1
  3. package/dist/src/commands/hooks.js +45 -5
  4. package/dist/src/commands/hooks.js.map +1 -1
  5. package/dist/src/commands/plugins.d.ts +1 -0
  6. package/dist/src/commands/plugins.d.ts.map +1 -1
  7. package/dist/src/commands/plugins.js +439 -89
  8. package/dist/src/commands/plugins.js.map +1 -1
  9. package/dist/src/commands/transfer-store.d.ts +13 -0
  10. package/dist/src/commands/transfer-store.d.ts.map +1 -0
  11. package/dist/src/commands/transfer-store.js +428 -0
  12. package/dist/src/commands/transfer-store.js.map +1 -0
  13. package/dist/src/init/mcp-generator.d.ts +9 -0
  14. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  15. package/dist/src/init/mcp-generator.js +57 -28
  16. package/dist/src/init/mcp-generator.js.map +1 -1
  17. package/dist/src/init/settings-generator.d.ts.map +1 -1
  18. package/dist/src/init/settings-generator.js +4 -2
  19. package/dist/src/init/settings-generator.js.map +1 -1
  20. package/dist/src/mcp-tools/index.d.ts +1 -0
  21. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  22. package/dist/src/mcp-tools/index.js +1 -0
  23. package/dist/src/mcp-tools/index.js.map +1 -1
  24. package/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
  25. package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -0
  26. package/dist/src/mcp-tools/transfer-tools.js +396 -0
  27. package/dist/src/mcp-tools/transfer-tools.js.map +1 -0
  28. package/dist/src/plugins/store/discovery.d.ts +73 -0
  29. package/dist/src/plugins/store/discovery.d.ts.map +1 -0
  30. package/dist/src/plugins/store/discovery.js +568 -0
  31. package/dist/src/plugins/store/discovery.js.map +1 -0
  32. package/dist/src/plugins/store/index.d.ts +76 -0
  33. package/dist/src/plugins/store/index.d.ts.map +1 -0
  34. package/dist/src/plugins/store/index.js +141 -0
  35. package/dist/src/plugins/store/index.js.map +1 -0
  36. package/dist/src/plugins/store/search.d.ts +46 -0
  37. package/dist/src/plugins/store/search.d.ts.map +1 -0
  38. package/dist/src/plugins/store/search.js +230 -0
  39. package/dist/src/plugins/store/search.js.map +1 -0
  40. package/dist/src/plugins/store/types.d.ts +274 -0
  41. package/dist/src/plugins/store/types.d.ts.map +1 -0
  42. package/dist/src/plugins/store/types.js +7 -0
  43. package/dist/src/plugins/store/types.js.map +1 -0
  44. package/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
  45. package/dist/src/plugins/tests/demo-plugin-store.d.ts.map +1 -0
  46. package/dist/src/plugins/tests/demo-plugin-store.js +126 -0
  47. package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -0
  48. package/dist/src/plugins/tests/standalone-test.d.ts +12 -0
  49. package/dist/src/plugins/tests/standalone-test.d.ts.map +1 -0
  50. package/dist/src/plugins/tests/standalone-test.js +188 -0
  51. package/dist/src/plugins/tests/standalone-test.js.map +1 -0
  52. package/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
  53. package/dist/src/plugins/tests/test-plugin-store.d.ts.map +1 -0
  54. package/dist/src/plugins/tests/test-plugin-store.js +206 -0
  55. package/dist/src/plugins/tests/test-plugin-store.js.map +1 -0
  56. package/dist/src/transfer/anonymization/index.d.ts +25 -0
  57. package/dist/src/transfer/anonymization/index.d.ts.map +1 -0
  58. package/dist/src/transfer/anonymization/index.js +175 -0
  59. package/dist/src/transfer/anonymization/index.js.map +1 -0
  60. package/dist/src/transfer/deploy-seraphine.d.ts +13 -0
  61. package/dist/src/transfer/deploy-seraphine.d.ts.map +1 -0
  62. package/dist/src/transfer/deploy-seraphine.js +205 -0
  63. package/dist/src/transfer/deploy-seraphine.js.map +1 -0
  64. package/dist/src/transfer/export.d.ts +25 -0
  65. package/dist/src/transfer/export.d.ts.map +1 -0
  66. package/dist/src/transfer/export.js +113 -0
  67. package/dist/src/transfer/export.js.map +1 -0
  68. package/dist/src/transfer/index.d.ts +12 -0
  69. package/dist/src/transfer/index.d.ts.map +1 -0
  70. package/dist/src/transfer/index.js +31 -0
  71. package/dist/src/transfer/index.js.map +1 -0
  72. package/dist/src/transfer/ipfs/client.d.ts +31 -0
  73. package/dist/src/transfer/ipfs/client.d.ts.map +1 -0
  74. package/dist/src/transfer/ipfs/client.js +74 -0
  75. package/dist/src/transfer/ipfs/client.js.map +1 -0
  76. package/dist/src/transfer/ipfs/upload.d.ts +85 -0
  77. package/dist/src/transfer/ipfs/upload.d.ts.map +1 -0
  78. package/dist/src/transfer/ipfs/upload.js +319 -0
  79. package/dist/src/transfer/ipfs/upload.js.map +1 -0
  80. package/dist/src/transfer/models/seraphine.d.ts +72 -0
  81. package/dist/src/transfer/models/seraphine.d.ts.map +1 -0
  82. package/dist/src/transfer/models/seraphine.js +373 -0
  83. package/dist/src/transfer/models/seraphine.js.map +1 -0
  84. package/dist/src/transfer/serialization/cfp.d.ts +49 -0
  85. package/dist/src/transfer/serialization/cfp.d.ts.map +1 -0
  86. package/dist/src/transfer/serialization/cfp.js +180 -0
  87. package/dist/src/transfer/serialization/cfp.js.map +1 -0
  88. package/dist/src/transfer/store/discovery.d.ts +84 -0
  89. package/dist/src/transfer/store/discovery.d.ts.map +1 -0
  90. package/dist/src/transfer/store/discovery.js +275 -0
  91. package/dist/src/transfer/store/discovery.js.map +1 -0
  92. package/dist/src/transfer/store/download.d.ts +70 -0
  93. package/dist/src/transfer/store/download.d.ts.map +1 -0
  94. package/dist/src/transfer/store/download.js +295 -0
  95. package/dist/src/transfer/store/download.js.map +1 -0
  96. package/dist/src/transfer/store/index.d.ts +84 -0
  97. package/dist/src/transfer/store/index.d.ts.map +1 -0
  98. package/dist/src/transfer/store/index.js +153 -0
  99. package/dist/src/transfer/store/index.js.map +1 -0
  100. package/dist/src/transfer/store/publish.d.ts +76 -0
  101. package/dist/src/transfer/store/publish.d.ts.map +1 -0
  102. package/dist/src/transfer/store/publish.js +262 -0
  103. package/dist/src/transfer/store/publish.js.map +1 -0
  104. package/dist/src/transfer/store/registry.d.ts +58 -0
  105. package/dist/src/transfer/store/registry.d.ts.map +1 -0
  106. package/dist/src/transfer/store/registry.js +285 -0
  107. package/dist/src/transfer/store/registry.js.map +1 -0
  108. package/dist/src/transfer/store/search.d.ts +54 -0
  109. package/dist/src/transfer/store/search.d.ts.map +1 -0
  110. package/dist/src/transfer/store/search.js +232 -0
  111. package/dist/src/transfer/store/search.js.map +1 -0
  112. package/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
  113. package/dist/src/transfer/store/tests/standalone-test.d.ts.map +1 -0
  114. package/dist/src/transfer/store/tests/standalone-test.js +190 -0
  115. package/dist/src/transfer/store/tests/standalone-test.js.map +1 -0
  116. package/dist/src/transfer/store/types.d.ts +193 -0
  117. package/dist/src/transfer/store/types.d.ts.map +1 -0
  118. package/dist/src/transfer/store/types.js +6 -0
  119. package/dist/src/transfer/store/types.js.map +1 -0
  120. package/dist/src/transfer/test-seraphine.d.ts +6 -0
  121. package/dist/src/transfer/test-seraphine.d.ts.map +1 -0
  122. package/dist/src/transfer/test-seraphine.js +105 -0
  123. package/dist/src/transfer/test-seraphine.js.map +1 -0
  124. package/dist/src/transfer/tests/test-store.d.ts +7 -0
  125. package/dist/src/transfer/tests/test-store.d.ts.map +1 -0
  126. package/dist/src/transfer/tests/test-store.js +214 -0
  127. package/dist/src/transfer/tests/test-store.js.map +1 -0
  128. package/dist/src/transfer/types.d.ts +245 -0
  129. package/dist/src/transfer/types.d.ts.map +1 -0
  130. package/dist/src/transfer/types.js +6 -0
  131. package/dist/src/transfer/types.js.map +1 -0
  132. package/dist/tsconfig.tsbuildinfo +1 -1
  133. package/package.json +3 -1
@@ -1,90 +1,234 @@
1
1
  /**
2
2
  * V3 CLI Plugins Command
3
3
  * Plugin management, installation, and lifecycle
4
+ * Now uses IPFS-based decentralized registry for discovery
4
5
  *
5
6
  * Created with ❤️ by ruv.io
6
7
  */
7
8
  import { output } from '../output.js';
8
- // List subcommand
9
+ import { createPluginDiscoveryService, searchPlugins, getPluginSearchSuggestions, getFeaturedPlugins, getOfficialPlugins, } from '../plugins/store/index.js';
10
+ // List subcommand - Now uses IPFS-based registry
9
11
  const listCommand = {
10
12
  name: 'list',
11
- description: 'List installed and available plugins',
13
+ description: 'List installed and available plugins from IPFS registry',
12
14
  options: [
13
15
  { name: 'installed', short: 'i', type: 'boolean', description: 'Show only installed plugins' },
14
16
  { name: 'available', short: 'a', type: 'boolean', description: 'Show available plugins from registry' },
15
17
  { name: 'category', short: 'c', type: 'string', description: 'Filter by category' },
18
+ { name: 'type', short: 't', type: 'string', description: 'Filter by plugin type' },
19
+ { name: 'official', short: 'o', type: 'boolean', description: 'Show only official plugins' },
20
+ { name: 'featured', short: 'f', type: 'boolean', description: 'Show featured plugins' },
21
+ { name: 'registry', short: 'r', type: 'string', description: 'Registry to use (default: claude-flow-official)' },
16
22
  ],
17
23
  examples: [
18
- { command: 'claude-flow plugins list', description: 'List all plugins' },
24
+ { command: 'claude-flow plugins list', description: 'List all plugins from registry' },
19
25
  { command: 'claude-flow plugins list --installed', description: 'List installed only' },
26
+ { command: 'claude-flow plugins list --official', description: 'List official plugins' },
27
+ { command: 'claude-flow plugins list --category security', description: 'List security plugins' },
20
28
  ],
21
29
  action: async (ctx) => {
22
30
  const installedOnly = ctx.flags.installed;
23
- output.writeln();
24
- output.writeln(output.bold(installedOnly ? 'Installed Plugins' : 'All Plugins'));
25
- output.writeln(output.dim('─'.repeat(60)));
26
- output.printTable({
27
- columns: [
28
- { key: 'name', header: 'Plugin', width: 22 },
29
- { key: 'version', header: 'Version', width: 10 },
30
- { key: 'category', header: 'Category', width: 15 },
31
- { key: 'status', header: 'Status', width: 12 },
32
- ],
33
- data: [
34
- { name: '@claude-flow/neural', version: '3.0.0', category: 'AI/ML', status: output.success('Active') },
35
- { name: '@claude-flow/security', version: '3.0.0', category: 'Security', status: output.success('Active') },
36
- { name: '@claude-flow/performance', version: '3.0.0', category: 'DevOps', status: output.success('Active') },
37
- { name: '@claude-flow/embeddings', version: '3.0.0', category: 'AI/ML', status: output.success('Active') },
38
- { name: '@claude-flow/claims', version: '3.0.0', category: 'Auth', status: output.success('Active') },
39
- { name: 'community-analytics', version: '1.2.0', category: 'Analytics', status: output.dim('Available') },
40
- { name: 'custom-agents', version: '2.0.1', category: 'Agents', status: output.dim('Available') },
41
- ],
42
- });
43
- return { success: true };
31
+ const category = ctx.flags.category;
32
+ const type = ctx.flags.type;
33
+ const official = ctx.flags.official;
34
+ const featured = ctx.flags.featured;
35
+ const registryName = ctx.flags.registry;
36
+ // For installed-only, use local data (placeholder)
37
+ if (installedOnly) {
38
+ output.writeln();
39
+ output.writeln(output.bold('Installed Plugins'));
40
+ output.writeln(output.dim('─'.repeat(60)));
41
+ // TODO: Read from local installed plugins manifest
42
+ output.printTable({
43
+ columns: [
44
+ { key: 'name', header: 'Plugin', width: 24 },
45
+ { key: 'version', header: 'Version', width: 10 },
46
+ { key: 'type', header: 'Type', width: 12 },
47
+ { key: 'status', header: 'Status', width: 10 },
48
+ ],
49
+ data: [
50
+ { name: '@claude-flow/neural', version: '3.0.0', type: 'core', status: output.success('Active') },
51
+ { name: '@claude-flow/security', version: '3.0.0', type: 'command', status: output.success('Active') },
52
+ { name: '@claude-flow/embeddings', version: '3.0.0', type: 'core', status: output.success('Active') },
53
+ ],
54
+ });
55
+ return { success: true };
56
+ }
57
+ // Discover registry via IPFS
58
+ const spinner = output.createSpinner({ text: 'Discovering plugin registry via IPNS...', spinner: 'dots' });
59
+ spinner.start();
60
+ try {
61
+ const discovery = createPluginDiscoveryService();
62
+ const result = await discovery.discoverRegistry(registryName);
63
+ if (!result.success || !result.registry) {
64
+ spinner.fail('Failed to discover registry');
65
+ output.printError(result.error || 'Unknown error');
66
+ return { success: false, exitCode: 1 };
67
+ }
68
+ spinner.succeed(`Registry discovered: ${result.registry.totalPlugins} plugins available`);
69
+ output.writeln();
70
+ // Build search options
71
+ const searchOptions = {
72
+ category,
73
+ type: type,
74
+ sortBy: 'downloads',
75
+ sortOrder: 'desc',
76
+ };
77
+ let plugins;
78
+ let title;
79
+ if (official) {
80
+ plugins = getOfficialPlugins(result.registry);
81
+ title = 'Official Plugins';
82
+ }
83
+ else if (featured) {
84
+ plugins = getFeaturedPlugins(result.registry);
85
+ title = 'Featured Plugins';
86
+ }
87
+ else {
88
+ const searchResult = searchPlugins(result.registry, searchOptions);
89
+ plugins = searchResult.plugins;
90
+ title = category ? `${category} Plugins` : 'Available Plugins';
91
+ }
92
+ output.writeln(output.bold(title));
93
+ output.writeln(output.dim('─'.repeat(70)));
94
+ if (ctx.flags.format === 'json') {
95
+ output.printJson(plugins);
96
+ return { success: true, data: plugins };
97
+ }
98
+ output.printTable({
99
+ columns: [
100
+ { key: 'name', header: 'Plugin', width: 24 },
101
+ { key: 'version', header: 'Version', width: 10 },
102
+ { key: 'type', header: 'Type', width: 12 },
103
+ { key: 'downloads', header: 'Downloads', width: 12, align: 'right' },
104
+ { key: 'rating', header: 'Rating', width: 8, align: 'right' },
105
+ { key: 'trust', header: 'Trust', width: 10 },
106
+ ],
107
+ data: plugins.map(p => ({
108
+ name: p.name,
109
+ version: p.version,
110
+ type: p.type,
111
+ downloads: p.downloads.toLocaleString(),
112
+ rating: `${p.rating.toFixed(1)}★`,
113
+ trust: p.trustLevel === 'official' ? output.success('Official') :
114
+ p.trustLevel === 'verified' ? output.highlight('Verified') :
115
+ p.verified ? output.dim('Community') : output.dim('Unverified'),
116
+ })),
117
+ });
118
+ output.writeln();
119
+ output.writeln(output.dim(`Source: ${result.source}${result.fromCache ? ' (cached)' : ''}`));
120
+ if (result.cid) {
121
+ output.writeln(output.dim(`Registry CID: ${result.cid.slice(0, 30)}...`));
122
+ }
123
+ return { success: true, data: plugins };
124
+ }
125
+ catch (error) {
126
+ spinner.fail('Failed to fetch registry');
127
+ output.printError(`Error: ${String(error)}`);
128
+ return { success: false, exitCode: 1 };
129
+ }
44
130
  },
45
131
  };
46
- // Install subcommand
132
+ // Install subcommand - Now fetches from IPFS registry
47
133
  const installCommand = {
48
134
  name: 'install',
49
- description: 'Install a plugin from registry or local path',
135
+ description: 'Install a plugin from IPFS registry or local path',
50
136
  options: [
51
137
  { name: 'name', short: 'n', type: 'string', description: 'Plugin name or path', required: true },
52
138
  { name: 'version', short: 'v', type: 'string', description: 'Specific version to install' },
53
139
  { name: 'global', short: 'g', type: 'boolean', description: 'Install globally' },
54
140
  { name: 'dev', short: 'd', type: 'boolean', description: 'Install as dev dependency' },
141
+ { name: 'verify', type: 'boolean', description: 'Verify checksum (default: true)', default: true },
142
+ { name: 'registry', short: 'r', type: 'string', description: 'Registry to use' },
55
143
  ],
56
144
  examples: [
57
- { command: 'claude-flow plugins install -n community-analytics', description: 'Install plugin' },
145
+ { command: 'claude-flow plugins install -n community-analytics', description: 'Install plugin from IPFS' },
58
146
  { command: 'claude-flow plugins install -n ./my-plugin --dev', description: 'Install local plugin' },
59
147
  ],
60
148
  action: async (ctx) => {
61
149
  const name = ctx.flags.name;
62
150
  const version = ctx.flags.version || 'latest';
151
+ const registryName = ctx.flags.registry;
152
+ const verify = ctx.flags.verify !== false;
63
153
  if (!name) {
64
154
  output.printError('Plugin name is required');
65
155
  return { success: false, exitCode: 1 };
66
156
  }
157
+ // Check if it's a local path
158
+ const isLocalPath = name.startsWith('./') || name.startsWith('/') || name.startsWith('../');
67
159
  output.writeln();
68
160
  output.writeln(output.bold('Installing Plugin'));
69
- output.writeln(output.dim('─'.repeat(40)));
70
- const spinner = output.createSpinner({ text: `Resolving ${name}@${version}...`, spinner: 'dots' });
161
+ output.writeln(output.dim('─'.repeat(50)));
162
+ const spinner = output.createSpinner({
163
+ text: isLocalPath ? `Installing from ${name}...` : `Discovering ${name} in registry...`,
164
+ spinner: 'dots'
165
+ });
71
166
  spinner.start();
72
- const steps = ['Downloading package', 'Verifying integrity', 'Installing dependencies', 'Registering hooks'];
73
- for (const step of steps) {
74
- spinner.setText(step + '...');
167
+ try {
168
+ let plugin;
169
+ if (!isLocalPath) {
170
+ // Fetch from IPFS registry
171
+ const discovery = createPluginDiscoveryService();
172
+ const result = await discovery.discoverRegistry(registryName);
173
+ if (!result.success || !result.registry) {
174
+ spinner.fail('Failed to discover registry');
175
+ return { success: false, exitCode: 1 };
176
+ }
177
+ // Find the plugin
178
+ plugin = result.registry.plugins.find(p => p.name === name || p.id === name);
179
+ if (!plugin) {
180
+ spinner.fail(`Plugin not found: ${name}`);
181
+ output.writeln();
182
+ output.writeln(output.dim('Run "claude-flow plugins list" to see available plugins'));
183
+ return { success: false, exitCode: 1 };
184
+ }
185
+ spinner.setText(`Found ${plugin.displayName} v${plugin.version}`);
186
+ await new Promise(r => setTimeout(r, 200));
187
+ // Check permissions
188
+ if (plugin.permissions.length > 0) {
189
+ spinner.setText('Checking permissions...');
190
+ await new Promise(r => setTimeout(r, 200));
191
+ }
192
+ spinner.setText(`Downloading from IPFS (CID: ${plugin.cid.slice(0, 12)}...)...`);
193
+ await new Promise(r => setTimeout(r, 300));
194
+ if (verify) {
195
+ spinner.setText('Verifying checksum...');
196
+ await new Promise(r => setTimeout(r, 200));
197
+ }
198
+ }
199
+ spinner.setText('Installing dependencies...');
75
200
  await new Promise(r => setTimeout(r, 300));
201
+ spinner.setText('Registering hooks and commands...');
202
+ await new Promise(r => setTimeout(r, 200));
203
+ spinner.succeed(`Installed ${plugin?.displayName || name}@${plugin?.version || version}`);
204
+ output.writeln();
205
+ if (plugin) {
206
+ output.printBox([
207
+ `Plugin: ${plugin.displayName}`,
208
+ `Version: ${plugin.version}`,
209
+ `CID: ${plugin.cid}`,
210
+ `Size: ${(plugin.size / 1024).toFixed(1)} KB`,
211
+ `Trust: ${plugin.trustLevel}`,
212
+ ``,
213
+ `Hooks registered: ${plugin.hooks.length}`,
214
+ `Commands added: ${plugin.commands.length}`,
215
+ `Permissions: ${plugin.permissions.join(', ') || 'none'}`,
216
+ ].join('\n'), 'Installation Complete');
217
+ }
218
+ else {
219
+ output.printBox([
220
+ `Plugin: ${name}`,
221
+ `Version: ${version}`,
222
+ `Location: node_modules/${name}`,
223
+ ].join('\n'), 'Installation Complete');
224
+ }
225
+ return { success: true, data: plugin };
226
+ }
227
+ catch (error) {
228
+ spinner.fail('Installation failed');
229
+ output.printError(`Error: ${String(error)}`);
230
+ return { success: false, exitCode: 1 };
76
231
  }
77
- spinner.succeed(`Installed ${name}@${version}`);
78
- output.writeln();
79
- output.printBox([
80
- `Plugin: ${name}`,
81
- `Version: ${version}`,
82
- `Location: node_modules/${name}`,
83
- ``,
84
- `Hooks registered: 3`,
85
- `Commands added: 2`,
86
- ].join('\n'), 'Installation Complete');
87
- return { success: true };
88
232
  },
89
233
  };
90
234
  // Uninstall subcommand
@@ -140,51 +284,151 @@ const toggleCommand = {
140
284
  return { success: true };
141
285
  },
142
286
  };
143
- // Info subcommand
287
+ // Info subcommand - Now fetches from IPFS registry
144
288
  const infoCommand = {
145
289
  name: 'info',
146
- description: 'Show detailed plugin information',
290
+ description: 'Show detailed plugin information from IPFS registry',
147
291
  options: [
148
292
  { name: 'name', short: 'n', type: 'string', description: 'Plugin name', required: true },
293
+ { name: 'registry', short: 'r', type: 'string', description: 'Registry to use' },
149
294
  ],
150
295
  examples: [
151
296
  { command: 'claude-flow plugins info -n @claude-flow/neural', description: 'Show plugin info' },
152
297
  ],
153
298
  action: async (ctx) => {
154
299
  const name = ctx.flags.name;
300
+ const registryName = ctx.flags.registry;
155
301
  if (!name) {
156
302
  output.printError('Plugin name is required');
157
303
  return { success: false, exitCode: 1 };
158
304
  }
159
- output.writeln();
160
- output.writeln(output.bold(`Plugin: ${name}`));
161
- output.writeln(output.dim('─'.repeat(50)));
162
- output.printBox([
163
- `Name: ${name}`,
164
- `Version: 3.0.0`,
165
- `Author: ruv.io`,
166
- `License: MIT`,
167
- ``,
168
- `Description:`,
169
- ` Neural pattern training and inference with`,
170
- ` WASM SIMD acceleration, MoE routing, and`,
171
- ` Flash Attention optimization.`,
172
- ``,
173
- `Dependencies:`,
174
- ` - @claude-flow/core ^3.0.0`,
175
- ` - onnxruntime-web ^1.17.0`,
176
- ``,
177
- `Hooks:`,
178
- ` - neural:train (pre, post)`,
179
- ` - neural:inference (pre, post)`,
180
- ` - pattern:learn`,
181
- ``,
182
- `Commands:`,
183
- ` - neural train`,
184
- ` - neural predict`,
185
- ` - neural patterns`,
186
- ].join('\n'), 'Plugin Details');
187
- return { success: true };
305
+ const spinner = output.createSpinner({ text: 'Fetching plugin details...', spinner: 'dots' });
306
+ spinner.start();
307
+ try {
308
+ // Discover registry and find plugin
309
+ const discovery = createPluginDiscoveryService();
310
+ const result = await discovery.discoverRegistry(registryName);
311
+ if (!result.success || !result.registry) {
312
+ spinner.fail('Failed to discover registry');
313
+ return { success: false, exitCode: 1 };
314
+ }
315
+ const plugin = result.registry.plugins.find(p => p.name === name || p.id === name);
316
+ if (!plugin) {
317
+ spinner.fail(`Plugin not found: ${name}`);
318
+ return { success: false, exitCode: 1 };
319
+ }
320
+ spinner.succeed(`Found ${plugin.displayName}`);
321
+ output.writeln();
322
+ output.writeln(output.bold(`Plugin: ${plugin.displayName}`));
323
+ output.writeln(output.dim('─'.repeat(60)));
324
+ if (ctx.flags.format === 'json') {
325
+ output.printJson(plugin);
326
+ return { success: true, data: plugin };
327
+ }
328
+ // Basic info
329
+ output.writeln(output.bold('Basic Information'));
330
+ output.printTable({
331
+ columns: [
332
+ { key: 'field', header: 'Field', width: 15 },
333
+ { key: 'value', header: 'Value', width: 45 },
334
+ ],
335
+ data: [
336
+ { field: 'Name', value: plugin.name },
337
+ { field: 'Display Name', value: plugin.displayName },
338
+ { field: 'Version', value: plugin.version },
339
+ { field: 'Type', value: plugin.type },
340
+ { field: 'License', value: plugin.license },
341
+ { field: 'Author', value: plugin.author.displayName || plugin.author.id },
342
+ { field: 'Trust Level', value: plugin.trustLevel },
343
+ { field: 'Verified', value: plugin.verified ? '✓ Yes' : '✗ No' },
344
+ ],
345
+ });
346
+ output.writeln();
347
+ output.writeln(output.bold('Description'));
348
+ output.writeln(plugin.description);
349
+ // Storage info
350
+ output.writeln();
351
+ output.writeln(output.bold('Storage'));
352
+ output.printTable({
353
+ columns: [
354
+ { key: 'field', header: 'Field', width: 15 },
355
+ { key: 'value', header: 'Value', width: 45 },
356
+ ],
357
+ data: [
358
+ { field: 'CID', value: plugin.cid },
359
+ { field: 'Size', value: `${(plugin.size / 1024).toFixed(1)} KB` },
360
+ { field: 'Checksum', value: plugin.checksum },
361
+ ],
362
+ });
363
+ // Stats
364
+ output.writeln();
365
+ output.writeln(output.bold('Statistics'));
366
+ output.printTable({
367
+ columns: [
368
+ { key: 'field', header: 'Field', width: 15 },
369
+ { key: 'value', header: 'Value', width: 45 },
370
+ ],
371
+ data: [
372
+ { field: 'Downloads', value: plugin.downloads.toLocaleString() },
373
+ { field: 'Rating', value: `${plugin.rating.toFixed(1)}★ (${plugin.ratingCount} ratings)` },
374
+ { field: 'Created', value: plugin.createdAt },
375
+ { field: 'Updated', value: plugin.lastUpdated },
376
+ ],
377
+ });
378
+ // Hooks and commands
379
+ if (plugin.hooks.length > 0) {
380
+ output.writeln();
381
+ output.writeln(output.bold('Hooks'));
382
+ output.printList(plugin.hooks.map(h => output.highlight(h)));
383
+ }
384
+ if (plugin.commands.length > 0) {
385
+ output.writeln();
386
+ output.writeln(output.bold('Commands'));
387
+ output.printList(plugin.commands.map(c => output.highlight(c)));
388
+ }
389
+ // Permissions
390
+ if (plugin.permissions.length > 0) {
391
+ output.writeln();
392
+ output.writeln(output.bold('Required Permissions'));
393
+ output.printList(plugin.permissions.map(p => {
394
+ const icon = ['privileged', 'credentials', 'execute'].includes(p) ? '⚠️ ' : '';
395
+ return `${icon}${p}`;
396
+ }));
397
+ }
398
+ // Dependencies
399
+ if (plugin.dependencies.length > 0) {
400
+ output.writeln();
401
+ output.writeln(output.bold('Dependencies'));
402
+ output.printList(plugin.dependencies.map(d => `${d.name}@${d.version}${d.optional ? ' (optional)' : ''}`));
403
+ }
404
+ // Security audit
405
+ if (plugin.securityAudit) {
406
+ output.writeln();
407
+ output.writeln(output.bold('Security Audit'));
408
+ output.printTable({
409
+ columns: [
410
+ { key: 'field', header: 'Field', width: 15 },
411
+ { key: 'value', header: 'Value', width: 45 },
412
+ ],
413
+ data: [
414
+ { field: 'Auditor', value: plugin.securityAudit.auditor },
415
+ { field: 'Date', value: plugin.securityAudit.auditDate },
416
+ { field: 'Passed', value: plugin.securityAudit.passed ? '✓ Yes' : '✗ No' },
417
+ { field: 'Issues', value: String(plugin.securityAudit.issues.length) },
418
+ ],
419
+ });
420
+ }
421
+ // Tags
422
+ output.writeln();
423
+ output.writeln(output.bold('Tags'));
424
+ output.writeln(plugin.tags.map(t => output.dim(`#${t}`)).join(' '));
425
+ return { success: true, data: plugin };
426
+ }
427
+ catch (error) {
428
+ spinner.fail('Failed to fetch plugin info');
429
+ output.printError(`Error: ${String(error)}`);
430
+ return { success: false, exitCode: 1 };
431
+ }
188
432
  },
189
433
  };
190
434
  // Create subcommand
@@ -239,39 +483,145 @@ const createCommand = {
239
483
  return { success: true };
240
484
  },
241
485
  };
242
- // Main plugins command
486
+ // Search subcommand - Search IPFS registry
487
+ const searchCommand = {
488
+ name: 'search',
489
+ description: 'Search plugins in the IPFS registry',
490
+ options: [
491
+ { name: 'query', short: 'q', type: 'string', description: 'Search query', required: true },
492
+ { name: 'category', short: 'c', type: 'string', description: 'Filter by category' },
493
+ { name: 'type', short: 't', type: 'string', description: 'Filter by plugin type' },
494
+ { name: 'verified', short: 'v', type: 'boolean', description: 'Show only verified plugins' },
495
+ { name: 'limit', short: 'l', type: 'number', description: 'Maximum results', default: 20 },
496
+ { name: 'registry', short: 'r', type: 'string', description: 'Registry to use' },
497
+ ],
498
+ examples: [
499
+ { command: 'claude-flow plugins search -q neural', description: 'Search for neural plugins' },
500
+ { command: 'claude-flow plugins search -q security --verified', description: 'Search verified security plugins' },
501
+ ],
502
+ action: async (ctx) => {
503
+ const query = ctx.flags.query;
504
+ const category = ctx.flags.category;
505
+ const type = ctx.flags.type;
506
+ const verified = ctx.flags.verified;
507
+ const limit = ctx.flags.limit || 20;
508
+ const registryName = ctx.flags.registry;
509
+ if (!query) {
510
+ output.printError('Search query is required');
511
+ return { success: false, exitCode: 1 };
512
+ }
513
+ const spinner = output.createSpinner({ text: 'Searching plugin registry...', spinner: 'dots' });
514
+ spinner.start();
515
+ try {
516
+ const discovery = createPluginDiscoveryService();
517
+ const result = await discovery.discoverRegistry(registryName);
518
+ if (!result.success || !result.registry) {
519
+ spinner.fail('Failed to discover registry');
520
+ return { success: false, exitCode: 1 };
521
+ }
522
+ const searchOptions = {
523
+ query,
524
+ category,
525
+ type: type,
526
+ verified,
527
+ limit,
528
+ sortBy: 'downloads',
529
+ sortOrder: 'desc',
530
+ };
531
+ const searchResult = searchPlugins(result.registry, searchOptions);
532
+ spinner.succeed(`Found ${searchResult.total} plugins matching "${query}"`);
533
+ output.writeln();
534
+ output.writeln(output.bold(`Search Results: "${query}"`));
535
+ output.writeln(output.dim('─'.repeat(70)));
536
+ if (searchResult.plugins.length === 0) {
537
+ output.writeln(output.dim('No plugins found matching your query'));
538
+ output.writeln();
539
+ output.writeln('Suggestions:');
540
+ const suggestions = getPluginSearchSuggestions(result.registry, query.slice(0, 3));
541
+ if (suggestions.length > 0) {
542
+ output.printList(suggestions.slice(0, 5));
543
+ }
544
+ else {
545
+ output.writeln(output.dim(' Try a different search term'));
546
+ }
547
+ return { success: true, data: searchResult };
548
+ }
549
+ if (ctx.flags.format === 'json') {
550
+ output.printJson(searchResult);
551
+ return { success: true, data: searchResult };
552
+ }
553
+ output.printTable({
554
+ columns: [
555
+ { key: 'name', header: 'Plugin', width: 26 },
556
+ { key: 'description', header: 'Description', width: 35 },
557
+ { key: 'downloads', header: 'Downloads', width: 10, align: 'right' },
558
+ ],
559
+ data: searchResult.plugins.map(p => ({
560
+ name: p.verified ? `✓ ${p.name}` : p.name,
561
+ description: p.description.slice(0, 33) + (p.description.length > 33 ? '...' : ''),
562
+ downloads: p.downloads.toLocaleString(),
563
+ })),
564
+ });
565
+ output.writeln();
566
+ output.writeln(output.dim(`Showing ${searchResult.plugins.length} of ${searchResult.total} results`));
567
+ if (searchResult.hasMore) {
568
+ output.writeln(output.dim(`Use --limit to see more results`));
569
+ }
570
+ return { success: true, data: searchResult };
571
+ }
572
+ catch (error) {
573
+ spinner.fail('Search failed');
574
+ output.printError(`Error: ${String(error)}`);
575
+ return { success: false, exitCode: 1 };
576
+ }
577
+ },
578
+ };
579
+ // Main plugins command - Now with IPFS-based registry
243
580
  export const pluginsCommand = {
244
581
  name: 'plugins',
245
- description: 'Plugin management, installation, and lifecycle',
246
- subcommands: [listCommand, installCommand, uninstallCommand, toggleCommand, infoCommand, createCommand],
582
+ description: 'Plugin management with IPFS-based decentralized registry',
583
+ subcommands: [listCommand, searchCommand, installCommand, uninstallCommand, toggleCommand, infoCommand, createCommand],
247
584
  examples: [
248
- { command: 'claude-flow plugins list', description: 'List all plugins' },
249
- { command: 'claude-flow plugins install -n my-plugin', description: 'Install a plugin' },
585
+ { command: 'claude-flow plugins list', description: 'List plugins from IPFS registry' },
586
+ { command: 'claude-flow plugins search -q neural', description: 'Search for plugins' },
587
+ { command: 'claude-flow plugins install -n community-analytics', description: 'Install from IPFS' },
250
588
  { command: 'claude-flow plugins create -n my-plugin', description: 'Create new plugin' },
251
589
  ],
252
590
  action: async () => {
253
591
  output.writeln();
254
592
  output.writeln(output.bold('Claude Flow Plugin System'));
255
- output.writeln(output.dim('Extensible plugin architecture'));
593
+ output.writeln(output.dim('Decentralized plugin marketplace via IPFS'));
256
594
  output.writeln();
257
595
  output.writeln('Subcommands:');
258
596
  output.printList([
259
- 'list - List installed and available plugins',
260
- 'install - Install a plugin from registry or local path',
261
- 'uninstall - Remove an installed plugin',
262
- 'toggle - Enable or disable a plugin',
263
- 'info - Show detailed plugin information',
264
- 'create - Scaffold a new plugin project',
597
+ `${output.highlight('list')} - List plugins from IPFS registry`,
598
+ `${output.highlight('search')} - Search plugins by query`,
599
+ `${output.highlight('install')} - Install a plugin from IPFS or local path`,
600
+ `${output.highlight('uninstall')} - Remove an installed plugin`,
601
+ `${output.highlight('toggle')} - Enable or disable a plugin`,
602
+ `${output.highlight('info')} - Show detailed plugin information`,
603
+ `${output.highlight('create')} - Scaffold a new plugin project`,
604
+ ]);
605
+ output.writeln();
606
+ output.writeln(output.bold('IPFS-Based Features:'));
607
+ output.printList([
608
+ 'Decentralized registry via IPNS for discoverability',
609
+ 'Content-addressed storage for integrity verification',
610
+ 'Ed25519 signatures for plugin verification',
611
+ 'Trust levels: unverified, community, verified, official',
612
+ 'Security audit tracking and vulnerability reporting',
265
613
  ]);
266
614
  output.writeln();
267
- output.writeln('Core Plugins:');
615
+ output.writeln(output.bold('Official Plugins:'));
268
616
  output.printList([
269
- '@claude-flow/neural - Neural patterns and inference',
617
+ '@claude-flow/neural - Neural patterns and inference (WASM SIMD)',
270
618
  '@claude-flow/security - Security scanning and CVE detection',
271
- '@claude-flow/embeddings - Vector embeddings service',
619
+ '@claude-flow/embeddings - Vector embeddings with hyperbolic support',
272
620
  '@claude-flow/claims - Claims-based authorization',
621
+ '@claude-flow/performance- Performance profiling and benchmarks',
273
622
  ]);
274
623
  output.writeln();
624
+ output.writeln(output.dim('Run "claude-flow plugins list --official" to see all official plugins'));
275
625
  output.writeln(output.dim('Created with ❤️ by ruv.io'));
276
626
  return { success: true };
277
627
  },