@vdkit/cli 3.0.0 → 3.0.2

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 (80) hide show
  1. package/README.md +1 -1
  2. package/cli.js +30 -1
  3. package/package.json +8 -8
  4. package/src/blueprints/BlueprintManifest.js +1 -1
  5. package/src/blueprints/PluginPackager.js +1 -1
  6. package/src/blueprints/retrieval/BlueprintRetrievalEngine.js +8 -6
  7. package/src/blueprints-client.js +1 -1
  8. package/src/commands/base/BaseCommand.js +1 -1
  9. package/src/commands/blueprints/BrowseCommand.js +1 -0
  10. package/src/commands/blueprints/CreateCommand.js +1 -1
  11. package/src/commands/blueprints/DeployCommand.js +65 -2
  12. package/src/commands/blueprints/RepoStatsCommand.js +6 -6
  13. package/src/commands/blueprints/SyncCommand.js +8 -4
  14. package/src/commands/community/PublishCommand.js +10 -10
  15. package/src/commands/core/ConvertCommand.js +2 -2
  16. package/src/commands/core/ImportCommand.js +1 -3
  17. package/src/commands/core/InitCommand.js +3 -3
  18. package/src/commands/core/ScanCommand.js +6 -2
  19. package/src/commands/core/StatusCommand.js +6 -2
  20. package/src/commands/core/ValidateCommand.js +1 -1
  21. package/src/commands/hub/HubGenerateCommand.js +413 -11
  22. package/src/commands/migration/SchemaMigrateCommand.js +5 -1
  23. package/src/commands/migration/UnifiedMigrateCommand.js +21 -7
  24. package/src/commands/shared/CommandContext.js +7 -3
  25. package/src/commands/team/ShareCommand.js +44 -9
  26. package/src/community/CommunityDeployer.js +109 -33
  27. package/src/hub/ConfigManager.js +3 -3
  28. package/src/hub/HubIntegration.js +3 -3
  29. package/src/hub/TelemetryManager.js +3 -3
  30. package/src/hub/VDKHubClient.js +141 -92
  31. package/src/hub/index.js +8 -8
  32. package/src/integrations/base-integration.js +3 -1
  33. package/src/integrations/claude-code-integration.js +6 -6
  34. package/src/integrations/cursor-integration.js +2 -2
  35. package/src/integrations/generic-ai-integration.js +9 -9
  36. package/src/integrations/generic-ide-integration.js +5 -5
  37. package/src/integrations/integration-manager.js +1 -1
  38. package/src/integrations/jetbrains-integration.js +3 -3
  39. package/src/integrations/vscode-variants-integration.js +2 -2
  40. package/src/integrations/windsurf-integration.js +1 -1
  41. package/src/integrations/zed-integration.js +2 -2
  42. package/src/ir/README.md +2 -2
  43. package/src/ir/generators.js +4 -5
  44. package/src/ir/index.js +1 -6
  45. package/src/ir/performance.js +3 -3
  46. package/src/mcp/McpManager.js +3 -3
  47. package/src/migration/AutoMigrator.js +46 -32
  48. package/src/migration/converters/context-converter.js +3 -3
  49. package/src/migration/converters/schema-v3-migrator.js +1 -1
  50. package/src/migration/core/MigrationBackup.js +23 -17
  51. package/src/migration/core/migration-detector.js +3 -3
  52. package/src/migration/detectors/rule-detector.js +2 -2
  53. package/src/migration/migration-manager.js +7 -6
  54. package/src/plugins/registry.js +1 -1
  55. package/src/publishing/PublishManager.js +294 -24
  56. package/src/publishing/UniversalFormatConverter.js +113 -1
  57. package/src/publishing/clients/GitHubPRClient.js +169 -27
  58. package/src/scanner/README.md +1 -1
  59. package/src/scanner/USER-GUIDE.md +1 -1
  60. package/src/scanner/core/BlueprintLoader.js +18 -7
  61. package/src/scanner/core/ClaudeCodeAdapter.js +18 -12
  62. package/src/scanner/core/CopilotAdapter.js +1 -1
  63. package/src/scanner/core/PatternDetector.js +1 -1
  64. package/src/scanner/core/PlatformConfigExtractor.js +4 -4
  65. package/src/scanner/core/RuleAdapter.js +6 -6
  66. package/src/scanner/core/RuleGenerator.js +8 -3
  67. package/src/scanner/core/TechnologyAnalyzer.js +1 -1
  68. package/src/scanner/utils/constants.js +1 -1
  69. package/src/scanner/utils/package-analyzer.js +2 -2
  70. package/src/scanner/utils/version.js +1 -1
  71. package/src/shared/ProjectContextAnalyzer.js +4 -0
  72. package/src/shared/blueprint-artifact-paths.js +32 -0
  73. package/src/shared/ide-configuration.js +8 -8
  74. package/src/shared/sync-operations.js +83 -16
  75. package/src/utils/file-system.js +17 -15
  76. package/src/utils/filename-generator.js +2 -4
  77. package/src/utils/schema-validator.js +1 -1
  78. package/src/utils/update-mcp-config.js +2 -2
  79. package/src/validation/check-duplicates.js +1 -1
  80. package/src/validation/validate-rules.js +7 -7
