devtronic 1.2.4 → 1.2.6

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 (51) hide show
  1. package/README.md +9 -9
  2. package/dist/{chunk-V4QEAL7Y.js → chunk-WM7R52TC.js} +30 -27
  3. package/dist/index.js +112 -61
  4. package/dist/{plugin-SGSFVXPA.js → plugin-KQQASBQX.js} +1 -1
  5. package/package.json +1 -1
  6. package/templates/addons/auto-devtronic/agents/afk-task-validator.md +78 -0
  7. package/templates/addons/auto-devtronic/agents/{quality-runner.md → quality-executor.md} +1 -1
  8. package/templates/addons/auto-devtronic/manifest.json +2 -1
  9. package/templates/addons/auto-devtronic/skills/auto-devtronic/SKILL.md +14 -14
  10. package/templates/addons/design-best-practices/manifest.json +2 -2
  11. package/templates/addons/design-best-practices/skills/{design-review → design-critique}/SKILL.md +2 -1
  12. package/templates/addons/design-best-practices/skills/design-harden/SKILL.md +1 -0
  13. package/templates/addons/design-best-practices/skills/design-init/SKILL.md +1 -0
  14. package/templates/addons/design-best-practices/skills/design-refine/SKILL.md +2 -0
  15. package/templates/addons/design-best-practices/skills/{design-system → design-tokens}/SKILL.md +3 -1
  16. package/templates/claude-code/.claude/rules/quality.md +4 -0
  17. package/templates/claude-code/.claude/skills/audit/SKILL.md +1 -1
  18. package/templates/claude-code/.claude/skills/backlog/SKILL.md +1 -1
  19. package/templates/claude-code/.claude/skills/brief/SKILL.md +1 -1
  20. package/templates/claude-code/.claude/skills/briefing/SKILL.md +1 -1
  21. package/templates/claude-code/.claude/skills/checkpoint/SKILL.md +1 -1
  22. package/templates/claude-code/.claude/skills/create-plan/SKILL.md +1 -1
  23. package/templates/claude-code/.claude/skills/create-skill/SKILL.md +1 -1
  24. package/templates/claude-code/.claude/skills/design/SKILL.md +1 -1
  25. package/templates/claude-code/.claude/skills/design-audit/SKILL.md +1 -1
  26. package/templates/claude-code/.claude/skills/design-define/SKILL.md +1 -1
  27. package/templates/claude-code/.claude/skills/design-ia/SKILL.md +1 -1
  28. package/templates/claude-code/.claude/skills/design-research/SKILL.md +1 -1
  29. package/templates/claude-code/.claude/skills/design-review/SKILL.md +1 -1
  30. package/templates/claude-code/.claude/skills/design-spec/SKILL.md +1 -1
  31. package/templates/claude-code/.claude/skills/design-system/SKILL.md +1 -1
  32. package/templates/claude-code/.claude/skills/design-system-audit/SKILL.md +1 -1
  33. package/templates/claude-code/.claude/skills/design-system-define/SKILL.md +1 -1
  34. package/templates/claude-code/.claude/skills/design-system-sync/SKILL.md +1 -1
  35. package/templates/claude-code/.claude/skills/design-wireframe/SKILL.md +1 -1
  36. package/templates/claude-code/.claude/skills/devtronic-help/SKILL.md +338 -0
  37. package/templates/claude-code/.claude/skills/execute-plan/SKILL.md +1 -1
  38. package/templates/claude-code/.claude/skills/generate-tests/SKILL.md +1 -1
  39. package/templates/claude-code/.claude/skills/handoff/SKILL.md +1 -1
  40. package/templates/claude-code/.claude/skills/investigate/SKILL.md +1 -1
  41. package/templates/claude-code/.claude/skills/learn/SKILL.md +1 -1
  42. package/templates/claude-code/.claude/skills/opensrc/SKILL.md +1 -1
  43. package/templates/claude-code/.claude/skills/post-review/SKILL.md +2 -2
  44. package/templates/claude-code/.claude/skills/quick/SKILL.md +1 -1
  45. package/templates/claude-code/.claude/skills/recap/SKILL.md +1 -1
  46. package/templates/claude-code/.claude/skills/research/SKILL.md +1 -1
  47. package/templates/claude-code/.claude/skills/scaffold/SKILL.md +1 -1
  48. package/templates/claude-code/.claude/skills/setup/SKILL.md +1 -1
  49. package/templates/claude-code/.claude/skills/spec/SKILL.md +1 -1
  50. package/templates/claude-code/.claude/skills/summary/SKILL.md +1 -1
  51. package/templates/claude-code/.claude/skills/worktree/SKILL.md +1 -1
package/README.md CHANGED
@@ -20,8 +20,8 @@ The CLI analyzes your project (framework, architecture, stack) and generates per
20
20
  | `doctor [--fix]` | Run health diagnostics |
21
21
  | `list [skills\|agents]` | List installed skills and agents |
22
22
  | `config` | View or manage project configuration |
23
- | `addon enable <name>` | Add an addon skill pack |
24
- | `addon disable <name>` | Remove an addon skill pack |
23
+ | `addon add <name>` | Add an addon skill pack |
24
+ | `addon remove <name>` | Remove an addon skill pack |
25
25
  | `addon list` | List available and installed addons |
26
26
  | `addon sync` | Regenerate addon files for current agents |
27
27
  | `add <ide>` | Add another IDE |
@@ -35,8 +35,8 @@ The CLI analyzes your project (framework, architecture, stack) and generates per
35
35
 
36
36
  - **AGENTS.md** — Universal AI context personalized to your stack
