compound-workflow 1.6.12 → 1.6.14

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compound-workflow",
3
- "version": "1.6.12",
3
+ "version": "1.6.14",
4
4
  "description": "Clarify -> plan -> execute -> verify -> capture workflow: commands, skills, and agents for Claude Code",
5
5
  "author": {
6
6
  "name": "Compound Workflow"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compound-workflow",
3
- "version": "1.6.12",
3
+ "version": "1.6.14",
4
4
  "description": "Clarify -> plan -> execute -> verify -> capture workflow for Cursor",
5
5
  "author": {
6
6
  "name": "Compound Workflow"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compound-workflow",
3
- "version": "1.6.12",
3
+ "version": "1.6.14",
4
4
  "description": "Clarify → plan → execute → verify → capture. One Install action for Cursor, Claude, and OpenCode.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -351,15 +351,40 @@ function writePluginManifests(targetRoot, dryRun, isSelfInstall) {
351
351
  const cursorDir = path.join(targetRoot, ".cursor-plugin");
352
352
  const claudeDir = path.join(targetRoot, ".claude-plugin");
353
353
 
354
+ const installPathAbs = realpathSafe(targetRoot);
355
+ const registrationDescriptor = {
356
+ pluginId: "compound-workflow@local",
357
+ scope: "user",
358
+ installPath: installPathAbs,
359
+ };
360
+
354
361
  if (dryRun) {
355
- console.log("[dry-run] Would write .cursor-plugin/plugin.json, .claude-plugin/plugin.json");
362
+ console.log("[dry-run] Would write .cursor-plugin/plugin.json, .claude-plugin/plugin.json, .cursor-plugin/registration.json" + (isSelfInstall ? "" : ", .claude-plugin/marketplace.json"));
356
363
  return;
357
364
  }
358
365
  fs.mkdirSync(cursorDir, { recursive: true });
359
366
  fs.mkdirSync(claudeDir, { recursive: true });
360
367
  fs.writeFileSync(path.join(cursorDir, "plugin.json"), JSON.stringify(cursorOut, null, 2) + "\n", "utf8");
361
368
  fs.writeFileSync(path.join(claudeDir, "plugin.json"), JSON.stringify(claudeOut, null, 2) + "\n", "utf8");
362
- console.log("Wrote: .cursor-plugin/plugin.json, .claude-plugin/plugin.json");
369
+ fs.writeFileSync(path.join(cursorDir, "registration.json"), JSON.stringify(registrationDescriptor, null, 2) + "\n", "utf8");
370
+
371
+ // Claude Code 2.1.x+ no longer loads from installed_plugins.json; it requires marketplace flow.
372
+ // Write a project-level marketplace so user can: /plugin marketplace add . then /plugin install compound-workflow@compound-workflow-local
373
+ if (!isSelfInstall) {
374
+ const marketplaceManifest = {
375
+ name: "compound-workflow-local",
376
+ owner: { name: "Compound Workflow" },
377
+ plugins: [
378
+ {
379
+ name: "compound-workflow",
380
+ source: "./node_modules/compound-workflow",
381
+ description: claudeOut.description || "Clarify → plan → execute → verify → capture workflow.",
382
+ },
383
+ ],
384
+ };
385
+ fs.writeFileSync(path.join(claudeDir, "marketplace.json"), JSON.stringify(marketplaceManifest, null, 2) + "\n", "utf8");
386
+ }
387
+ console.log("Wrote: .cursor-plugin/plugin.json, .claude-plugin/plugin.json, .cursor-plugin/registration.json" + (isSelfInstall ? "" : ", .claude-plugin/marketplace.json"));
363
388
  }
364
389
 
365
390
  /**
@@ -446,17 +471,57 @@ function cursorDetected() {
446
471
  }
447
472
 
448
473
  function applyCursorRegistration(targetRoot, dryRun, noRegisterCursor, forceRegister, isSelfInstall) {
474
+ const claudePluginsDir = path.join(os.homedir(), ".claude", "plugins");
475
+ const installedPath = path.join(claudePluginsDir, "installed_plugins.json");
449
476
  const settingsPath = path.join(os.homedir(), ".claude", "settings.json");
450
477
 
451
- const LEGACY_PLUGIN_ID = "compound-workflow@local";
452
- const pluginId = "compound-workflow@compound-workflow";
478
+ const pluginVersion = (() => {
479
+ try {
480
+ const pkgPath = path.join(PACKAGE_ROOT, "package.json");
481
+ return JSON.parse(fs.readFileSync(pkgPath, "utf8")).version || "0.0.0";
482
+ } catch {
483
+ return "0.0.0";
484
+ }
485
+ })();
453
486
 
454
- // Marketplace source path:
455
- // - Self-install (dev): absolute path to package root
456
- // - Consumer projects: relative path from project root to package
457
- const marketplacePath = isSelfInstall
458
- ? realpathSafe(PACKAGE_ROOT)
459
- : "./node_modules/compound-workflow";
487
+ const targetRootReal = realpathSafe(isSelfInstall ? PACKAGE_ROOT : targetRoot);
488
+ const pluginId = "compound-workflow@local";
489
+ const scope = isSelfInstall ? "user" : "project";
490
+
491
+ let installed = {};
492
+ if (fs.existsSync(installedPath)) {
493
+ try {
494
+ installed = readJsonMaybe(installedPath) ?? {};
495
+ } catch {
496
+ installed = {};
497
+ }
498
+ }
499
+ const plugins = ensureObject(installed.plugins);
500
+ const existingEntries = Array.isArray(plugins[pluginId]) ? plugins[pluginId] : [];
501
+ const cleanedEntries = scope === "project"
502
+ ? existingEntries.filter((e) => e.scope !== "user")
503
+ : existingEntries;
504
+ const pruned = cleanedEntries.filter((e) => {
505
+ const manifest = path.join(e.installPath || "", ".claude-plugin", "plugin.json");
506
+ return fs.existsSync(manifest);
507
+ });
508
+ const matchIndex = pruned.findIndex((e) =>
509
+ scope === "user" ? e.scope === "user" : e.scope === "project" && e.projectPath === targetRootReal
510
+ );
511
+ const existingEntry = matchIndex >= 0 ? pruned[matchIndex] : {};
512
+ const now = new Date().toISOString();
513
+ const newEntry = {
514
+ scope,
515
+ ...(scope === "project" ? { projectPath: targetRootReal } : {}),
516
+ installPath: targetRootReal,
517
+ version: pluginVersion,
518
+ installedAt: existingEntry.installedAt || now,
519
+ lastUpdated: now,
520
+ };
521
+ plugins[pluginId] = matchIndex >= 0
522
+ ? pruned.map((e, i) => (i === matchIndex ? newEntry : e))
523
+ : [...pruned, newEntry];
524
+ installed.plugins = plugins;
460
525
 
461
526
  let settings = {};
462
527
  if (fs.existsSync(settingsPath)) {
@@ -466,53 +531,39 @@ function applyCursorRegistration(targetRoot, dryRun, noRegisterCursor, forceRegi
466
531
  settings = {};
467
532
  }
468
533
  }
469
- // Clean up legacy @local entry and register with correct plugin ID
470
534
  settings.enabledPlugins = ensureObject(settings.enabledPlugins);
471
- delete settings.enabledPlugins[LEGACY_PLUGIN_ID];
472
535
  settings.enabledPlugins[pluginId] = true;
473
536
 
474
537
  if (dryRun) {
475
- console.log("[dry-run] Would register Claude plugin via extraKnownMarketplaces with id:", pluginId);
538
+ console.log("[dry-run] Would register Claude plugin:", JSON.stringify(newEntry, null, 2));
476
539
  return;
477
540
  }
478
541
 
542
+ fs.mkdirSync(claudePluginsDir, { recursive: true });
479
543
  fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
544
+ fs.writeFileSync(installedPath, JSON.stringify(installed, null, 2) + "\n", "utf8");
480
545
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
481
546
 
482
- // Project-level settings: register local marketplace and enable plugin
483
547
  if (!isSelfInstall) {
484
548
  const projectSettingsPath = path.join(targetRoot, ".claude", "settings.json");
485
549
  let projectSettings = {};
486
550
  if (fs.existsSync(projectSettingsPath)) {
487
551
  try { projectSettings = readJsonMaybe(projectSettingsPath) ?? {}; } catch { projectSettings = {}; }
488
552
  }
489
- // Clean up legacy @local entry
490
553
  projectSettings.enabledPlugins = ensureObject(projectSettings.enabledPlugins);
491
- delete projectSettings.enabledPlugins[LEGACY_PLUGIN_ID];
492
554
  projectSettings.enabledPlugins[pluginId] = true;
493
- // Register the package as a local marketplace so Claude Code resolves compound-workflow@compound-workflow
494
- projectSettings.extraKnownMarketplaces = ensureObject(projectSettings.extraKnownMarketplaces);
495
- projectSettings.extraKnownMarketplaces["compound-workflow"] = {
496
- source: {
497
- source: "local",
498
- path: marketplacePath,
499
- },
500
- };
555
+ if (projectSettings.extraKnownMarketplaces?.["compound-workflow"]) {
556
+ delete projectSettings.extraKnownMarketplaces["compound-workflow"];
557
+ }
501
558
  fs.mkdirSync(path.join(targetRoot, ".claude"), { recursive: true });
502
559
  fs.writeFileSync(projectSettingsPath, JSON.stringify(projectSettings, null, 2) + "\n", "utf8");
503
- } else {
504
- // Self-install: register marketplace at user level with absolute path
505
- settings.extraKnownMarketplaces = ensureObject(settings.extraKnownMarketplaces);
506
- settings.extraKnownMarketplaces["compound-workflow"] = {
507
- source: {
508
- source: "local",
509
- path: marketplacePath,
510
- },
511
- };
512
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
513
560
  }
514
561
 
515
- console.log("Registered compound-workflow with Claude Code. Restart Claude Code; enable 'Include third-party Plugins, Skills, and other configs' in Settings if needed.");
562
+ console.log("Registered compound-workflow with Claude Code.");
563
+ if (!isSelfInstall) {
564
+ console.log(" Claude Code 2.1+: run in this project: /plugin marketplace add . then /plugin install compound-workflow@compound-workflow-local");
565
+ }
566
+ console.log(" Restart Claude Code; enable 'Include third-party Plugins, Skills, and other configs' in Settings if needed.");
516
567
 
517
568
  if (noRegisterCursor && !forceRegister) return;
518
569
  const shouldApply = forceRegister || (cursorDetected() && !noRegisterCursor);
@@ -520,9 +571,8 @@ function applyCursorRegistration(targetRoot, dryRun, noRegisterCursor, forceRegi
520
571
  console.log("[cursor] Cursor not detected; skipped Cursor plugin registration. Use --register-cursor to force.");
521
572
  return;
522
573
  }
523
-
524
- const cursorPluginPath = path.join(targetRoot, ".cursor-plugin", "plugin.json");
525
- if (!fs.existsSync(cursorPluginPath)) return;
574
+ const registrationPath = path.join(targetRoot, ".cursor-plugin", "registration.json");
575
+ if (!fs.existsSync(registrationPath)) return;
526
576
  console.log("Registered compound-workflow with Cursor. Restart Cursor; enable 'Include third-party Plugins, Skills, and other configs' in Settings if needed.");
527
577
  }
528
578