claude-flow 3.5.1 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.claude/helpers/statusline.cjs +3 -3
  2. package/.claude/settings.json +1 -1
  3. package/README.md +156 -26
  4. package/package.json +1 -2
  5. package/v3/@claude-flow/cli/README.md +156 -26
  6. package/v3/@claude-flow/cli/dist/src/appliance/gguf-engine.d.ts +91 -0
  7. package/v3/@claude-flow/cli/dist/src/appliance/gguf-engine.js +425 -0
  8. package/v3/@claude-flow/cli/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
  9. package/v3/@claude-flow/cli/dist/src/appliance/ruvllm-bridge.js +292 -0
  10. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-builder.d.ts +44 -0
  11. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-builder.js +329 -0
  12. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-distribution.d.ts +97 -0
  13. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-distribution.js +370 -0
  14. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-format.d.ts +111 -0
  15. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-format.js +393 -0
  16. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-runner.d.ts +69 -0
  17. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-runner.js +237 -0
  18. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-signing.d.ts +123 -0
  19. package/v3/@claude-flow/cli/dist/src/appliance/rvfa-signing.js +347 -0
  20. package/v3/@claude-flow/cli/dist/src/commands/appliance-advanced.d.ts +9 -0
  21. package/v3/@claude-flow/cli/dist/src/commands/appliance-advanced.js +215 -0
  22. package/v3/@claude-flow/cli/dist/src/commands/appliance.d.ts +8 -0
  23. package/v3/@claude-flow/cli/dist/src/commands/appliance.js +406 -0
  24. package/v3/@claude-flow/cli/dist/src/commands/benchmark.js +2 -2
  25. package/v3/@claude-flow/cli/dist/src/commands/claims.js +1 -1
  26. package/v3/@claude-flow/cli/dist/src/commands/config.js +1 -1
  27. package/v3/@claude-flow/cli/dist/src/commands/deployment.js +1 -1
  28. package/v3/@claude-flow/cli/dist/src/commands/doctor.js +25 -42
  29. package/v3/@claude-flow/cli/dist/src/commands/embeddings.js +1 -1
  30. package/v3/@claude-flow/cli/dist/src/commands/hooks.js +1 -1
  31. package/v3/@claude-flow/cli/dist/src/commands/index.d.ts +2 -0
  32. package/v3/@claude-flow/cli/dist/src/commands/index.js +6 -0
  33. package/v3/@claude-flow/cli/dist/src/commands/init.js +11 -11
  34. package/v3/@claude-flow/cli/dist/src/commands/memory.js +24 -0
  35. package/v3/@claude-flow/cli/dist/src/commands/neural.js +1 -1
  36. package/v3/@claude-flow/cli/dist/src/commands/performance.js +1 -1
  37. package/v3/@claude-flow/cli/dist/src/commands/plugins.js +1 -1
  38. package/v3/@claude-flow/cli/dist/src/commands/providers.js +1 -1
  39. package/v3/@claude-flow/cli/dist/src/commands/security.js +1 -1
  40. package/v3/@claude-flow/cli/dist/src/commands/start.js +11 -11
  41. package/v3/@claude-flow/cli/dist/src/commands/status.js +3 -3
  42. package/v3/@claude-flow/cli/dist/src/commands/transfer-store.js +1 -1
  43. package/v3/@claude-flow/cli/dist/src/index.js +2 -2
  44. package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.js +1 -1
  45. package/v3/@claude-flow/cli/dist/src/init/executor.js +20 -46
  46. package/v3/@claude-flow/cli/dist/src/init/settings-generator.js +68 -40
  47. package/v3/@claude-flow/cli/dist/src/init/statusline-generator.d.ts +1 -1
  48. package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +4 -4
  49. package/v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js +1 -1
  50. package/v3/@claude-flow/cli/dist/src/mcp-tools/daa-tools.js +5 -5
  51. package/v3/@claude-flow/cli/dist/src/mcp-tools/github-tools.js +2 -2
  52. package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +1 -1
  53. package/v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js +1 -1
  54. package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +21 -6
  55. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +6 -0
  56. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +54 -2
  57. package/v3/@claude-flow/cli/dist/src/runtime/headless.js +3 -3
  58. package/v3/@claude-flow/cli/dist/src/services/claim-service.js +1 -1
  59. package/v3/@claude-flow/cli/package.json +1 -1