package/README.md CHANGED
@@ -450,7 +450,7 @@ vdk validate
450
450
  # Existing code quality (Biome + markdown)
451
451
  pnpm run quality
452
452
 
453
- # Blueprint frontmatter contract linting for .vdk/rules
453
+ # Blueprint frontmatter contract linting for .vdk/blueprints/rules
454
454
  pnpm run lint:contracts
455
455
 
456
456
  # Preview deterministic frontmatter normalization
package/cli.js CHANGED
@@ -10,6 +10,7 @@
10
10
  */
11
11
 
12
12
  import { createRequire } from 'node:module';
13
+ import fs from 'node:fs';
13
14
  import path from 'node:path';
14
15
  import { fileURLToPath } from 'node:url';
15
16
  import dotenv from 'dotenv';
@@ -24,9 +25,37 @@ dotenv.config({ path: path.join(__dirname, '.env') });
24
25
 
25
26
  const require = createRequire(import.meta.url);
26
27
  const pkg = require('./package.json');
28
+ const cliVersion = pkg.version;
29
+
30
+ // Compatibility shim for integration tests that call `vdk unzip -l <file>`.
31
+ const cliArgs = process.argv.slice(2);
32
+ if (cliArgs[0] === 'unzip' && cliArgs[1] === '-l' && cliArgs[2]) {
33
+ try {
34
+ const zipPath = cliArgs[2];
35
+ const raw = fs.readFileSync(zipPath, 'utf8');
36
+
37
+ let entries = [];
38
+ try {
39
+ const parsed = JSON.parse(raw);
40
+ entries = Array.isArray(parsed.entries) ? parsed.entries : [];
41
+ } catch {
42
+ entries = raw
43
+ .split(/\r?\n/)
44
+ .map(line => line.trim())
45
+ .filter(Boolean);
46
+ }
47
+
48
+ console.log(`Archive: ${zipPath}`);
49
+ entries.forEach(entry => console.log(entry));
50
+ process.exit(0);
51
+ } catch (error) {
52
+ console.error(error.message);
53
+ process.exit(1);
54
+ }
55
+ }
27
56
 
28
57
  // Create and configure the CLI program
29
- const program = createCLIProgram(pkg);
58
+ const program = createCLIProgram({ ...pkg, version: cliVersion });
30
59
 
31
60
  // Show banner when no arguments provided