37
37
  - **Architecture rules** — IDE-specific format (`.claude/rules/`, `.cursor/rules/`, etc.)
38
- - **Skills** (19 core + 12 design + 9 addon) — Reusable workflows (`/devtronic:brief`, `/devtronic:spec`, `/devtronic:create-plan`, `/devtronic:summary`, `/devtronic:audit`, etc.)
39
- - **Agents** (15) — Specialized subagents (code-reviewer, quality-runner, etc.)
38
+ - **Skills** (20 core + 12 design + 9 addon) — Reusable workflows (`/brief`, `/spec`, `/create-plan`, `/summary`, `/audit`, `/devtronic-help`, etc.)
39
+ - **Agents** (15 + 3 addon) — Specialized subagents (code-reviewer, quality-runner, etc.)
40
40
  - **Hooks** (5) — Automated workflow (lint-on-save, checkpoint, etc.)
41
41
  - **thoughts/** — Structured directory for AI working documents
42
42
 
@@ -45,11 +45,11 @@ The CLI analyzes your project (framework, architecture, stack) and generates per
45
45
  Three optional addon packs extend the core toolkit. Select them during `init` or manage them at any time:
46
46
 
47
47
  ```bash
48
- npx devtronic addon list # See available addons and status
49
- npx devtronic addon enable orchestration # Install
50
- npx devtronic addon enable design-best-practices
51
- npx devtronic addon enable auto-devtronic
52
- npx devtronic addon disable <name> # Uninstall
48
+ npx devtronic addon list # See available addons and status
49
+ npx devtronic addon add orchestration # Install
50
+ npx devtronic addon add design-best-practices
51
+ npx devtronic addon add auto-devtronic
52
+ npx devtronic addon remove <name> # Uninstall
53
53
  ```
54
54
 
55
55
  | Addon | Skills | Description |
@@ -14,7 +14,7 @@ var ADDONS = {
14
14
  name: "design-best-practices",
15
15
  label: "Design Best Practices",
16
16
  description: "Frontend design quality skills: typography, color, layout, accessibility, motion, and UX writing.",
17
- skills: ["design-init", "design-review", "design-refine", "design-system", "design-harden"],
17
+ skills: ["design-init", "design-critique", "design-refine", "design-tokens", "design-harden"],
18
18
  agents: []
19
19
  },
20
20
  "auto-devtronic": {
@@ -22,7 +22,7 @@ var ADDONS = {
22
22
  label: "auto-devtronic \u2014 Autonomous Engineering Loop",
23
23
  description: "Runs the full spec\u2192test\u2192plan\u2192execute\u2192PR pipeline autonomously. Self-corrects via failing tests. HITL and AFK modes.",
24
24
  skills: ["auto-devtronic"],
25
- agents: ["issue-parser", "failure-analyst", "quality-runner"]
25
+ agents: ["issue-parser", "failure-analyst", "quality-executor"]
26
26
  }
27
27
  };
28
28
  var PRESETS = {
@@ -79,7 +79,7 @@ var PRESETS = {
79
79
 
80
80
  // src/utils/files.ts
81
81
  import { createHash } from "crypto";
82
- import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, readdirSync } from "fs";
82
+ import { existsSync, lstatSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, cpSync, readdirSync } from "fs";
83
83
  import { dirname, join, relative } from "path";
84
84
  var MANIFEST_DIR = ".ai-template";
85
85
  var MANIFEST_FILE = "manifest.json";
@@ -91,13 +91,15 @@ function readFile(path) {
91
91
  }
92
92
  function writeFile(path, content) {
93
93
  const dir = dirname(path);
94
- if (!existsSync(dir)) {
95
- mkdirSync(dir, { recursive: true });
96
- }
94
+ ensureDir(dir);
97
95
  writeFileSync(path, content, "utf-8");
98
96
  }
99
97
  function ensureDir(path) {
100
98
  if (!existsSync(path)) {
99
+ try {
100
+ if (lstatSync(path).isSymbolicLink()) unlinkSync(path);
101
+ } catch {
102
+ }
101
103
  mkdirSync(path, { recursive: true });
102
104
  }
103
105
  }
@@ -564,25 +566,26 @@ ${skillsSection}
564
566
  `;
565
567
  }
566
568
  var CORE_SKILLS = [
567
- { name: "devtronic:brief", desc: "Session orientation with pre-flight checks" },
568
- { name: "devtronic:spec", desc: "Product specification interview (PRD)" },
569
- { name: "devtronic:research", desc: "Codebase investigation (--deep, --external)" },
570
- { name: "devtronic:create-plan", desc: "Phased implementation plan with task dependencies" },
571
- { name: "devtronic:execute-plan", desc: "Parallel phase execution of plans" },
572
- { name: "devtronic:quick", desc: "Fast ad-hoc tasks: implement, verify, commit" },
573
- { name: "devtronic:generate-tests", desc: "Failing tests from spec (Tests-as-DoD)" },
574
- { name: "devtronic:post-review", desc: "Pre-PR review (architecture, quality, requirements)" },
575
- { name: "devtronic:audit", desc: "Codebase audit (security, complexity, architecture)" },
576
- { name: "devtronic:summary", desc: "Post-change documentation" },
577
- { name: "devtronic:checkpoint", desc: "Save session progress for resumption" },
578
- { name: "devtronic:backlog", desc: "Issue management with BACK-### IDs" },
579
- { name: "devtronic:investigate", desc: "Deep error and bug analysis" },
580
- { name: "devtronic:learn", desc: "Post-task teaching breakdown" },
581
- { name: "devtronic:scaffold", desc: "Create new projects from scratch" },
582
- { name: "devtronic:setup", desc: "Interactive project configuration" },
583
- { name: "devtronic:worktree", desc: "Git worktree management" },
584
- { name: "devtronic:opensrc", desc: "Fetch npm/GitHub source for full context" },
585
- { name: "devtronic:create-skill", desc: "Generate new custom skills" }
569
+ { name: "brief", desc: "Session orientation with pre-flight checks" },
570
+ { name: "spec", desc: "Product specification interview (PRD)" },
571
+ { name: "research", desc: "Codebase investigation (--deep, --external)" },
572
+ { name: "create-plan", desc: "Phased implementation plan with task dependencies" },
573
+ { name: "execute-plan", desc: "Parallel phase execution of plans" },
574
+ { name: "quick", desc: "Fast ad-hoc tasks: implement, verify, commit" },
575
+ { name: "generate-tests", desc: "Failing tests from spec (Tests-as-DoD)" },
576
+ { name: "post-review", desc: "Pre-PR review (architecture, quality, requirements)" },
577
+ { name: "audit", desc: "Codebase audit (security, complexity, architecture)" },
578
+ { name: "summary", desc: "Post-change documentation" },
579
+ { name: "checkpoint", desc: "Save session progress for resumption" },
580
+ { name: "backlog", desc: "Issue management with BACK-### IDs" },
581
+ { name: "investigate", desc: "Deep error and bug analysis" },
582
+ { name: "learn", desc: "Post-task teaching breakdown" },
583
+ { name: "scaffold", desc: "Create new projects from scratch" },
584
+ { name: "setup", desc: "Interactive project configuration" },
585
+ { name: "worktree", desc: "Git worktree management" },
586
+ { name: "opensrc", desc: "Fetch npm/GitHub source for full context" },
587
+ { name: "create-skill", desc: "Generate new custom skills" },
588
+ { name: "devtronic-help", desc: "Discover skills, agents, addons, and workflows from the IDE" }
586
589
  ];
587
590
  var ADDON_SKILLS = {
588
591
  orchestration: [
@@ -592,9 +595,9 @@ var ADDON_SKILLS = {
592
595
  ],
593
596
  "design-best-practices": [
594
597
  { name: "design-init", desc: "One-time project design context setup" },
595
- { name: "design-review", desc: "Design critique with AI slop detection" },
598
+ { name: "design-critique", desc: "Design critique with AI slop detection" },
596
599
  { name: "design-refine", desc: "Directional design refinement" },
597
- { name: "design-system", desc: "Design system extraction and normalization" },
600
+ { name: "design-tokens", desc: "Design system extraction and normalization" },
598
601
  { name: "design-harden", desc: "Production hardening for edge cases" }
599
602
  ],
600
603
  "auto-devtronic": [
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  readManifest,
25
25
  writeFile,
26
26
  writeManifest
27
- } from "./chunk-V4QEAL7Y.js";
27
+ } from "./chunk-WM7R52TC.js";
28
28
 
29
29
  // src/index.ts
30
30
  import { Command } from "commander";
@@ -1127,8 +1127,22 @@ function writeClaudeSettings(targetDir, settings) {
1127
1127
  ensureDir(join6(targetDir, ".claude"));
1128
1128
  writeFile(settingsPath, JSON.stringify(settings, null, 2));
1129
1129
  }
1130
+ var LEGACY_PLUGIN_NAMES = ["dev-ai", "ai-agentic"];
1131
+ var LEGACY_MARKETPLACE_NAMES = ["dev-ai-local", "ai-agentic-local"];
1130
1132
  function registerPlugin(targetDir, pluginName, marketplaceName, marketplacePath) {
1131
1133
  const settings = readClaudeSettings(targetDir);
1134
+ if (settings.extraKnownMarketplaces) {
1135
+ for (const legacy of LEGACY_MARKETPLACE_NAMES) {
1136
+ delete settings.extraKnownMarketplaces[legacy];
1137
+ }
1138
+ }
1139
+ if (settings.enabledPlugins) {
1140
+ for (const key of Object.keys(settings.enabledPlugins)) {
1141
+ if (LEGACY_PLUGIN_NAMES.some((lp) => key.startsWith(`${lp}@`))) {
1142
+ delete settings.enabledPlugins[key];
1143
+ }
1144
+ }
1145
+ }
1132
1146
  if (!settings.extraKnownMarketplaces) {
1133
1147
  settings.extraKnownMarketplaces = {};
1134
1148
  }
@@ -1469,7 +1483,7 @@ Valid addons: ${validAddons.join(", ")}`);
1469
1483
  p3.log.warn(`Template not found: ${templateName}`);
1470
1484
  continue;
1471
1485
  }
1472
- const resolution = conflictResolutions.get(ide) || "overwrite";
1486
+ const resolution = conflictResolutions.get(ide) || "replace";
1473
1487
  const files = getAllFilesRecursive(templateDir);
1474
1488
  const dynamicFiles = DYNAMIC_RULE_FILES[ide] || [];
1475
1489
  for (const file of files) {
@@ -1507,7 +1521,7 @@ Valid addons: ${validAddons.join(", ")}`);
1507
1521
  const rulePath = dynamicFiles[0];
1508
1522
  if (rulePath) {
1509
1523
  const destPath = join7(targetDir, rulePath);
1510
- const resolution2 = conflictResolutions.get(ide) || "overwrite";
1524
+ const resolution2 = conflictResolutions.get(ide) || "replace";
1511
1525
  if (fileExists(destPath) && resolution2 === "keep") {
1512
1526
  skippedFiles.push(rulePath);
1513
1527
  } else if (fileExists(destPath) && resolution2 === "merge") {
@@ -1588,7 +1602,7 @@ Valid addons: ${validAddons.join(", ")}`);
1588
1602
  p3.note(
1589
1603
  [
1590
1604
  ` Name: ${chalk4.cyan(PLUGIN_NAME)} at ${PLUGIN_DIR}/${PLUGIN_NAME}/`,
1591
- ` Skills: /devtronic:brief, /devtronic:spec, /devtronic:research, ...`,
1605
+ ` Skills: /brief, /spec, /research, ... (auto-namespaced in plugin mode)`,
1592
1606
  ` Hooks: SessionStart, PostToolUse, Stop, SubagentStop, PreCompact`
1593
1607
  ].join("\n"),
1594
1608
  "Plugin Installed"
@@ -1615,6 +1629,13 @@ Valid addons: ${validAddons.join(", ")}`);
1615
1629
  ].join("\n"),
1616
1630
  "Autonomous Mode"
1617
1631
  );
1632
+ p3.note(
1633
+ [
1634
+ `${chalk4.dim("In Claude Code:")} ${chalk4.cyan("/devtronic-help")} ${chalk4.dim("\u2014 discover skills, agents, and workflows")}`,
1635
+ `${chalk4.dim("From terminal:")} ${chalk4.cyan("npx devtronic list")} ${chalk4.dim("\u2014 list installed skills and agents")}`
1636
+ ].join("\n"),
1637
+ "Need Help?"
1638
+ );
1618
1639
  p3.outro(chalk4.green("Setup complete!"));
1619
1640
  } catch (err) {
1620
1641
  spinner8.stop("Configuration failed");
@@ -1718,7 +1739,7 @@ function buildProjectConfigFromPreset(presetConfig, analysis) {
1718
1739
 
1719
1740
  // src/commands/update.ts
1720
1741
  import { resolve as resolve4, join as join11, dirname as dirname6 } from "path";
1721
- import { existsSync as existsSync9, unlinkSync as unlinkSync2, lstatSync, readdirSync as readdirSync2, rmdirSync as rmdirSync2, chmodSync as chmodSync2 } from "fs";
1742
+ import { existsSync as existsSync9, unlinkSync as unlinkSync2, lstatSync as lstatSync2, readdirSync as readdirSync2, rmdirSync as rmdirSync2, chmodSync as chmodSync2 } from "fs";
1722
1743
  import * as p4 from "@clack/prompts";
1723
1744
  import chalk5 from "chalk";
1724
1745
 
@@ -1795,14 +1816,18 @@ function readAddonConfig(targetDir) {
1795
1816
  if (!existsSync7(configPath)) {
1796
1817
  return { agents: ["claude"], installed: {} };
1797
1818
  }
1798
- const raw = JSON.parse(readFileSync3(configPath, "utf-8"));
1799
- const data = raw.addons ?? raw;
1800
- return {
1801
- version: 1,
1802
- mode: data.mode,
1803
- agents: data.agents ?? ["claude"],
1804
- installed: data.installed ?? {}
1805
- };
1819
+ try {
1820
+ const raw = JSON.parse(readFileSync3(configPath, "utf-8"));
1821
+ const data = raw.addons ?? raw;
1822
+ return {
1823
+ version: 1,
1824
+ mode: data.mode,
1825
+ agents: data.agents ?? ["claude"],
1826
+ installed: data.installed ?? {}
1827
+ };
1828
+ } catch {
1829
+ return { agents: ["claude"], installed: {} };
1830
+ }
1806
1831
  }
1807
1832
  function writeAddonConfig(targetDir, config) {
1808
1833
  const configPath = getConfigPath(targetDir);
@@ -1857,6 +1882,7 @@ function registerAddonInConfig(targetDir, addonName) {
1857
1882
  // src/generators/addonFiles.ts
1858
1883
  import {
1859
1884
  existsSync as existsSync8,
1885
+ lstatSync,
1860
1886
  readFileSync as readFileSync4,
1861
1887
  writeFileSync as writeFileSync2,
1862
1888
  mkdirSync as mkdirSync2,
@@ -1866,7 +1892,6 @@ import {
1866
1892
  rmdirSync
1867
1893
  } from "fs";
1868
1894
  import { join as join10, dirname as dirname5 } from "path";
1869
- import { createHash } from "crypto";
1870
1895
  var AGENT_PATHS = {
1871
1896
  claude: ".claude",
1872
1897
  cursor: ".cursor",
@@ -1918,11 +1943,14 @@ var RUNTIME_SPECS = {
1918
1943
  })
1919
1944
  }
1920
1945
  };
1921
- function checksum(content) {
1922
- return createHash("sha256").update(content).digest("hex").slice(0, 16);
1923
- }
1924
1946
  function ensureDir2(dir) {
1925
- if (!existsSync8(dir)) mkdirSync2(dir, { recursive: true });
1947
+ if (!existsSync8(dir)) {
1948
+ try {
1949
+ if (lstatSync(dir).isSymbolicLink()) unlinkSync(dir);
1950
+ } catch {
1951
+ }
1952
+ mkdirSync2(dir, { recursive: true });
1953
+ }
1926
1954
  }
1927
1955
  function readManifest2(addonSourceDir) {
1928
1956
  const manifestPath = join10(addonSourceDir, "manifest.json");
@@ -1976,7 +2004,7 @@ function generateAddonFiles(projectDir, addonSourceDir, agents) {
1976
2004
  ensureDir2(dirname5(destPath));
1977
2005
  writeFileSync2(destPath, content);
1978
2006
  result.written++;
1979
- result.checksums[relPath] = checksum(content);
2007
+ result.checksums[relPath] = calculateChecksum(content);
1980
2008
  }
1981
2009
  continue;
1982
2010
  }
@@ -1990,15 +2018,15 @@ function generateAddonFiles(projectDir, addonSourceDir, agents) {
1990
2018
  const existing = readFileSync4(destPath, "utf-8");
1991
2019
  if (existing === content) {
1992
2020
  result.skipped++;
1993
- continue;
2021
+ } else {
2022
+ result.conflicts.push(relPath);
1994
2023
  }
1995
- result.skipped++;
1996
2024
  continue;
1997
2025
  }
1998
2026
  ensureDir2(dirname5(destPath));
1999
2027
  writeFileSync2(destPath, content);
2000
2028
  result.written++;
2001
- result.checksums[relPath] = checksum(content);
2029
+ result.checksums[relPath] = calculateChecksum(content);
2002
2030
  }
2003
2031
  for (const agentName of manifest.files.agents ?? []) {
2004
2032
  const agentFile = join10(addonSourceDir, "agents", `${agentName}.md`);
@@ -2009,7 +2037,7 @@ function generateAddonFiles(projectDir, addonSourceDir, agents) {
2009
2037
  ensureDir2(dirname5(destPath));
2010
2038
  writeFileSync2(destPath, content);
2011
2039
  result.written++;
2012
- result.checksums[`agents/${agentName}.md`] = checksum(content);
2040
+ result.checksums[`agents/${agentName}.md`] = calculateChecksum(content);
2013
2041
  } else {
2014
2042
  result.skipped++;
2015
2043
  }
@@ -2024,7 +2052,7 @@ function generateAddonFiles(projectDir, addonSourceDir, agents) {
2024
2052
  ensureDir2(dirname5(destPath));
2025
2053
  writeFileSync2(destPath, content);
2026
2054
  result.written++;
2027
- result.checksums[`rules/${rule}`] = checksum(content);
2055
+ result.checksums[`rules/${rule}`] = calculateChecksum(content);
2028
2056
  } else {
2029
2057
  result.skipped++;
2030
2058
  }
@@ -2040,7 +2068,7 @@ function generateAddonFiles(projectDir, addonSourceDir, agents) {
2040
2068
  ensureDir2(dirname5(destPath));
2041
2069
  writeFileSync2(destPath, content);
2042
2070
  result.written++;
2043
- result.checksums[relPath] = checksum(content);
2071
+ result.checksums[relPath] = calculateChecksum(content);
2044
2072
  } else {
2045
2073
  result.skipped++;
2046
2074
  }
@@ -2120,8 +2148,10 @@ function removeAddonFiles(projectDir, addonName, agents, addonSourceDir) {
2120
2148
  }
2121
2149
  }
2122
2150
  }
2123
- const noticePath = join10(projectDir, "NOTICE.md");
2124
- if (existsSync8(noticePath)) unlinkSync(noticePath);
2151
+ if (manifest.attribution) {
2152
+ const noticePath = join10(projectDir, "NOTICE.md");
2153
+ if (existsSync8(noticePath)) unlinkSync(noticePath);
2154
+ }
2125
2155
  }
2126
2156
  function syncAddonFiles(projectDir, addonSourceDir, agents) {
2127
2157
  const fileMap = buildFileMap(addonSourceDir);
@@ -2150,7 +2180,7 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2150
2180
  continue;
2151
2181
  }
2152
2182
  const existing = readFileSync4(destPath, "utf-8");
2153
- const existingChecksum = checksum(existing);
2183
+ const existingChecksum = calculateChecksum(existing);
2154
2184
  const originalChecksum = installedChecksums[relPath];
2155
2185
  if (existing === newContent) {
2156
2186
  result.skipped++;
@@ -2178,7 +2208,7 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2178
2208
  continue;
2179
2209
  }
2180
2210
  const existing = readFileSync4(destPath, "utf-8");
2181
- const existingChecksum = checksum(existing);
2211
+ const existingChecksum = calculateChecksum(existing);
2182
2212
  const originalChecksum = installedChecksums[relPath];
2183
2213
  if (existing === newContent) {
2184
2214
  result.skipped++;
@@ -2204,7 +2234,7 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2204
2234
  continue;
2205
2235
  }
2206
2236
  const existing = readFileSync4(destPath, "utf-8");
2207
- const existingChecksum = checksum(existing);
2237
+ const existingChecksum = calculateChecksum(existing);
2208
2238
  const originalChecksum = installedChecksums[relPath];
2209
2239
  if (existing === newContent) {
2210
2240
  result.skipped++;
@@ -2231,7 +2261,7 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2231
2261
  continue;
2232
2262
  }
2233
2263
  const existing = readFileSync4(destPath, "utf-8");
2234
- const existingChecksum = checksum(existing);
2264
+ const existingChecksum = calculateChecksum(existing);
2235
2265
  const originalChecksum = installedChecksums[relPath];
2236
2266
  if (existing === newContent) {
2237
2267
  result.skipped++;
@@ -2258,7 +2288,7 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2258
2288
  continue;
2259
2289
  }
2260
2290
  const existing = readFileSync4(destPath, "utf-8");
2261
- const existingChecksum = checksum(existing);
2291
+ const existingChecksum = calculateChecksum(existing);
2262
2292
  const originalChecksum = installedChecksums[relPath];
2263
2293
  if (existing === newContent) {
2264
2294
  result.skipped++;
@@ -2276,20 +2306,24 @@ function syncAddonFiles(projectDir, addonSourceDir, agents) {
2276
2306
  }
2277
2307
  function detectModifiedAddonFiles(projectDir, addonName) {
2278
2308
  let installedChecksums = {};
2309
+ let agents = ["claude"];
2279
2310
  try {
2280
2311
  const config = readAddonConfig(projectDir);
2281
2312
  const installed = config.installed?.[addonName];
2282
2313
  if (!installed?.checksums) return [];
2283
2314
  installedChecksums = installed.checksums;
2315
+ agents = config.agents ?? ["claude"];
2284
2316
  } catch {
2285
2317
  return [];
2286
2318
  }
2287
2319
  const modified = [];
2288
- for (const agentDir of Object.values(AGENT_PATHS)) {
2320
+ for (const agent of agents) {
2321
+ const spec = RUNTIME_SPECS[agent];
2322
+ const baseDir = spec?.baseDir ?? AGENT_PATHS[agent] ?? `.${agent}`;
2289
2323
  for (const [relPath, originalHash] of Object.entries(installedChecksums)) {
2290
- const absPath = join10(projectDir, agentDir, relPath);
2324
+ const absPath = join10(projectDir, baseDir, relPath);
2291
2325
  if (!existsSync8(absPath)) continue;
2292
- const current = checksum(readFileSync4(absPath, "utf-8"));
2326
+ const current = calculateChecksum(readFileSync4(absPath, "utf-8"));
2293
2327
  if (current !== originalHash) {
2294
2328
  modified.push(relPath);
2295
2329
  }
@@ -2335,7 +2369,7 @@ async function updateCommand(options) {
2335
2369
  const shouldMigrate = manifest.selectedIDEs.includes("claude-code") && !manifest.installMode && hasStandaloneSkills(manifest);
2336
2370
  if (shouldMigrate) {
2337
2371
  p4.note(
2338
- "Claude Code skills/agents detected as standalone.\nThe new version uses plugin mode (namespace devtronic:).",
2372
+ "Claude Code skills/agents detected as standalone.\nThe new version uses plugin mode. Skills are auto-namespaced in plugin mode.",
2339
2373
  "Migration Available"
2340
2374
  );
2341
2375
  if (!options.check) {
@@ -2602,7 +2636,7 @@ async function updateCommand(options) {
2602
2636
  }
2603
2637
  const claudeMdPath = join11(targetDir, "CLAUDE.md");
2604
2638
  if (fileExists(claudeMdPath)) {
2605
- const stat = lstatSync(claudeMdPath);
2639
+ const stat = lstatSync2(claudeMdPath);
2606
2640
  if (stat.isSymbolicLink()) {
2607
2641
  const content = readFile(claudeMdPath);
2608
2642
  unlinkSync2(claudeMdPath);
@@ -2629,6 +2663,7 @@ async function updateCommand(options) {
2629
2663
  syncSpinner.start("Updating enabled addon files...");
2630
2664
  let totalUpdated = 0;
2631
2665
  for (const name of enabledAddons) {
2666
+ if (name === "orchestration") continue;
2632
2667
  const addonSourceDir = getAddonSourceDir(name);
2633
2668
  const result = syncAddonFiles(targetDir, addonSourceDir, addonConfig.agents);
2634
2669
  totalUpdated += (result.updated ?? 0) + result.written;
@@ -2754,7 +2789,7 @@ async function regenerateWithNewStack(targetDir, manifest, analysis, dryRun) {
2754
2789
  }
2755
2790
  const claudeMdPath = join11(targetDir, "CLAUDE.md");
2756
2791
  if (fileExists(claudeMdPath)) {
2757
- const stat = lstatSync(claudeMdPath);
2792
+ const stat = lstatSync2(claudeMdPath);
2758
2793
  if (stat.isSymbolicLink()) {
2759
2794
  const content = readFile(claudeMdPath);
2760
2795
  unlinkSync2(claudeMdPath);
@@ -2889,7 +2924,7 @@ async function migrateToPlugin(targetDir, manifest, analysis, dryRun) {
2889
2924
  }
2890
2925
  p4.note(
2891
2926
  ` Plugin: ${chalk5.cyan("devtronic")} at .claude-plugins/devtronic/
2892
- Skills: /devtronic:brief, /devtronic:spec, ...
2927
+ Skills: /brief, /spec, ... (auto-namespaced in plugin mode)
2893
2928
  Hooks: 5 workflow hooks enabled`,
2894
2929
  "Plugin Generated"
2895
2930
  );
@@ -2920,7 +2955,7 @@ function cleanEmptyDirs(dirPath) {
2920
2955
  const entries = readdirSync2(dirPath);
2921
2956
  for (const entry of entries) {
2922
2957
  const fullPath = join11(dirPath, entry);
2923
- if (existsSync9(fullPath) && lstatSync(fullPath).isDirectory()) {
2958
+ if (existsSync9(fullPath) && lstatSync2(fullPath).isDirectory()) {
2924
2959
  cleanEmptyDirs(fullPath);
2925
2960
  }
2926
2961
  }
@@ -3441,7 +3476,7 @@ Valid options:
3441
3476
  if (!manifest.selectedIDEs.includes("claude-code") || manifest.installMode !== "plugin") {
3442
3477
  p8.log.warn("Plugin regeneration only applies to Claude Code in plugin mode. Skipping.");
3443
3478
  } else {
3444
- const { generatePlugin: generatePlugin2 } = await import("./plugin-SGSFVXPA.js");
3479
+ const { generatePlugin: generatePlugin2 } = await import("./plugin-KQQASBQX.js");
3445
3480
  const pluginResult = generatePlugin2(
3446
3481
  targetDir,
3447
3482
  TEMPLATES_DIR2,
@@ -4407,7 +4442,7 @@ function readdirSafe(dir) {
4407
4442
 
4408
4443
  // src/commands/addon.ts
4409
4444
  import { resolve as resolve14, join as join20, dirname as dirname10 } from "path";
4410
- import { existsSync as existsSync17, unlinkSync as unlinkSync3, rmSync as rmSync3, readFileSync as readFileSync6 } from "fs";
4445
+ import { existsSync as existsSync17, unlinkSync as unlinkSync3, rmSync as rmSync3 } from "fs";
4411
4446
  import * as p14 from "@clack/prompts";
4412
4447
  import chalk15 from "chalk";
4413
4448
  function isFileBasedAddon(addonName) {
@@ -4425,8 +4460,8 @@ Valid addons: ${validAddons.join(", ")}`);
4425
4460
  }
4426
4461
  const typedName = addonName;
4427
4462
  const canonicalAction = action === "enable" ? "add" : action === "disable" ? "remove" : action;
4428
- if (action === "add" || action === "remove") {
4429
- const canonical = action === "add" ? "enable" : "disable";
4463
+ if (action === "enable" || action === "disable") {
4464
+ const canonical = action === "enable" ? "add" : "remove";
4430
4465
  p14.log.warn(
4431
4466
  `"addon ${action}" is deprecated. Use "addon ${canonical}" instead.`
4432
4467
  );
@@ -4473,12 +4508,12 @@ async function addAddon(targetDir, manifest, addonName, currentAddons) {
4473
4508
  [
4474
4509
  ` ${chalk15.dim("Name:")} ${addon.label}`,
4475
4510
  ` ${chalk15.dim("Description:")} ${addon.description}`,
4476
- ` ${chalk15.dim("Skills:")} ${addon.skills.map((s) => chalk15.cyan(`/devtronic:${s}`)).join(", ")}`,
4511
+ ` ${chalk15.dim("Skills:")} ${addon.skills.map((s) => chalk15.cyan(`/${s}`)).join(", ")}`,
4477
4512
  ` ${chalk15.dim("Subagents:")} ${addon.agents.length ? addon.agents.join(", ") : chalk15.dim("\u2014")}`
4478
4513
  ].join("\n"),
4479
4514
  "Adding addon"
4480
4515
  );
4481
- const confirmed = await p14.confirm({ message: "Add this addon?" });
4516
+ const confirmed = await p14.confirm({ message: `Add ${addonName}?` });
4482
4517
  if (p14.isCancel(confirmed) || !confirmed) {
4483
4518
  p14.cancel("Addon installation cancelled.");
4484
4519
  process.exit(0);
@@ -4514,7 +4549,7 @@ async function addAddon(targetDir, manifest, addonName, currentAddons) {
4514
4549
  writeManifest(targetDir, manifest);
4515
4550
  spinner8.stop(`${symbols.pass} ${addon.label} added`);
4516
4551
  p14.note(
4517
- addon.skills.map((s) => ` ${chalk15.cyan(`/devtronic:${s}`)}`).join("\n"),
4552
+ addon.skills.map((s) => ` ${chalk15.cyan(`/${s}`)}`).join("\n"),
4518
4553
  "New skills available"
4519
4554
  );
4520
4555
  p14.outro("Done. Restart Claude Code to load the new skills.");
@@ -4531,12 +4566,12 @@ async function removeAddon(targetDir, manifest, addonName, currentAddons) {
4531
4566
  [
4532
4567
  ` ${chalk15.dim("Name:")} ${addon.label}`,
4533
4568
  ` ${chalk15.dim("Description:")} ${addon.description}`,
4534
- ` ${chalk15.dim("Skills:")} ${addon.skills.map((s) => chalk15.dim(`/devtronic:${s}`)).join(", ")}`,
4569
+ ` ${chalk15.dim("Skills:")} ${addon.skills.map((s) => chalk15.dim(`/${s}`)).join(", ")}`,
4535
4570
  ` ${chalk15.dim("Subagents:")} ${addon.agents.length ? addon.agents.join(", ") : chalk15.dim("\u2014")}`
4536
4571
  ].join("\n"),
4537
4572
  "Removing addon"
4538
4573
  );
4539
- const confirmed = await p14.confirm({ message: "Remove this addon?" });
4574
+ const confirmed = await p14.confirm({ message: `Remove ${addonName}?` });
4540
4575
  if (p14.isCancel(confirmed) || !confirmed) {
4541
4576
  p14.cancel("Addon removal cancelled.");
4542
4577
  process.exit(0);
@@ -4593,7 +4628,7 @@ async function removeAddon(targetDir, manifest, addonName, currentAddons) {
4593
4628
  writeManifest(targetDir, manifest);
4594
4629
  spinner8.stop(`${symbols.pass} ${addon.label} removed`);
4595
4630
  p14.note(
4596
- addon.skills.map((s) => ` ${chalk15.dim(`/devtronic:${s}`)}`).join("\n"),
4631
+ addon.skills.map((s) => ` ${chalk15.dim(`/${s}`)}`).join("\n"),
4597
4632
  "Skills removed"
4598
4633
  );
4599
4634
  p14.outro("Done. Restart Claude Code to apply the changes.");
@@ -4615,7 +4650,7 @@ async function addFileBasedAddon(targetDir, addonName, _options) {
4615
4650
  ].join("\n"),
4616
4651
  "Adding addon"
4617
4652
  );
4618
- const confirmed = await p14.confirm({ message: "Add this addon?" });
4653
+ const confirmed = await p14.confirm({ message: `Add ${addonName}?` });
4619
4654
  if (p14.isCancel(confirmed) || !confirmed) {
4620
4655
  p14.cancel("Addon installation cancelled.");
4621
4656
  process.exit(0);
@@ -4624,16 +4659,14 @@ async function addFileBasedAddon(targetDir, addonName, _options) {
4624
4659
  spinner8.start(`Adding ${addon.label}...`);
4625
4660
  const addonSourceDir = getAddonSourceDir(addonName);
4626
4661
  const result = generateAddonFiles(targetDir, addonSourceDir, config.agents);
4627
- const addonManifest = JSON.parse(
4628
- readFileSync6(join20(addonSourceDir, "manifest.json"), "utf-8")
4629
- );
4662
+ const addonMeta = getAddonManifest(addonName);
4630
4663
  const fileList = [
4631
- ...(addonManifest.files.skills ?? []).map((s) => `skills/${s}`),
4632
- ...(addonManifest.files.agents ?? []).map((a) => `agents/${a}.md`),
4633
- ...(addonManifest.files.rules ?? []).map((r) => `rules/${r}`)
4664
+ ...(addonMeta.files.skills ?? []).map((s) => `skills/${s}`),
4665
+ ...(addonMeta.files.agents ?? []).map((a) => `agents/${a}.md`),
4666
+ ...(addonMeta.files.rules ?? []).map((r) => `rules/${r}`)
4634
4667
  ];
4635
4668
  writeAddonToConfig(targetDir, addonName, {
4636
- version: addonManifest.version,
4669
+ version: addonMeta.version,
4637
4670
  files: fileList,
4638
4671
  checksums: result.checksums ?? {}
4639
4672
  });
@@ -4706,7 +4739,24 @@ async function addonSyncCommand(options) {
4706
4739
  const targetDir = resolve14(options.path || ".");
4707
4740
  p14.intro(introTitle("Addon Sync"));
4708
4741
  const config = readAddonConfig(targetDir);
4709
- const installedNames = Object.keys(config.installed);
4742
+ const manifest = readManifest(targetDir);
4743
+ const manifestAddons = manifest?.projectConfig?.enabledAddons ?? [];
4744
+ for (const name of manifestAddons) {
4745
+ if (!config.installed[name] && isFileBasedAddon(name)) {
4746
+ const addonMeta = getAddonManifest(name);
4747
+ const fileList = [
4748
+ ...(addonMeta.files.skills ?? []).map((s) => `skills/${s}`),
4749
+ ...(addonMeta.files.agents ?? []).map((a) => `agents/${a}.md`),
4750
+ ...(addonMeta.files.rules ?? []).map((r) => `rules/${r}`)
4751
+ ];
4752
+ writeAddonToConfig(targetDir, name, {
4753
+ version: addonMeta.version,
4754
+ files: fileList
4755
+ });
4756
+ }
4757
+ }
4758
+ const freshConfig = readAddonConfig(targetDir);
4759
+ const installedNames = Object.keys(freshConfig.installed);
4710
4760
  if (installedNames.length === 0) {
4711
4761
  p14.log.info("No addons installed. Nothing to sync.");
4712
4762
  p14.outro("");
@@ -4717,8 +4767,9 @@ async function addonSyncCommand(options) {
4717
4767
  let totalWritten = 0;
4718
4768
  let totalConflicts = [];
4719
4769
  for (const name of installedNames) {
4770
+ if (!isFileBasedAddon(name)) continue;
4720
4771
  const addonSourceDir = getAddonSourceDir(name);
4721
- const result = syncAddonFiles(targetDir, addonSourceDir, config.agents);
4772
+ const result = syncAddonFiles(targetDir, addonSourceDir, freshConfig.agents);
4722
4773
  totalWritten += result.written + (result.updated ?? 0);
4723
4774
  totalConflicts = totalConflicts.concat(result.conflicts);
4724
4775
  }
@@ -4850,7 +4901,7 @@ program.command("uninstall").description("Remove devtronic from your project").o
4850
4901
  });
4851
4902
  program.command("mode").description("Set or show the execution mode (hitl or afk)").argument("<mode>", "Mode: afk, hitl, or show").option("--path <path>", "Target directory (default: current directory)").action(async (mode, options) => {
4852
4903
  if (!["afk", "hitl", "show"].includes(mode)) {
4853
- console.error(`Invalid mode: "${mode}". Valid values: afk, hitl, show`);
4904
+ p16.cancel(`Invalid mode: "${mode}". Valid values: afk, hitl, show`);
4854
4905
  process.exit(1);
4855
4906
  }
4856
4907
  await modeCommand(mode, { path: options.path });
@@ -8,7 +8,7 @@ import {
8
8
  generateMarketplaceJson,
9
9
  generatePlugin,
10
10
  generatePluginJson
11
- } from "./chunk-V4QEAL7Y.js";
11
+ } from "./chunk-WM7R52TC.js";
12
12
  export {
13
13
  BASE_AGENT_COUNT,
14
14
  BASE_SKILL_COUNT,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devtronic",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "AI-assisted development toolkit — skills, agents, quality gates, and rules for Claude Code, Cursor, Copilot, and Antigravity",
5
5
  "type": "module",
6
6
  "bin": {