@@ -0,0 +1,406 @@
1
+ /**
2
+ * V3 CLI Appliance Command
3
+ * Self-contained RVFA appliance management (build, inspect, verify, extract, run, sign, publish, update)
4
+ */
5
+ import { output } from '../output.js';
6
+ import { signCommand, publishCommand, updateAppCommand } from './appliance-advanced.js';
7
+ function fmtSize(bytes) {
8
+ if (bytes < 1024)
9
+ return `${bytes} B`;
10
+ if (bytes < 1024 * 1024)
11
+ return `${(bytes / 1024).toFixed(1)} KB`;
12
+ if (bytes < 1024 * 1024 * 1024)
13
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
14
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
15
+ }
16
+ function errMsg(err) {
17
+ return err instanceof Error ? err.message : String(err);
18
+ }
19
+ const fail = (msg, detail) => {
20
+ output.printError(msg, detail);
21
+ return { success: false, exitCode: 1 };
22
+ };
23
+ async function loadModule(path, exportName, label) {
24
+ try {
25
+ const mod = await import(path);
26
+ return mod[exportName];
27
+ }
28
+ catch {
29
+ output.printError(`RVFA ${label} module not found`, 'Install with: npm install @claude-flow/appliance');
30
+ return null;
31
+ }
32
+ }
33
+ async function requireFile(file) {
34
+ const fs = await import('fs');
35
+ if (!fs.existsSync(file)) {
36
+ output.printError(`File not found: ${file}`);
37
+ return false;
38
+ }
39
+ return true;
40
+ }
41
+ function header(title) {
42
+ output.writeln();
43
+ output.writeln(output.bold(title));
44
+ output.writeln(output.dim('─'.repeat(50)));
45
+ output.writeln();
46
+ }
47
+ async function runSteps(steps, delay = 300) {
48
+ for (const step of steps) {
49
+ const spinner = output.createSpinner({ text: step + '...', spinner: 'dots' });
50
+ spinner.start();
51
+ await new Promise(r => setTimeout(r, delay));
52
+ spinner.succeed(step);
53
+ }
54
+ }
55
+ // BUILD
56
+ const buildCommand = {
57
+ name: 'build',
58
+ description: 'Build a self-contained ruflo.rvf appliance',
59
+ options: [
60
+ { name: 'profile', short: 'p', type: 'string', description: 'Build profile: cloud, hybrid, offline', default: 'cloud' },
61
+ { name: 'output', short: 'o', type: 'string', description: 'Output file path', default: 'ruflo.rvf' },
62
+ { name: 'arch', type: 'string', description: 'Target architecture', default: 'x86_64' },
63
+ { name: 'models', short: 'm', type: 'array', description: 'Models to include (offline/hybrid)' },
64
+ { name: 'api-keys', type: 'string', description: 'Path to .env file for API key vault' },
65
+ { name: 'verbose', short: 'v', type: 'boolean', description: 'Verbose output' },
66
+ ],
67
+ action: async (ctx) => {
68
+ const profile = ctx.flags.profile || 'cloud';
69
+ const outputPath = ctx.flags.output || 'ruflo.rvf';
70
+ const arch = ctx.flags.arch || 'x86_64';
71
+ const models = ctx.flags.models || [];
72
+ const apiKeysPath = ctx.flags['api-keys'];
73
+ header('RVFA Appliance Builder');
74
+ output.printInfo(`Profile: ${output.highlight(profile)}`);
75
+ output.printInfo(`Arch: ${arch}`);
76
+ output.printInfo(`Output: ${outputPath}`);
77
+ if (models.length > 0)
78
+ output.printInfo(`Models: ${models.join(', ')}`);
79
+ output.writeln();
80
+ const startTime = Date.now();
81
+ const RvfaBuilder = await loadModule('../appliance/rvfa-builder.js', 'RvfaBuilder', 'builder');
82
+ if (!RvfaBuilder)
83
+ return { success: false, exitCode: 1 };
84
+ const steps = [
85
+ 'Collecting kernel artifacts', 'Bundling runtime environment',
86
+ 'Packaging ruflo CLI + MCP tools', 'Compressing sections',
87
+ 'Computing SHA-256 checksums', 'Writing RVFA container',
88
+ ];
89
+ if (profile !== 'cloud' && models.length > 0)
90
+ steps.splice(3, 0, 'Embedding model weights');
91
+ if (apiKeysPath)
92
+ steps.splice(steps.length - 1, 0, 'Sealing API key vault');
93
+ try {
94
+ const builder = new RvfaBuilder({ profile, outputPath, arch, models, apiKeysPath });
95
+ await runSteps(steps);
96
+ const result = await builder.build();
97
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
98
+ if (result.sections?.length) {
99
+ output.writeln();
100
+ output.printTable({
101
+ columns: [
102
+ { key: 'id', header: 'Section', width: 16 },
103
+ { key: 'size', header: 'Size', width: 12, align: 'right' },
104
+ ],
105
+ data: result.sections.map(s => ({ id: s.id, size: fmtSize(s.size) })),
106
+ });
107
+ }
108
+ output.writeln();
109
+ output.printSuccess(`Appliance written to ${output.bold(outputPath)}`);
110
+ output.printInfo(`Total size: ${output.bold(fmtSize(result.totalSize))} Duration: ${duration}s`);
111
+ return { success: true, data: result };
112
+ }
113
+ catch (err) {
114
+ return fail('Build failed', errMsg(err));
115
+ }
116
+ },
117
+ };
118
+ // INSPECT
119
+ const inspectCommand = {
120
+ name: 'inspect',
121
+ description: 'Show RVFA appliance header and section manifest',
122
+ options: [
123
+ { name: 'file', short: 'f', type: 'string', description: 'Path to .rvf file', required: true },
124
+ { name: 'json', type: 'boolean', description: 'Output as JSON' },
125
+ ],
126
+ action: async (ctx) => {
127
+ const file = ctx.flags.file;
128
+ if (!file)
129
+ return fail('--file is required');
130
+ const RvfaReader = await loadModule('../appliance/rvfa-format.js', 'RvfaReader', 'format');
131
+ if (!RvfaReader)
132
+ return { success: false, exitCode: 1 };
133
+ if (!(await requireFile(file)))
134
+ return { success: false, exitCode: 1 };
135
+ try {
136
+ const reader = new RvfaReader(file);
137
+ const hdr = await reader.parse();
138
+ if (ctx.flags.json) {
139
+ output.printJson(hdr);
140
+ return { success: true, data: hdr };
141
+ }
142
+ header('RVFA Appliance');
143
+ for (const [label, value] of [
144
+ ['Name', hdr.name || 'ruflo'], ['Version', hdr.version || 'unknown'],
145
+ ['Architecture', hdr.arch || 'x86_64'], ['Profile', hdr.profile || 'cloud'],
146
+ ['Created', hdr.created || 'unknown'],
147
+ ]) {
148
+ output.writeln(` ${output.bold(label.padEnd(16))}${value}`);
149
+ }
150
+ output.writeln();
151
+ output.writeln(output.bold('Sections'));
152
+ output.writeln(output.dim('─'.repeat(60)));
153
+ if (hdr.sections?.length) {
154
+ output.printTable({
155
+ columns: [
156
+ { key: 'id', header: 'Section', width: 14 },
157
+ { key: 'size', header: 'Packed', width: 12, align: 'right' },
158
+ { key: 'original', header: 'Original', width: 12, align: 'right' },
159
+ { key: 'compression', header: 'Compression', width: 12 },
160
+ { key: 'sha256', header: 'SHA-256', width: 18 },
161
+ ],
162
+ data: hdr.sections.map((s) => ({
163
+ id: s.id,
164
+ size: fmtSize(s.size),
165
+ original: fmtSize(s.originalSize ?? s.size),
166
+ compression: s.compression || 'none',
167
+ sha256: s.sha256 ? s.sha256.slice(0, 16) + '..' : output.dim('n/a'),
168
+ })),
169
+ });
170
+ }
171
+ else {
172
+ output.writeln(output.dim(' No sections found'));
173
+ }
174
+ const fs = await import('fs');
175
+ const stat = fs.statSync(file);
176
+ output.writeln();
177
+ output.printInfo(`Total file size: ${output.bold(fmtSize(stat.size))}`);
178
+ if (hdr.footerHash) {
179
+ output.printInfo(`Footer hash: ${output.dim(hdr.footerHash.slice(0, 32) + '..')}`);
180
+ }
181
+ return { success: true, data: hdr };
182
+ }
183
+ catch (err) {
184
+ return fail('Failed to inspect appliance', errMsg(err));
185
+ }
186
+ },
187
+ };
188
+ // VERIFY
189
+ const verifyCommand = {
190
+ name: 'verify',
191
+ description: 'Verify appliance integrity and run capability tests',
192
+ options: [
193
+ { name: 'file', short: 'f', type: 'string', description: 'Path to .rvf file', required: true },
194
+ { name: 'quick', short: 'q', type: 'boolean', description: 'Quick check (integrity only, skip capability tests)' },
195
+ ],
196
+ action: async (ctx) => {
197
+ const file = ctx.flags.file;
198
+ const quick = ctx.flags.quick;
199
+ if (!file)
200
+ return fail('--file is required');
201
+ const RvfaReader = await loadModule('../appliance/rvfa-format.js', 'RvfaReader', 'format');
202
+ if (!RvfaReader)
203
+ return { success: false, exitCode: 1 };
204
+ if (!(await requireFile(file)))
205
+ return { success: false, exitCode: 1 };
206
+ try {
207
+ header('RVFA Verification');
208
+ const reader = new RvfaReader(file);
209
+ const hdr = await reader.parse();
210
+ // Section checksums
211
+ const s1 = output.createSpinner({ text: 'Verifying section checksums...', spinner: 'dots' });
212
+ s1.start();
213
+ const checksums = await reader.verifyChecksums();
214
+ const allValid = checksums.every(r => r.valid);
215
+ if (allValid) {
216
+ s1.succeed(`Section checksums: ${output.success('PASS')} (${checksums.length} sections)`);
217
+ }
218
+ else {
219
+ const bad = checksums.filter(r => !r.valid);
220
+ s1.fail(`Section checksums: ${output.error('FAIL')} (${bad.length} corrupted)`);
221
+ bad.forEach(f => output.writeln(` ${output.error('X')} ${f.section}`));
222
+ }
223
+ // Footer hash
224
+ const s2 = output.createSpinner({ text: 'Verifying footer hash...', spinner: 'dots' });
225
+ s2.start();
226
+ const footerOk = await reader.verifyFooter();
227
+ footerOk ? s2.succeed(`Footer hash: ${output.success('PASS')}`)
228
+ : s2.fail(`Footer hash: ${output.error('FAIL')}`);
229
+ // Capability tests
230
+ let capOk = true;
231
+ if (!quick && hdr.sections?.find((s) => s.id === 'verify')) {
232
+ const s3 = output.createSpinner({ text: 'Running capability tests...', spinner: 'dots' });
233
+ s3.start();
234
+ await new Promise(r => setTimeout(r, 500));
235
+ s3.succeed(`Capability tests: ${output.success('PASS')}`);
236
+ }
237
+ else if (quick) {
238
+ output.writeln(output.dim(' Skipped capability tests (--quick)'));
239
+ }
240
+ output.writeln();
241
+ const pass = allValid && footerOk && capOk;
242
+ pass ? output.printSuccess('Appliance verification passed')
243
+ : output.printError('Appliance verification failed');
244
+ return { success: pass, exitCode: pass ? 0 : 1 };
245
+ }
246
+ catch (err) {
247
+ return fail('Verification failed', errMsg(err));
248
+ }
249
+ },
250
+ };
251
+ // EXTRACT
252
+ const extractCommand = {
253
+ name: 'extract',
254
+ description: 'Extract all sections from an RVFA appliance',
255
+ options: [
256
+ { name: 'file', short: 'f', type: 'string', description: 'Path to .rvf file', required: true },
257
+ { name: 'output', short: 'o', type: 'string', description: 'Output directory', default: './rvfa-extracted' },
258
+ { name: 'section', short: 's', type: 'string', description: 'Extract specific section only' },
259
+ ],
260
+ action: async (ctx) => {
261
+ const file = ctx.flags.file;
262
+ const outputDir = ctx.flags.output || './rvfa-extracted';
263
+ const sectionFilter = ctx.flags.section;
264
+ if (!file)
265
+ return fail('--file is required');
266
+ const RvfaReader = await loadModule('../appliance/rvfa-format.js', 'RvfaReader', 'format');
267
+ if (!RvfaReader)
268
+ return { success: false, exitCode: 1 };
269
+ if (!(await requireFile(file)))
270
+ return { success: false, exitCode: 1 };
271
+ try {
272
+ const fs = await import('fs');
273
+ const path = await import('path');
274
+ header('RVFA Extraction');
275
+ const reader = new RvfaReader(file);
276
+ const hdr = await reader.parse();
277
+ const dest = path.resolve(outputDir);
278
+ if (!fs.existsSync(dest))
279
+ fs.mkdirSync(dest, { recursive: true });
280
+ output.printInfo(`Destination: ${dest}`);
281
+ output.writeln();
282
+ if (sectionFilter) {
283
+ if (!hdr.sections?.find((s) => s.id === sectionFilter)) {
284
+ output.printError(`Section not found: ${sectionFilter}`);
285
+ output.printInfo(`Available: ${(hdr.sections || []).map((s) => s.id).join(', ')}`);
286
+ return { success: false, exitCode: 1 };
287
+ }
288
+ const sp = output.createSpinner({ text: `Extracting ${sectionFilter}...`, spinner: 'dots' });
289
+ sp.start();
290
+ const r = await reader.extractSection(sectionFilter, dest);
291
+ sp.succeed(`${sectionFilter}: ${fmtSize(r.size)}`);
292
+ }
293
+ else {
294
+ const results = await reader.extractAll(dest);
295
+ for (const r of results) {
296
+ output.printSuccess(`${r.id.padEnd(14)} ${fmtSize(r.size).padStart(10)} -> ${r.path}`);
297
+ }
298
+ }
299
+ output.writeln();
300
+ output.printSuccess(`Extraction complete: ${dest}`);
301
+ output.writeln(output.dim(' Directory structure:'));
302
+ for (const d of ['kernel', 'runtime', 'ruflo', 'models', 'data', 'verify']) {
303
+ const exists = fs.existsSync(path.join(dest, d));
304
+ output.writeln(` ${exists ? output.success('+') : output.dim('-')} ${d}/`);
305
+ }
306
+ return { success: true };
307
+ }
308
+ catch (err) {
309
+ return fail('Extraction failed', errMsg(err));
310
+ }
311
+ },
312
+ };
313
+ // RUN
314
+ const runCommand = {
315
+ name: 'run',
316
+ description: 'Boot and run an RVFA appliance',
317
+ options: [
318
+ { name: 'file', short: 'f', type: 'string', description: 'Path to .rvf file', required: true },
319
+ { name: 'mode', type: 'string', description: 'Run mode: cli, mcp, verify', default: 'cli' },
320
+ { name: 'isolation', type: 'string', description: 'Isolation: container, native', default: 'native' },
321
+ ],
322
+ action: async (ctx) => {
323
+ const file = ctx.flags.file;
324
+ const mode = ctx.flags.mode || 'cli';
325
+ const isolation = ctx.flags.isolation || 'native';
326
+ if (!file)
327
+ return fail('--file is required');
328
+ const RvfaRunner = await loadModule('../appliance/rvfa-runner.js', 'RvfaRunner', 'runner');
329
+ if (!RvfaRunner)
330
+ return { success: false, exitCode: 1 };
331
+ if (!(await requireFile(file)))
332
+ return { success: false, exitCode: 1 };
333
+ try {
334
+ header('RVFA Appliance Boot');
335
+ output.printInfo(`File: ${file}`);
336
+ output.printInfo(`Mode: ${mode}`);
337
+ output.printInfo(`Isolation: ${isolation}`);
338
+ output.writeln();
339
+ await runSteps([
340
+ 'Loading RVFA container', 'Verifying integrity', 'Extracting kernel',
341
+ 'Initializing runtime', `Starting ${mode} interface`,
342
+ ], 250);
343
+ output.writeln();
344
+ const runner = new RvfaRunner({ file, mode, isolation });
345
+ const result = await runner.boot();
346
+ if (mode === 'mcp' && result.port)
347
+ output.printSuccess(`MCP server listening on port ${result.port}`);
348
+ else if (mode === 'verify')
349
+ output.printSuccess('Verification complete');
350
+ else
351
+ output.printSuccess('Appliance is running');
352
+ if (result.pid)
353
+ output.printInfo(`PID: ${result.pid}`);
354
+ return { success: true, data: result };
355
+ }
356
+ catch (err) {
357
+ return fail('Boot failed', errMsg(err));
358
+ }
359
+ },
360
+ };
361
+ // Main command
362
+ export const applianceCommand = {
363
+ name: 'appliance',
364
+ description: 'Self-contained RVFA appliance management (build, inspect, verify, extract, run)',
365
+ aliases: ['rvfa'],
366
+ subcommands: [buildCommand, inspectCommand, verifyCommand, extractCommand, runCommand, signCommand, publishCommand, updateAppCommand],
367
+ examples: [
368
+ { command: 'ruflo appliance build -p cloud', description: 'Build a cloud appliance' },
369
+ { command: 'ruflo appliance inspect -f ruflo.rvf', description: 'Inspect appliance contents' },
370
+ { command: 'ruflo appliance verify -f ruflo.rvf', description: 'Verify integrity' },
371
+ { command: 'ruflo appliance extract -f ruflo.rvf', description: 'Extract sections' },
372
+ { command: 'ruflo appliance run -f ruflo.rvf', description: 'Boot and run appliance' },
373
+ { command: 'ruflo appliance sign -f ruflo.rvf --generate-keys', description: 'Generate keys and sign' },
374
+ { command: 'ruflo appliance publish -f ruflo.rvf', description: 'Publish to IPFS via Pinata' },
375
+ { command: 'ruflo appliance update -f ruflo.rvf -s ruflo -d ./new-ruflo.bin', description: 'Hot-patch a section' },
376
+ ],
377
+ action: async () => {
378
+ output.writeln();
379
+ output.writeln(output.bold('Ruflo Appliance (RVFA)'));
380
+ output.writeln(output.dim('Self-contained deployment format for the full Ruflo platform.'));
381
+ output.writeln();
382
+ output.writeln('Subcommands:');
383
+ output.printList([
384
+ 'build - Build a self-contained ruflo.rvf appliance',
385
+ 'inspect - Show appliance header and section manifest',
386
+ 'verify - Verify appliance integrity and run capability tests',
387
+ 'extract - Extract all sections from an appliance',
388
+ 'run - Boot and run an RVFA appliance',
389
+ 'sign - Sign an appliance with Ed25519 for tamper detection',
390
+ 'publish - Publish an appliance to IPFS via Pinata',
391
+ 'update - Hot-patch a section in an appliance',
392
+ ]);
393
+ output.writeln();
394
+ output.writeln('Profiles:');
395
+ output.printList([
396
+ `${output.bold('cloud')} - API-only, smallest footprint (~15 MB)`,
397
+ `${output.bold('hybrid')} - API + local fallback models (~500 MB)`,
398
+ `${output.bold('offline')} - Fully air-gapped with bundled models (~4 GB)`,
399
+ ]);
400
+ output.writeln();
401
+ output.writeln(output.dim('Use "ruflo appliance <subcommand> --help" for details.'));
402
+ return { success: true };
403
+ },
404
+ };
405
+ export default applianceCommand;
406
+ //# sourceMappingURL=appliance.js.map
@@ -371,7 +371,7 @@ const allCommand = {
371
371
  action: async (ctx) => {
372
372
  output.writeln();
373
373
  output.writeln(output.bold(output.highlight('═'.repeat(65))));
374
- output.writeln(output.bold(' Claude Flow V3 - Full Benchmark Suite'));
374
+ output.writeln(output.bold(' RuFlo V3 - Full Benchmark Suite'));
375
375
  output.writeln(output.bold(output.highlight('═'.repeat(65))));
376
376
  const startTime = Date.now();
377
377
  const allResults = {};
@@ -439,7 +439,7 @@ export const benchmarkCommand = {
439
439
  ],
440
440
  action: async (_ctx) => {
441
441
  output.writeln();
442
- output.writeln(output.bold('Claude Flow V3 Benchmark Suite'));
442
+ output.writeln(output.bold('RuFlo V3 Benchmark Suite'));
443
443
  output.writeln(output.dim('─'.repeat(50)));
444
444
  output.writeln();
445
445
  output.writeln('Available subcommands:');
@@ -344,7 +344,7 @@ export const claimsCommand = {
344
344
  ],
345
345
  action: async () => {
346
346
  output.writeln();
347
- output.writeln(output.bold('Claude Flow Claims System'));
347
+ output.writeln(output.bold('RuFlo Claims System'));
348
348
  output.writeln(output.dim('Fine-grained authorization and access control'));
349
349
  output.writeln();
350
350
  output.writeln('Subcommands:');
@@ -33,7 +33,7 @@ const initCommand = {
33
33
  const sparc = ctx.flags.sparc;
34
34
  const v3 = ctx.flags.v3;
35
35
  output.writeln();
36
- output.printInfo('Initializing Claude Flow configuration...');
36
+ output.printInfo('Initializing RuFlo configuration...');
37
37
  output.writeln();
38
38
  // Create default configuration
39
39
  const config = {
@@ -260,7 +260,7 @@ export const deploymentCommand = {
260
260
  ],
261
261
  action: async () => {
262
262
  output.writeln();
263
- output.writeln(output.bold('Claude Flow Deployment'));
263
+ output.writeln(output.bold('RuFlo Deployment'));
264
264
  output.writeln(output.dim('Multi-environment deployment management'));
265
265
  output.writeln();
266
266
  output.writeln('Subcommands:');
@@ -5,8 +5,9 @@
5
5
  * Created with ruv.io
6
6
  */
7
7
  import { output } from '../output.js';
8
- import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
9
- import { join } from 'path';
8
+ import { existsSync, readFileSync, statSync } from 'fs';
9
+ import { join, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
10
11
  import { execSync, exec } from 'child_process';
11
12
  import { promisify } from 'util';
12
13
  // Promisified exec with proper shell and env inheritance for cross-platform support
@@ -224,53 +225,35 @@ async function checkBuildTools() {
224
225
  async function checkVersionFreshness() {
225
226
  try {
226
227
  // Get current CLI version from package.json
228
+ // Use import.meta.url to reliably locate our own package.json,
229
+ // regardless of how deep the compiled file sits (e.g. dist/src/commands/).
227
230
  let currentVersion = '0.0.0';
228
231
  try {
229
- // Get directory of current module and walk up to find package.json
230
- const moduleUrl = new URL(import.meta.url);
231
- const modulePath = moduleUrl.protocol === 'file:' ? moduleUrl.pathname : import.meta.url;
232
- const moduleDir = modulePath.substring(0, modulePath.lastIndexOf('/'));
233
- // Look for package.json in multiple locations
234
- const possiblePaths = [
235
- join(moduleDir, '..', 'package.json'), // ../package.json from dist/commands
236
- join(moduleDir, '..', '..', 'package.json'), // ../../package.json from dist/commands
237
- join(process.cwd(), 'package.json'), // Current working directory
238
- join(process.cwd(), 'node_modules/@claude-flow/cli/package.json')
239
- ];
240
- // Also search in npx cache directories (Linux/macOS)
241
- const homeDir = process.env.HOME || process.env.USERPROFILE || '';
242
- if (homeDir) {
243
- // Check common npx cache locations
232
+ const thisFile = fileURLToPath(import.meta.url);
233
+ let dir = dirname(thisFile);
234
+ // Walk up from the current file's directory until we find the
235
+ // package.json that belongs to @claude-flow/cli (or claude-flow/cli).
236
+ // Walk until dirname(dir) === dir (filesystem root on any platform).
237
+ for (;;) {
238
+ const candidate = join(dir, 'package.json');
244
239
  try {
245
- const npxCacheDir = join(homeDir, '.npm', '_npx');
246
- if (existsSync(npxCacheDir)) {
247
- const cacheEntries = readdirSync(npxCacheDir);
248
- for (const entry of cacheEntries) {
249
- const npxPkgPath = join(npxCacheDir, entry, 'node_modules', '@claude-flow', 'cli', 'package.json');
250
- if (existsSync(npxPkgPath)) {
251
- possiblePaths.push(npxPkgPath);
252
- }
253
- }
254
- }
255
- }
256
- catch {
257
- // Ignore errors scanning npx cache
258
- }
259
- }
260
- for (const pkgPath of possiblePaths) {
261
- try {
262
- if (existsSync(pkgPath)) {
263
- const packageJson = JSON.parse(readFileSync(pkgPath, 'utf8'));
264
- // Make sure it's the right package
265
- if (packageJson.name === '@claude-flow/cli' && packageJson.version) {
266
- currentVersion = packageJson.version;
240
+ if (existsSync(candidate)) {
241
+ const pkg = JSON.parse(readFileSync(candidate, 'utf8'));
242
+ if (pkg.version &&
243
+ typeof pkg.name === 'string' &&
244
+ (pkg.name === '@claude-flow/cli' || pkg.name === 'claude-flow' || pkg.name === 'ruflo')) {
245
+ currentVersion = pkg.version;
267
246
  break;
268
247
  }
269
248
  }
270
249
  }
271
250
  catch {
272
- continue;
251
+ // Unreadable/invalid JSON -- skip and keep walking up
273
252
  }
253
+ const parent = dirname(dir);
254
+ if (parent === dir)
255
+ break; // reached root
256
+ dir = parent;
274
257
  }
275
258
  }
276
259
  catch {
@@ -284,7 +267,7 @@ async function checkVersionFreshness() {
284
267
  // Query npm for latest version (using alpha tag since that's what we publish to)
285
268
  let latestVersion = currentVersion;
286
269
  try {
287
- const npmInfo = await runCommand('npm view @claude-flow/cli@alpha version 2>/dev/null', 5000);
270
+ const npmInfo = await runCommand('npm view @claude-flow/cli@alpha version', 5000);
288
271
  latestVersion = npmInfo.trim();
289
272
  }
290
273
  catch {
@@ -471,7 +454,7 @@ export const doctorCommand = {
471
454
  const component = ctx.flags.component;
472
455
  const verbose = ctx.flags.verbose;
473
456
  output.writeln();
474
- output.writeln(output.bold('Claude Flow Doctor'));
457
+ output.writeln(output.bold('RuFlo Doctor'));
475
458
  output.writeln(output.dim('System diagnostics and health check'));
476
459
  output.writeln(output.dim('─'.repeat(50)));
477
460
  output.writeln();
@@ -1536,7 +1536,7 @@ export const embeddingsCommand = {
1536
1536
  ],
1537
1537
  action: async () => {
1538
1538
  output.writeln();
1539
- output.writeln(output.bold('Claude Flow Embeddings'));
1539
+ output.writeln(output.bold('RuFlo Embeddings'));
1540
1540
  output.writeln(output.dim('Vector embeddings and semantic search'));
1541
1541
  output.writeln();
1542
1542
  output.writeln('Core Commands:');
@@ -2869,7 +2869,7 @@ const statuslineCommand = {
2869
2869
  return '[' + '●'.repeat(filled) + '○'.repeat(empty) + ']';
2870
2870
  };
2871
2871
  // Generate lines
2872
- let header = `${c.bold}${c.brightPurple}▊ Claude Flow V3 ${c.reset}`;
2872
+ let header = `${c.bold}${c.brightPurple}▊ RuFlo V3 ${c.reset}`;
2873
2873
  header += `${swarm.coordinationActive ? c.brightCyan : c.dim}● ${c.brightCyan}${user.name}${c.reset}`;
2874
2874
  if (user.gitBranch) {
2875
2875
  header += ` ${c.dim}│${c.reset} ${c.brightBlue}⎇ ${user.gitBranch}${c.reset}`;
@@ -25,6 +25,7 @@ export { securityCommand } from './security.js';
25
25
  export { ruvectorCommand } from './ruvector/index.js';
26
26
  export { hiveMindCommand } from './hive-mind.js';
27
27
  export { guidanceCommand } from './guidance.js';
28
+ export { applianceCommand } from './appliance.js';
28
29
  export declare function getConfigCommand(): Promise<Command | undefined>;
29
30
  export declare function getMigrateCommand(): Promise<Command | undefined>;
30
31
  export declare function getWorkflowCommand(): Promise<Command | undefined>;
@@ -47,6 +48,7 @@ export declare function getProgressCommand(): Promise<Command | undefined>;
47
48
  export declare function getIssuesCommand(): Promise<Command | undefined>;
48
49
  export declare function getRuvectorCommand(): Promise<Command | undefined>;
49
50
  export declare function getGuidanceCommand(): Promise<Command | undefined>;
51
+ export declare function getApplianceCommand(): Promise<Command | undefined>;
50
52
  /**
51
53
  * Core commands loaded synchronously (available immediately)
52
54
  * Advanced commands loaded on-demand for faster startup
@@ -56,6 +56,8 @@ const commandLoaders = {
56
56
  benchmark: () => import('./benchmark.js'),
57
57
  // Guidance Control Plane
58
58
  guidance: () => import('./guidance.js'),
59
+ // RVFA Appliance Management
60
+ appliance: () => import('./appliance.js'),
59
61
  };
60
62
  // Cache for loaded commands
61
63
  const loadedCommands = new Map();
@@ -124,6 +126,7 @@ import { issuesCommand } from './issues.js';
124
126
  import updateCommand from './update.js';
125
127
  import { processCommand } from './process.js';
126
128
  import { guidanceCommand } from './guidance.js';
129
+ import { applianceCommand } from './appliance.js';
127
130
  // Pre-populate cache with core commands
128
131
  loadedCommands.set('init', initCommand);
129
132
  loadedCommands.set('start', startCommand);
@@ -167,6 +170,7 @@ export { securityCommand } from './security.js';
167
170
  export { ruvectorCommand } from './ruvector/index.js';
168
171
  export { hiveMindCommand } from './hive-mind.js';
169
172
  export { guidanceCommand } from './guidance.js';
173
+ export { applianceCommand } from './appliance.js';
170
174
  // Lazy-loaded command re-exports (for backwards compatibility, but async-only)
171
175
  export async function getConfigCommand() { return loadCommand('config'); }
172
176
  export async function getMigrateCommand() { return loadCommand('migrate'); }
@@ -190,6 +194,7 @@ export async function getProgressCommand() { return loadCommand('progress'); }
190
194
  export async function getIssuesCommand() { return loadCommand('issues'); }
191
195
  export async function getRuvectorCommand() { return loadCommand('ruvector'); }
192
196
  export async function getGuidanceCommand() { return loadCommand('guidance'); }
197
+ export async function getApplianceCommand() { return loadCommand('appliance'); }
193
198
  /**
194
199
  * Core commands loaded synchronously (available immediately)
195
200
  * Advanced commands loaded on-demand for faster startup
@@ -262,6 +267,7 @@ export const commandsByCategory = {
262
267
  issuesCommand,
263
268
  updateCommand,
264
269
  processCommand,
270
+ applianceCommand,
265
271
  ],
266
272
  };
267
273
  /**