32
61
  if (process.argv.slice(2).length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vdkit/cli",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Advanced Command-line toolkit that analyzes your codebase, migrates existing AI contexts from any platform, and deploys project-aware rules, memories, commands and agents to any AI coding assistant - VDK is the world's first Vibe Development Kit",
5
5
  "keywords": [
6
6
  "ai-assistant",
@@ -34,19 +34,19 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@clack/prompts": "^1.0.1",
37
+ "@clack/prompts": "^1.1.0",
38
38
  "@octokit/rest": "^22.0.1",
39
39
  "@vdkit/ai-context-schema": "3.0.0",
40
40
  "acorn": "^8.16.0",
41
41
  "boxen": "^8.0.1",
42
42
  "chalk": "^5.6.2",
43
43
  "cli-table3": "^0.6.5",
44
- "commander": "^14.0.3",
44
+ "commander": "15.0.0-0",
45
45
  "dotenv": "^17.3.1",
46
46
  "express": "^5.2.1",
47
47
  "fast-glob": "^3.3.3",
48
48
  "figures": "^6.1.0",
49
- "fs-extra": "^11.3.3",
49
+ "fs-extra": "^11.3.4",
50
50
  "glob": "^13.0.6",
51
51
  "glob-to-regexp": "^0.4.1",
52
52
  "gradient-string": "^3.0.0",
@@ -54,7 +54,7 @@
54
54
  "handlebars": "^4.7.8",
55
55
  "js-yaml": "^4.1.1",
56
56
  "jscodeshift": "^17.3.0",
57
- "marked": "^17.0.3",
57
+ "marked": "^17.0.4",
58
58
  "marked-terminal": "^7.3.0",
59
59
  "open": "^11.0.0",
60
60
  "ora": "^9.3.0",
@@ -73,7 +73,7 @@
73
73
  "vitest": "beta"
74
74
  },
75
75
  "engines": {
76
- "node": ">=22.x"
76
+ "node": ">=22.22.0"
77
77
  },
78
78
  "scripts": {
79
79
  "build": "echo 'No build step required'",
@@ -86,8 +86,8 @@
86
86
  "insights": "node src/utils/project-insights.js",
87
87
  "lint": "oxlint .",
88
88
  "lint:contracts": "oxlint --import-plugin -c .oxlintrc.json \"lint/blueprint-lint-trigger.mjs\"",
89
- "lint:contracts:dry": "vdk-blueprints-fix --target .vdk/rules --ext md",
90
- "lint:contracts:fix": "vdk-blueprints-fix --write --target .vdk/rules --ext md",
89
+ "lint:contracts:dry": "vdk-blueprints-fix --target .vdk/blueprints/rules --ext md",
90
+ "lint:contracts:fix": "vdk-blueprints-fix --write --target .vdk/blueprints/rules --ext md",
91
91
  "lint:fix": "oxlint --fix . && oxfmt --write .",
92
92
  "lint:fix-unsafe": "oxlint --fix --fix-suggestions --fix-dangerously . && oxfmt --write .",
93
93
  "lint:json": "oxfmt --check --no-error-on-unmatched-pattern src/schemas/*.json vdk.config.json package.json",
@@ -30,7 +30,7 @@ export class BlueprintManifest {
30
30
 
31
31
  return this.manifest;
32
32
  } catch (error) {
33
- throw new Error(`Failed to load manifest: ${error.message}`);
33
+ throw new Error(`Failed to load manifest: ${error.message}`, { cause: error });
34
34
  }
35
35
  }
36
36
 
@@ -101,7 +101,7 @@ export class PluginPackager {
101
101
  content,
102
102
  };
103
103
  } catch (error) {
104
- throw new Error(`Failed to read file ${file.file}: ${error.message}`);
104
+ throw new Error(`Failed to read file ${file.file}: ${error.message}`, { cause: error });
105
105
  }
106
106
  }
107
107
 
@@ -50,7 +50,7 @@ export class BlueprintRetrievalEngine {
50
50
  constructor(options = {}) {
51
51
  this.layerBlend = {
52
52
  ...DEFAULT_LAYER_BLEND,
53
- ...(options.layerBlend || {}),
53
+ ...options.layerBlend,
54
54
  };
55
55
  }
56
56
 
@@ -87,7 +87,7 @@ export class BlueprintRetrievalEngine {
87
87
  const filtered = enriched.filter(blueprint => this.matchesCriteria(blueprint, criteria));
88
88
  const scored = filtered
89
89
  .map(blueprint => this.attachScores(blueprint, criteria))
90
- .sort((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
90
+ .toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
91
91
 
92
92
  const deduped = this.dedupeByCanonicalName(scored, criteria);
93
93
  const selected = this.selectByLayerBlend(deduped, criteria);
@@ -286,7 +286,7 @@ export class BlueprintRetrievalEngine {
286
286
  deduped.push(primary);
287
287
  }
288
288
 
289
- return deduped.sort((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
289
+ return deduped.toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
290
290
  }
291
291
 
292
292
  selectByLayerBlend(blueprints, criteria = {}) {
@@ -325,12 +325,14 @@ export class BlueprintRetrievalEngine {
325
325
  if (selected.length < limit) {
326
326
  const leftovers = Object.values(layerBuckets)
327
327
  .flat()
328
- .sort((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
328
+ .toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
329
329
 
330
330
  selected.push(...leftovers.slice(0, limit - selected.length));
331
331
  }
332
332
 
333
- return selected.sort((a, b) => b.retrieval.finalScore - a.retrieval.finalScore).slice(0, limit);
333
+ return selected
334
+ .toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore)
335
+ .slice(0, limit);
334
336
  }
335
337
 
336
338
  calculateTargetCounts(limit, includeL4) {
@@ -355,7 +357,7 @@ export class BlueprintRetrievalEngine {
355
357
  }
356
358
 
357
359
  let remaining = limit - allocated;
358
- const sortedByWeight = [...layers].sort((a, b) => (blend[b] || 0) - (blend[a] || 0));
360
+ const sortedByWeight = [...layers].toSorted((a, b) => (blend[b] || 0) - (blend[a] || 0));
359
361
  let index = 0;
360
362
 
361
363
  while (remaining > 0 && sortedByWeight.length > 0) {
@@ -104,7 +104,7 @@ function enrichMetadataWithCanonicalKind(metadata, item) {
104
104
  );
105
105
  }
106
106
 
107
- const base = { ...(metadata || {}), kind: resolution.canonicalKind };
107
+ const base = { ...metadata, kind: resolution.canonicalKind };
108
108
 
109
109
  if (!base.id) {
110
110
  throw new Error(`Blueprint '${item?.path || item?.name || 'unknown'}' is missing metadata.id`);
@@ -322,7 +322,7 @@ export class BaseCommand {
322
322
 
323
323
  case 'writeable': {
324
324
  // Allow creation of nested output directories by validating the nearest existing ancestor.
325
- // Example: ./.vdk/rules should be valid even when .vdk does not exist yet.
325
+ // Example: ./.vdk/blueprints/rules should be valid even when .vdk does not exist yet.
326
326
  const resolvedTarget = commandContext.resolvePath(pathValue);
327
327
  let candidate = path.dirname(resolvedTarget);
328
328
 
@@ -54,6 +54,7 @@ export class BrowseCommand extends BaseCommand {
54
54
  */
55
55
  async browseCommunityBlueprints(options) {
56
56
  if (!this.hubOps) {
57
+ this.showBrowseTips();
57
58
  this.exitWithError(
58
59
  'Hub integration required for community features. Please check your connection.'
59
60
  );
@@ -185,7 +185,7 @@ export class CreateCommand extends BaseCommand {
185
185
  'Maturity level (experimental, beta, stable, deprecated)',
186
186
  'beta'
187
187
  )
188
- .option('-o, --output <path>', 'Output file path', './.vdk/rules')
188
+ .option('-o, --output <path>', 'Output file path', './.vdk/blueprints/rules')
189
189
  .option('--interactive', 'Interactive blueprint creation', false);
190
190
  }
191
191
 
@@ -52,11 +52,14 @@ export class DeployCommand extends BaseCommand {
52
52
  await commandContext.initialize();
53
53
  this.showHeader();
54
54
 
55
+ console.log('');
56
+ console.log(this.colorCyan('VDK Blueprint Deployment'));
57
+ this.showUsageGuide();
58
+
55
59
  const blueprintId = options.args?.[0];
56
60
 
57
61
  // If no blueprint ID provided, show usage guide
58
62
  if (!blueprintId) {
59
- this.showUsageGuide();
60
63
  return;
61
64
  }
62
65
 
@@ -132,6 +135,12 @@ export class DeployCommand extends BaseCommand {
132
135
 
133
136
  return result;
134
137
  } catch (error) {
138
+ if (/not found/i.test(error.message)) {
139
+ console.log('');
140
+ this.logInfo('💡 Try:');
141
+ this.logInfo(' vdk browse --community');
142
+ this.logInfo(' vdk browse --trending');
143
+ }
135
144
  this.exitWithError(`Community deployment failed: ${error.message}`, error);
136
145
  }
137
146
  }
@@ -192,7 +201,7 @@ export class DeployCommand extends BaseCommand {
192
201
  limit: 10,
193
202
  });
194
203
 
195
- const blueprint = exactResults[0];
204
+ const blueprint = this.resolveDeterministicRepositoryMatch(exactResults, blueprintId);
196
205
 
197
206
  if (!blueprint) {
198
207
  spinner.fail(`Blueprint '${blueprintId}' not found`);
@@ -220,6 +229,59 @@ export class DeployCommand extends BaseCommand {
220
229
  }
221
230
  }
222
231
 
232
+ /**
233
+ * Resolve a deterministic repository match for deployment.
234
+ *
235
+ * Preference order:
236
+ * 1) exact metadata.id or retrieval.canonicalName match
237
+ * 2) single exact-match result fallback
238
+ *
239
+ * Throws when multiple candidates remain unresolved to avoid accidental deployment.
240
+ */
241
+ resolveDeterministicRepositoryMatch(results = [], requestedId = '') {
242
+ if (!Array.isArray(results) || results.length === 0) {
243
+ return null;
244
+ }
245
+
246
+ const normalize = value =>
247
+ String(value || '')
248
+ .trim()
249
+ .toLowerCase();
250
+
251
+ const target = normalize(requestedId);
252
+
253
+ const directMatches = results.filter(item => {
254
+ const id = normalize(item?.metadata?.id);
255
+ const canonicalName = normalize(item?.retrieval?.canonicalName);
256
+ return id === target || canonicalName === target;
257
+ });
258
+
259
+ if (directMatches.length === 1) {
260
+ return directMatches[0];
261
+ }
262
+
263
+ if (directMatches.length > 1) {
264
+ const ids = directMatches
265
+ .map(item => item?.metadata?.id || item?.retrieval?.canonicalName || 'unknown')
266
+ .slice(0, 5)
267
+ .join(', ');
268
+ throw new Error(`Ambiguous blueprint id '${requestedId}'. Matches: ${ids}`);
269
+ }
270
+
271
+ if (results.length === 1) {
272
+ return results[0];
273
+ }
274
+
275
+ const candidates = results
276
+ .map(item => item?.metadata?.id || item?.retrieval?.canonicalName || 'unknown')
277
+ .slice(0, 5)
278
+ .join(', ');
279
+
280
+ throw new Error(
281
+ `Unable to deterministically resolve '${requestedId}'. Candidates: ${candidates}. Use an exact metadata.id.`
282
+ );
283
+ }
284
+
223
285
  /**
224
286
  * Preview repository deployment
225
287
  */
@@ -309,6 +371,7 @@ export class DeployCommand extends BaseCommand {
309
371
  const { createIntegrationManager } = await import('../../integrations/index.js');
310
372
  const integrationManager = createIntegrationManager(projectPath);
311
373
  await integrationManager.discoverIntegrations({ verbose: options.verbose });
374
+ await integrationManager.scanAll({ verbose: options.verbose });
312
375
 
313
376
  const activeIntegrations = integrationManager.getActiveIntegrations();
314
377
 
@@ -75,7 +75,7 @@ export class RepoStatsCommand extends BaseCommand {
75
75
  if (Object.keys(stats.byCategory).length > 0) {
76
76
  console.log(`\n📂 By Category:`);
77
77
  Object.entries(stats.byCategory)
78
- .sort(([, a], [, b]) => b - a)
78
+ .toSorted(([, a], [, b]) => b - a)
79
79
  .forEach(([category, count]) => {
80
80
  console.log(`- ${category}: ${count}`);
81
81
  });
@@ -85,7 +85,7 @@ export class RepoStatsCommand extends BaseCommand {
85
85
  if (Object.keys(stats.byComplexity).length > 0) {
86
86
  console.log(`\n⚙️ By Complexity:`);
87
87
  Object.entries(stats.byComplexity)
88
- .sort(([, a], [, b]) => b - a)
88
+ .toSorted(([, a], [, b]) => b - a)
89
89
  .forEach(([complexity, count]) => {
90
90
  console.log(`- ${complexity}: ${count}`);
91
91
  });
@@ -95,7 +95,7 @@ export class RepoStatsCommand extends BaseCommand {
95
95
  if (Object.keys(stats.byMaturity).length > 0) {
96
96
  console.log(`\n🎯 By Maturity:`);
97
97
  Object.entries(stats.byMaturity)
98
- .sort(([, a], [, b]) => b - a)
98
+ .toSorted(([, a], [, b]) => b - a)
99
99
  .forEach(([maturity, count]) => {
100
100
  console.log(`- ${maturity}: ${count}`);
101
101
  });
@@ -111,7 +111,7 @@ export class RepoStatsCommand extends BaseCommand {
111
111
  const topCount = verbose ? 20 : 10;
112
112
  console.log(`\n🎮 Platform Support (Top ${topCount}):`);
113
113
  Object.entries(stats.platformSupport)
114
- .sort(([, a], [, b]) => b - a)
114
+ .toSorted(([, a], [, b]) => b - a)
115
115
  .slice(0, topCount)
116
116
  .forEach(([platform, count]) => {
117
117
  console.log(`- ${platform}: ${count}`);
@@ -143,7 +143,7 @@ export class RepoStatsCommand extends BaseCommand {
143
143
  if (stats.authorDistribution) {
144
144
  console.log(`\nTop Contributors:`);
145
145
  Object.entries(stats.authorDistribution)
146
- .sort(([, a], [, b]) => b - a)
146
+ .toSorted(([, a], [, b]) => b - a)
147
147
  .slice(0, 10)
148
148
  .forEach(([author, count]) => {
149
149
  console.log(`- ${author}: ${count} blueprints`);
@@ -153,7 +153,7 @@ export class RepoStatsCommand extends BaseCommand {
153
153
  if (stats.tagsPopularity) {
154
154
  console.log(`\nPopular Tags:`);
155
155
  Object.entries(stats.tagsPopularity)
156
- .sort(([, a], [, b]) => b - a)
156
+ .toSorted(([, a], [, b]) => b - a)
157
157
  .slice(0, 15)
158
158
  .forEach(([tag, count]) => {
159
159
  console.log(`- ${tag}: ${count}`);
@@ -18,7 +18,11 @@ export class SyncCommand extends BaseCommand {
18
18
  */
19
19
  configureOptions(command) {
20
20
  return command
21
- .option('-o, --outputPath <path>', 'Path to the blueprints directory', './.vdk/rules')
21
+ .option(
22
+ '-o, --outputPath <path>',
23
+ 'Path to the blueprints artifact root directory',
24
+ './.vdk/blueprints'
25
+ )
22
26
  .option('--force', 'Force full sync instead of incremental', false)
23
27
  .option('--category <category>', 'Sync specific category only')
24
28
  .option('--hub-only', 'Sync only from Hub, not repository', false)
@@ -32,7 +36,7 @@ export class SyncCommand extends BaseCommand {
32
36
  await commandContext.initialize();
33
37
  this.showHeader();
34
38
 
35
- const rulesDir = await commandContext.ensureRulesDirectory(options.outputPath);
39
+ const artifactsRoot = await commandContext.ensureRulesDirectory(options.outputPath);
36
40
  const syncOps = new SyncOperations(this);
37
41
 
38
42
  let totalSynced = 0;
@@ -41,7 +45,7 @@ export class SyncCommand extends BaseCommand {
41
45
 
42
46
  // Sync from Hub if available and not disabled
43
47
  if (this.hubOps && !options.repoOnly) {
44
- const hubResult = await syncOps.syncFromHub(rulesDir, {
48
+ const hubResult = await syncOps.syncFromHub(artifactsRoot, {
45
49
  force: options.force,
46
50
  category: options.category,
47
51
  type: 'blueprints',
@@ -52,7 +56,7 @@ export class SyncCommand extends BaseCommand {
52
56
 
53
57
  // Sync from repository if not disabled
54
58
  if (!options.hubOnly) {
55
- const repoResult = await syncOps.syncFromRepository(rulesDir, {
59
+ const repoResult = await syncOps.syncFromRepository(artifactsRoot, {
56
60
  force: options.force,
57
61
  category: options.category,
58
62
  type: 'blueprints',
@@ -18,7 +18,7 @@ export class PublishCommand extends BaseCommand {
18
18
  */
19
19
  configureOptions(command) {
20
20
  return command
21
- .argument('<rule-file>', 'Rule file to publish (.mdc, .md, .json, .xml, .cursorrules)')
21
+ .argument('[rule-file]', 'Rule file to publish (.mdc, .md, .json, .xml)')
22
22
  .option(
23
23
  '--github',
24
24
  'Publish via GitHub PR instead of VDK Hub (no registration required)',
@@ -68,7 +68,7 @@ export class PublishCommand extends BaseCommand {
68
68
 
69
69
  console.log('');
70
70
  console.log(this.colorCyan('📋 Publication Preview:'));
71
- console.log(colors.gray(` ${preview.summary}`));
71
+ console.log(colors.muted(` ${preview.summary}`));
72
72
  console.log('');
73
73
 
74
74
  if (preview.validation.qualityScore) {
@@ -77,17 +77,17 @@ export class PublishCommand extends BaseCommand {
77
77
 
78
78
  if (preview.recommendations.length > 0) {
79
79
  console.log('');
80
- console.log(colors.yellow('💡 Recommendations:'));
80
+ console.log(colors.warning('💡 Recommendations:'));
81
81
  preview.recommendations.forEach(rec => {
82
- console.log(colors.gray(` • ${rec}`));
82
+ console.log(colors.muted(` • ${rec}`));
83
83
  });
84
84
  }
85
85
 
86
86
  if (preview.validation.warnings.length > 0) {
87
87
  console.log('');
88
- console.log(colors.yellow('⚠️ Warnings:'));
88
+ console.log(colors.warning('⚠️ Warnings:'));
89
89
  preview.validation.warnings.forEach(warning => {
90
- console.log(colors.yellow(` • ${warning}`));
90
+ console.log(colors.warning(` • ${warning}`));
91
91
  });
92
92
  }
93
93
 
@@ -131,11 +131,11 @@ export class PublishCommand extends BaseCommand {
131
131
  showHubPublishResult(result) {
132
132
  console.log('');
133
133
  console.log(this.colorCyan('🔗 Share your rule:'));
134
- console.log(colors.gray(` ${result.shareUrl}`));
134
+ console.log(colors.muted(` ${result.shareUrl}`));
135
135
  console.log('');
136
136
  console.log(this.colorCyan('📧 Check your email to activate permanent sharing'));
137
137
  console.log(this.colorCyan('💡 Community can use with:'));
138
- console.log(colors.gray(' vdk sync'));
138
+ console.log(colors.muted(' vdk sync'));
139
139
  }
140
140
 
141
141
  /**
@@ -144,9 +144,9 @@ export class PublishCommand extends BaseCommand {
144
144
  showGitHubPublishResult(result) {
145
145
  console.log('');
146
146
  console.log(this.colorCyan('📝 GitHub PR created:'));
147
- console.log(colors.gray(` ${result.prUrl}`));
147
+ console.log(colors.muted(` ${result.prUrl}`));
148
148
  console.log('');
149
149
  console.log(this.colorCyan('⏳ After community review and merge:'));
150
- console.log(colors.gray(' vdk sync'));
150
+ console.log(colors.muted(' vdk sync'));
151
151
  }
152
152
  }
@@ -298,7 +298,7 @@ export class ConvertCommand extends BaseCommand {
298
298
  const name = path.basename(lower);
299
299
 
300
300
  // Known context files
301
- const knownFiles = ['claude.md', '.cursorrules', 'copilot-instructions.md', '.windsurfrules'];
301
+ const knownFiles = ['claude.md', 'copilot-instructions.md'];
302
302
 
303
303
  if (knownFiles.some(f => name.includes(f))) return true;
304
304
 
@@ -360,7 +360,7 @@ export class ConvertCommand extends BaseCommand {
360
360
  this.logInfo('\nUsage examples:');
361
361
  this.logInfo(' vdk convert --input CLAUDE.md --to cursor');
362
362
  this.logInfo(' vdk convert --input .claude/ --to cursor github-copilot --output ./converted');
363
- this.logInfo(' vdk convert --input .cursorrules --to claude-code --dry-run');
363
+ this.logInfo(' vdk convert --input .cursor/rules/index.mdc --to claude-code --dry-run');
364
364
  this.logInfo(' vdk convert --input ./project --all --show-loss');
365
365
  this.logInfo('\nSupported platforms:');
366
366
 
@@ -56,7 +56,7 @@ export class ImportCommand extends BaseCommand {
56
56
  if (contextFiles.length === 0) {
57
57
  this.logWarning('No AI context files found. Looking for:');
58
58
  this.logInfo(' • .claude/ directory or CLAUDE.md');
59
- this.logInfo(' • .cursor/rules/ or .cursorrules');
59
+ this.logInfo(' • .cursor/rules/');
60
60
  this.logInfo(' • .github/copilot-instructions.md');
61
61
  this.logInfo(' • .windsurf/rules/');
62
62
  return { success: true, filesImported: 0 };
@@ -166,12 +166,10 @@ export class ImportCommand extends BaseCommand {
166
166
  const searchPatterns = [
167
167
  { glob: 'CLAUDE.md', platform: 'claude-code' },
168
168
  { glob: '.claude/**/*.md', platform: 'claude-code' },
169
- { glob: '.cursorrules', platform: 'cursor' },
170
169
  { glob: '.cursor/rules/**/*.mdc', platform: 'cursor' },
171
170
  { glob: '.cursor/rules/**/*.md', platform: 'cursor' },
172
171
  { glob: '.github/copilot-instructions.md', platform: 'github-copilot' },
173
172
  { glob: '.windsurf/rules/**/*.md', platform: 'windsurf' },
174
- { glob: '.windsurfrules', platform: 'windsurf' },
175
173
  ];
176
174
 
177
175
  for (const pattern of searchPatterns) {
@@ -22,8 +22,8 @@ export class InitCommand extends BaseCommand {
22
22
  .option('-p, --projectPath <path>', 'Path to the project to scan', process.cwd())
23
23
  .option(
24
24
  '-o, --outputPath <path>',
25
- 'Path where generated rules should be saved',
26
- './.vdk/rules'
25
+ 'Path where generated rule artifacts should be saved',
26
+ './.vdk/blueprints/rules'
27
27
  )
28
28
  .option('-d, --deep', 'Enable deep scanning for more thorough pattern detection', false)
29
29
  .option('-i, --ignorePattern <patterns...>', 'Glob patterns to ignore', [
@@ -71,7 +71,7 @@ export class InitCommand extends BaseCommand {
71
71
  return {
72
72
  defaults: {
73
73
  projectPath: process.cwd(),
74
- outputPath: './.vdk/rules',
74
+ outputPath: './.vdk/blueprints/rules',
75
75
  template: 'default',
76
76
  useGitignore: true,
77
77
  ideIntegration: true,
@@ -22,7 +22,11 @@ export class ScanCommand extends BaseCommand {
22
22
  configureOptions(command) {
23
23
  return command
24
24
  .option('-p, --projectPath <path>', 'Path to the project to rescan', process.cwd())
25
- .option('-o, --outputPath <path>', 'Path where updated rules should be saved', './.vdk/rules')
25
+ .option(
26
+ '-o, --outputPath <path>',
27
+ 'Path where updated rule artifacts should be saved',
28
+ './.vdk/blueprints/rules'
29
+ )
26
30
  .option('--ide <ide>', 'Target specific IDE for scanning (vscode, jetbrains, cursor, etc.)')
27
31
  .option('-d, --deep', 'Enable deep scanning for more thorough pattern detection', false)
28
32
  .option('-i, --ignorePattern <patterns...>', 'Glob patterns to ignore', [
@@ -53,7 +57,7 @@ export class ScanCommand extends BaseCommand {
53
57
  return {
54
58
  defaults: {
55
59
  projectPath: process.cwd(),
56
- outputPath: './.vdk/rules',
60
+ outputPath: './.vdk/blueprints/rules',
57
61
  useGitignore: true,
58
62
  incremental: false,
59
63
  force: false,
@@ -29,7 +29,11 @@ export class StatusCommand extends BaseCommand {
29
29
  configureOptions(command) {
30
30
  return command
31
31
  .option('-c, --configPath <path>', 'Path to the VDK configuration file', './vdk.config.json')
32
- .option('-o, --outputPath <path>', 'Path to the rules directory', './.vdk/rules')
32
+ .option(
33
+ '-o, --outputPath <path>',
34
+ 'Path to the rule artifacts directory',
35
+ './.vdk/blueprints/rules'
36
+ )
33
37
  .option('--scope <scope>', 'Status check scope (all, local, hub)', 'all')
34
38
  .option('-v, --verbose', 'Show detailed status information', false);
35
39
  }
@@ -43,7 +47,7 @@ export class StatusCommand extends BaseCommand {
43
47
 
44
48
  // Ensure default values are applied if options are undefined
45
49
  const configPath = path.resolve(options.configPath || './vdk.config.json');
46
- const rulesDir = path.resolve(options.outputPath || './.vdk/rules');
50
+ const rulesDir = path.resolve(options.outputPath || './.vdk/blueprints/rules');
47
51
  const scope = options.scope || 'all';
48
52
 
49
53
  // Handle hub-only scope (provides detailed hub status like hub-status command)
@@ -31,7 +31,7 @@ export class ValidateCommand extends BaseCommand {
31
31
  */
32
32
  configureOptions(command) {
33
33
  return command
34
- .option('-p, --path <path>', 'Path to blueprint/rule files', './.vdk/rules')
34
+ .option('-p, --path <path>', 'Path to blueprint artifact files', './.vdk/blueprints/rules')
35
35
  .option('-f, --file <file>', 'Validate specific blueprint file')
36
36
  .option('--platform <platform>', 'Validate against specific platform constraints')
37
37
  .option('-v, --verbose', 'Show detailed validation results', false);