@orderful/droid 0.18.0 → 0.20.0

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 (41) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/bin/droid.js +189 -82
  3. package/dist/index.js +175 -72
  4. package/dist/lib/config.d.ts.map +1 -1
  5. package/dist/lib/migrations.d.ts +30 -0
  6. package/dist/lib/migrations.d.ts.map +1 -0
  7. package/dist/lib/skill-config.d.ts.map +1 -1
  8. package/dist/lib/skills.d.ts.map +1 -1
  9. package/dist/lib/types.d.ts +10 -0
  10. package/dist/lib/types.d.ts.map +1 -1
  11. package/dist/tools/brain/TOOL.yaml +1 -1
  12. package/dist/tools/coach/TOOL.yaml +1 -1
  13. package/dist/tools/codex/TOOL.yaml +32 -0
  14. package/dist/tools/codex/commands/codex.md +70 -0
  15. package/dist/tools/codex/skills/droid-codex/SKILL.md +266 -0
  16. package/dist/tools/codex/skills/droid-codex/references/creating.md +150 -0
  17. package/dist/tools/codex/skills/droid-codex/references/decisions.md +128 -0
  18. package/dist/tools/codex/skills/droid-codex/references/loading.md +163 -0
  19. package/dist/tools/codex/skills/droid-codex/references/topics.md +213 -0
  20. package/dist/tools/comments/TOOL.yaml +1 -1
  21. package/dist/tools/droid/skills/droid/SKILL.md +8 -0
  22. package/dist/tools/project/TOOL.yaml +1 -1
  23. package/package.json +1 -1
  24. package/src/lib/config.ts +13 -2
  25. package/src/lib/migrations.test.ts +163 -0
  26. package/src/lib/migrations.ts +182 -0
  27. package/src/lib/skill-config.ts +3 -1
  28. package/src/lib/skills.ts +10 -1
  29. package/src/lib/types.ts +11 -0
  30. package/src/tools/brain/TOOL.yaml +1 -1
  31. package/src/tools/coach/TOOL.yaml +1 -1
  32. package/src/tools/codex/TOOL.yaml +32 -0
  33. package/src/tools/codex/commands/codex.md +70 -0
  34. package/src/tools/codex/skills/droid-codex/SKILL.md +266 -0
  35. package/src/tools/codex/skills/droid-codex/references/creating.md +150 -0
  36. package/src/tools/codex/skills/droid-codex/references/decisions.md +128 -0
  37. package/src/tools/codex/skills/droid-codex/references/loading.md +163 -0
  38. package/src/tools/codex/skills/droid-codex/references/topics.md +213 -0
  39. package/src/tools/comments/TOOL.yaml +1 -1
  40. package/src/tools/droid/skills/droid/SKILL.md +8 -0
  41. package/src/tools/project/TOOL.yaml +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @orderful/droid
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#109](https://github.com/Orderful/droid/pull/109) [`1014243`](https://github.com/Orderful/droid/commit/10142438bcd75723027d12ec7bdc23f012643ee3) Thanks [@frytyler](https://github.com/frytyler)! - Add codex tool for shared organizational knowledge
8
+
9
+ New tool providing access to the orderful-codex repo containing PRDs, tech designs, patterns, and explored topics. Features include:
10
+ - Load project context with `/codex {name}`
11
+ - Search across all categories
12
+ - Capture decisions during implementation
13
+ - Add explored topics with freshness tracking
14
+ - Auto-generate CONTEXT.md from project artifacts
15
+
16
+ ## 0.19.0
17
+
18
+ ### Minor Changes
19
+
20
+ - [#104](https://github.com/Orderful/droid/pull/104) [`b6eaef4`](https://github.com/Orderful/droid/commit/b6eaef4fb3b003d41b5451e7efdba633a50b525e) Thanks [@frytyler](https://github.com/frytyler)! - Add tool migration system and fix skill config paths
21
+ - **Migration system**: Tools can now define migrations that run after install/update. Migrations are tracked per-tool in config and logged to `~/.droid/.migrations.log`.
22
+ - **Config path fix**: Skill overrides now save to unprefixed paths (`~/.droid/skills/brain/` not `~/.droid/skills/droid-brain/`), matching what SKILL.md tells Claude to read.
23
+ - **Automatic migration**: Existing users with prefixed config directories will have them automatically migrated on tool update.
24
+
25
+ Tool version bumps:
26
+ - brain: 0.2.2 → 0.2.3
27
+ - comments: 0.2.5 → 0.2.6
28
+ - project: 0.1.4 → 0.1.5
29
+ - coach: 0.1.2 → 0.1.3
30
+
3
31
  ## 0.18.0
4
32
 
5
33
  ### Minor Changes
package/dist/bin/droid.js CHANGED
@@ -7,8 +7,8 @@ import { program } from "commander";
7
7
  import inquirer from "inquirer";
8
8
  import chalk2 from "chalk";
9
9
  import { execSync as execSync2 } from "child_process";
10
- import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
11
- import { join as join7 } from "path";
10
+ import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "fs";
11
+ import { join as join8 } from "path";
12
12
  import { homedir as homedir3 } from "os";
13
13
 
14
14
  // src/lib/config.ts
@@ -126,8 +126,15 @@ function setConfigValue(key, value) {
126
126
  function getConfigPath() {
127
127
  return CONFIG_FILE;
128
128
  }
129
+ function getConfigDir() {
130
+ return CONFIG_DIR;
131
+ }
132
+ function normalizeSkillNameForConfig(skillName) {
133
+ return skillName.replace(/^droid-/, "");
134
+ }
129
135
  function getSkillOverridesPath(skillName) {
130
- return join(CONFIG_DIR, "skills", skillName, "overrides.yaml");
136
+ const normalizedName = normalizeSkillNameForConfig(skillName);
137
+ return join(CONFIG_DIR, "skills", normalizedName, "overrides.yaml");
131
138
  }
132
139
  function loadSkillOverrides(skillName) {
133
140
  const overridesPath = getSkillOverridesPath(skillName);
@@ -142,8 +149,9 @@ function loadSkillOverrides(skillName) {
142
149
  }
143
150
  }
144
151
  function saveSkillOverrides(skillName, overrides) {
152
+ const normalizedName = normalizeSkillNameForConfig(skillName);
145
153
  const overridesPath = getSkillOverridesPath(skillName);
146
- const skillDir = join(CONFIG_DIR, "skills", skillName);
154
+ const skillDir = join(CONFIG_DIR, "skills", normalizedName);
147
155
  if (!existsSync(skillDir)) {
148
156
  mkdirSync(skillDir, { recursive: true });
149
157
  }
@@ -168,8 +176,8 @@ function setAutoUpdateConfig(updates) {
168
176
  }
169
177
 
170
178
  // src/lib/skills.ts
171
- import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, rmSync } from "fs";
172
- import { join as join6, dirname as dirname4 } from "path";
179
+ import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, rmSync as rmSync2 } from "fs";
180
+ import { join as join7, dirname as dirname5, basename } from "path";
173
181
  import { fileURLToPath as fileURLToPath4 } from "url";
174
182
  import YAML4 from "yaml";
175
183
 
@@ -508,11 +516,104 @@ function uninstallAgent(agentName) {
508
516
  }
509
517
  }
510
518
 
519
+ // src/lib/migrations.ts
520
+ import { existsSync as existsSync4, appendFileSync, mkdirSync as mkdirSync3, renameSync, rmSync } from "fs";
521
+ import { join as join6, dirname as dirname4 } from "path";
522
+ var MIGRATIONS_LOG_FILE = ".migrations.log";
523
+ function getMigrationsLogPath() {
524
+ return join6(getConfigDir(), MIGRATIONS_LOG_FILE);
525
+ }
526
+ function logMigration(toolName, fromVersion, toVersion, status, error) {
527
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
528
+ const logEntry = error ? `${timestamp} ${toolName} ${fromVersion} \u2192 ${toVersion} ${status}: ${error}
529
+ ` : `${timestamp} ${toolName} ${fromVersion} \u2192 ${toVersion} ${status}
530
+ `;
531
+ const logPath = getMigrationsLogPath();
532
+ const logDir = dirname4(logPath);
533
+ if (!existsSync4(logDir)) {
534
+ mkdirSync3(logDir, { recursive: true });
535
+ }
536
+ appendFileSync(logPath, logEntry);
537
+ }
538
+ function createConfigDirMigration(skillName, version2) {
539
+ const unprefixedName = skillName.replace(/^droid-/, "");
540
+ return {
541
+ version: version2,
542
+ description: `Move ${skillName} config to unprefixed location`,
543
+ up: (configDir) => {
544
+ const oldDir = join6(configDir, "skills", skillName);
545
+ const newDir = join6(configDir, "skills", unprefixedName);
546
+ if (existsSync4(oldDir) && !existsSync4(newDir)) {
547
+ const parentDir = dirname4(newDir);
548
+ if (!existsSync4(parentDir)) {
549
+ mkdirSync3(parentDir, { recursive: true });
550
+ }
551
+ renameSync(oldDir, newDir);
552
+ } else if (existsSync4(oldDir) && existsSync4(newDir)) {
553
+ rmSync(oldDir, { recursive: true });
554
+ }
555
+ }
556
+ };
557
+ }
558
+ var TOOL_MIGRATIONS = {
559
+ brain: [createConfigDirMigration("droid-brain", "0.2.3")],
560
+ comments: [createConfigDirMigration("droid-comments", "0.2.6")],
561
+ project: [createConfigDirMigration("droid-project", "0.1.5")],
562
+ coach: [createConfigDirMigration("droid-coach", "0.1.3")]
563
+ };
564
+ function getToolMigrations(toolName) {
565
+ return TOOL_MIGRATIONS[toolName] ?? [];
566
+ }
567
+ function getLastMigratedVersion(toolName) {
568
+ const config = loadConfig();
569
+ return config.migrations?.[toolName] ?? "0.0.0";
570
+ }
571
+ function setLastMigratedVersion(toolName, version2) {
572
+ const config = loadConfig();
573
+ if (!config.migrations) {
574
+ config.migrations = {};
575
+ }
576
+ config.migrations[toolName] = version2;
577
+ saveConfig(config);
578
+ }
579
+ function runMigrations(toolName, fromVersion, toVersion) {
580
+ const migrations = getToolMigrations(toolName);
581
+ const pendingMigrations = migrations.filter((m) => {
582
+ const afterFrom = compareSemver(m.version, fromVersion) > 0;
583
+ const beforeOrAtTo = compareSemver(m.version, toVersion) <= 0;
584
+ return afterFrom && beforeOrAtTo;
585
+ });
586
+ if (pendingMigrations.length === 0) {
587
+ setLastMigratedVersion(toolName, toVersion);
588
+ return { success: true };
589
+ }
590
+ const configDir = getConfigDir();
591
+ for (const migration of pendingMigrations) {
592
+ try {
593
+ migration.up(configDir);
594
+ logMigration(toolName, fromVersion, migration.version, "OK");
595
+ } catch (error) {
596
+ const errorMessage = error instanceof Error ? error.message : String(error);
597
+ logMigration(toolName, fromVersion, migration.version, "FAILED", errorMessage);
598
+ return { success: false, error: `Migration ${migration.version} failed: ${errorMessage}` };
599
+ }
600
+ }
601
+ setLastMigratedVersion(toolName, toVersion);
602
+ return { success: true };
603
+ }
604
+ function runToolMigrations(toolName, installedVersion) {
605
+ const lastMigrated = getLastMigratedVersion(toolName);
606
+ if (compareSemver(installedVersion, lastMigrated) <= 0) {
607
+ return { success: true };
608
+ }
609
+ return runMigrations(toolName, lastMigrated, installedVersion);
610
+ }
611
+
511
612
  // src/lib/skills.ts
512
613
  var DROID_SKILLS_START = "<!-- droid-skills-start -->";
513
614
  var DROID_SKILLS_END = "<!-- droid-skills-end -->";
514
- var __dirname4 = dirname4(fileURLToPath4(import.meta.url));
515
- var BUNDLED_SKILLS_DIR = join6(__dirname4, "../tools");
615
+ var __dirname4 = dirname5(fileURLToPath4(import.meta.url));
616
+ var BUNDLED_SKILLS_DIR = join7(__dirname4, "../tools");
516
617
  function getSkillsInstallPath(platform) {
517
618
  return getSkillsPath(platform);
518
619
  }
@@ -525,7 +626,7 @@ function getPlatformConfigPath(platform) {
525
626
  function updatePlatformConfigSkills(platform, installedSkills) {
526
627
  const configPath = getPlatformConfigPath(platform);
527
628
  let content = "";
528
- if (existsSync4(configPath)) {
629
+ if (existsSync5(configPath)) {
529
630
  content = readFileSync5(configPath, "utf-8");
530
631
  }
531
632
  const skillLines = installedSkills.map((name) => {
@@ -544,9 +645,9 @@ ${DROID_SKILLS_END}` : "";
544
645
  } else if (skillsSection) {
545
646
  content = content.trim() + "\n\n" + skillsSection + "\n";
546
647
  }
547
- const configDir = dirname4(configPath);
548
- if (!existsSync4(configDir)) {
549
- mkdirSync3(configDir, { recursive: true });
648
+ const configDir = dirname5(configPath);
649
+ if (!existsSync5(configDir)) {
650
+ mkdirSync4(configDir, { recursive: true });
550
651
  }
551
652
  writeFileSync3(configPath, content, "utf-8");
552
653
  }
@@ -567,8 +668,8 @@ function parseSkillFrontmatter(content) {
567
668
  }
568
669
  }
569
670
  function loadSkillManifest(skillDir) {
570
- const skillMdPath = join6(skillDir, "SKILL.md");
571
- if (!existsSync4(skillMdPath)) {
671
+ const skillMdPath = join7(skillDir, "SKILL.md");
672
+ if (!existsSync5(skillMdPath)) {
572
673
  return null;
573
674
  }
574
675
  const content = readFileSync5(skillMdPath, "utf-8");
@@ -576,7 +677,7 @@ function loadSkillManifest(skillDir) {
576
677
  if (!frontmatter || !frontmatter.name) {
577
678
  return null;
578
679
  }
579
- const toolDir = dirname4(dirname4(skillDir));
680
+ const toolDir = dirname5(dirname5(skillDir));
580
681
  const toolManifest = loadToolManifest(toolDir);
581
682
  return {
582
683
  name: frontmatter.name,
@@ -588,17 +689,17 @@ function loadSkillManifest(skillDir) {
588
689
  };
589
690
  }
590
691
  function findSkillPath(skillName) {
591
- if (!existsSync4(BUNDLED_SKILLS_DIR)) {
692
+ if (!existsSync5(BUNDLED_SKILLS_DIR)) {
592
693
  return null;
593
694
  }
594
695
  const toolDirs = readdirSync3(BUNDLED_SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
595
696
  for (const toolName of toolDirs) {
596
- const skillsDir = join6(BUNDLED_SKILLS_DIR, toolName, "skills");
597
- if (!existsSync4(skillsDir)) continue;
598
- const skillDir = join6(skillsDir, skillName);
599
- if (existsSync4(skillDir) && existsSync4(join6(skillDir, "SKILL.md"))) {
697
+ const skillsDir = join7(BUNDLED_SKILLS_DIR, toolName, "skills");
698
+ if (!existsSync5(skillsDir)) continue;
699
+ const skillDir = join7(skillsDir, skillName);
700
+ if (existsSync5(skillDir) && existsSync5(join7(skillDir, "SKILL.md"))) {
600
701
  return {
601
- toolDir: join6(BUNDLED_SKILLS_DIR, toolName),
702
+ toolDir: join7(BUNDLED_SKILLS_DIR, toolName),
602
703
  skillDir
603
704
  };
604
705
  }
@@ -606,17 +707,17 @@ function findSkillPath(skillName) {
606
707
  return null;
607
708
  }
608
709
  function getBundledSkills() {
609
- if (!existsSync4(BUNDLED_SKILLS_DIR)) {
710
+ if (!existsSync5(BUNDLED_SKILLS_DIR)) {
610
711
  return [];
611
712
  }
612
713
  const toolDirs = readdirSync3(BUNDLED_SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
613
714
  const skills = [];
614
715
  for (const toolName of toolDirs) {
615
- const skillsDir = join6(BUNDLED_SKILLS_DIR, toolName, "skills");
616
- if (!existsSync4(skillsDir)) continue;
716
+ const skillsDir = join7(BUNDLED_SKILLS_DIR, toolName, "skills");
717
+ if (!existsSync5(skillsDir)) continue;
617
718
  const skillSubdirs = readdirSync3(skillsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
618
719
  for (const skillName of skillSubdirs) {
619
- const manifest = loadSkillManifest(join6(skillsDir, skillName));
720
+ const manifest = loadSkillManifest(join7(skillsDir, skillName));
620
721
  if (manifest) {
621
722
  skills.push(manifest);
622
723
  }
@@ -693,15 +794,15 @@ function installSkill(skillName) {
693
794
  }
694
795
  }
695
796
  const skillsPath = getSkillsInstallPath(config.platform);
696
- const targetSkillDir = join6(skillsPath, skillName);
797
+ const targetSkillDir = join7(skillsPath, skillName);
697
798
  const commandsPath = getCommandsInstallPath(config.platform);
698
799
  const tools = getPlatformTools(config);
699
800
  if (skillName.startsWith("droid-")) {
700
801
  const oldSkillName = skillName.replace(/^droid-/, "");
701
- const oldSkillDir = join6(skillsPath, oldSkillName);
702
- if (existsSync4(oldSkillDir)) {
802
+ const oldSkillDir = join7(skillsPath, oldSkillName);
803
+ if (existsSync5(oldSkillDir)) {
703
804
  try {
704
- rmSync(oldSkillDir, { recursive: true });
805
+ rmSync2(oldSkillDir, { recursive: true });
705
806
  } catch (error) {
706
807
  console.warn(`Warning: Could not remove old skill directory ${oldSkillDir}: ${error}`);
707
808
  }
@@ -712,14 +813,14 @@ function installSkill(skillName) {
712
813
  saveConfig(config);
713
814
  }
714
815
  }
715
- const commandsSource = join6(toolDir, "commands");
716
- const agentsSource = join6(toolDir, "agents");
816
+ const commandsSource = join7(toolDir, "commands");
817
+ const agentsSource = join7(toolDir, "agents");
717
818
  if (!tools[skillName]) {
718
- if (existsSync4(commandsSource)) {
819
+ if (existsSync5(commandsSource)) {
719
820
  const commandFiles = readdirSync3(commandsSource).filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md");
720
821
  for (const file of commandFiles) {
721
- const targetCommandPath = join6(commandsPath, file);
722
- if (existsSync4(targetCommandPath)) {
822
+ const targetCommandPath = join7(commandsPath, file);
823
+ if (existsSync5(targetCommandPath)) {
723
824
  const commandName = file.replace(".md", "");
724
825
  return {
725
826
  success: false,
@@ -728,7 +829,7 @@ function installSkill(skillName) {
728
829
  }
729
830
  }
730
831
  }
731
- if (existsSync4(agentsSource)) {
832
+ if (existsSync5(agentsSource)) {
732
833
  const agentDirs = readdirSync3(agentsSource, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
733
834
  for (const agentName of agentDirs) {
734
835
  if (isAgentInstalled(agentName)) {
@@ -740,49 +841,49 @@ function installSkill(skillName) {
740
841
  }
741
842
  }
742
843
  }
743
- if (!existsSync4(skillsPath)) {
744
- mkdirSync3(skillsPath, { recursive: true });
844
+ if (!existsSync5(skillsPath)) {
845
+ mkdirSync4(skillsPath, { recursive: true });
745
846
  }
746
- const skillMdSource = join6(skillDir, "SKILL.md");
747
- if (existsSync4(skillMdSource)) {
748
- if (!existsSync4(targetSkillDir)) {
749
- mkdirSync3(targetSkillDir, { recursive: true });
847
+ const skillMdSource = join7(skillDir, "SKILL.md");
848
+ if (existsSync5(skillMdSource)) {
849
+ if (!existsSync5(targetSkillDir)) {
850
+ mkdirSync4(targetSkillDir, { recursive: true });
750
851
  }
751
- const skillMdTarget = join6(targetSkillDir, "SKILL.md");
852
+ const skillMdTarget = join7(targetSkillDir, "SKILL.md");
752
853
  const content = readFileSync5(skillMdSource, "utf-8");
753
854
  writeFileSync3(skillMdTarget, content);
754
855
  }
755
- const referencesSource = join6(skillDir, "references");
756
- if (existsSync4(referencesSource)) {
757
- const targetReferencesDir = join6(targetSkillDir, "references");
758
- if (!existsSync4(targetReferencesDir)) {
759
- mkdirSync3(targetReferencesDir, { recursive: true });
856
+ const referencesSource = join7(skillDir, "references");
857
+ if (existsSync5(referencesSource)) {
858
+ const targetReferencesDir = join7(targetSkillDir, "references");
859
+ if (!existsSync5(targetReferencesDir)) {
860
+ mkdirSync4(targetReferencesDir, { recursive: true });
760
861
  }
761
862
  const referenceFiles = readdirSync3(referencesSource).filter((f) => f.endsWith(".md"));
762
863
  for (const file of referenceFiles) {
763
- const sourcePath = join6(referencesSource, file);
764
- const targetPath = join6(targetReferencesDir, file);
864
+ const sourcePath = join7(referencesSource, file);
865
+ const targetPath = join7(targetReferencesDir, file);
765
866
  const content = readFileSync5(sourcePath, "utf-8");
766
867
  writeFileSync3(targetPath, content);
767
868
  }
768
869
  }
769
- if (existsSync4(commandsSource)) {
770
- if (!existsSync4(commandsPath)) {
771
- mkdirSync3(commandsPath, { recursive: true });
870
+ if (existsSync5(commandsSource)) {
871
+ if (!existsSync5(commandsPath)) {
872
+ mkdirSync4(commandsPath, { recursive: true });
772
873
  }
773
874
  const commandFiles = readdirSync3(commandsSource).filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md");
774
875
  for (const file of commandFiles) {
775
- const sourcePath = join6(commandsSource, file);
776
- const targetPath = join6(commandsPath, file);
876
+ const sourcePath = join7(commandsSource, file);
877
+ const targetPath = join7(commandsPath, file);
777
878
  const content = readFileSync5(sourcePath, "utf-8");
778
879
  writeFileSync3(targetPath, content);
779
880
  }
780
881
  }
781
882
  const installedAgents = [];
782
- if (existsSync4(agentsSource)) {
883
+ if (existsSync5(agentsSource)) {
783
884
  const agentDirs = readdirSync3(agentsSource, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
784
885
  for (const agentName of agentDirs) {
785
- const agentDir = join6(agentsSource, agentName);
886
+ const agentDir = join7(agentsSource, agentName);
786
887
  const result = installAgentFromPath(agentDir, agentName);
787
888
  if (result.success) {
788
889
  installedAgents.push(agentName);
@@ -801,6 +902,11 @@ function installSkill(skillName) {
801
902
  saveConfig(config);
802
903
  const installedSkillNames = Object.keys(updatedTools);
803
904
  updatePlatformConfigSkills(config.platform, installedSkillNames);
905
+ const toolName = basename(toolDir);
906
+ const migrationResult = runToolMigrations(toolName, manifest.version);
907
+ if (!migrationResult.success) {
908
+ console.warn(`Warning: Migration failed for ${toolName}: ${migrationResult.error}`);
909
+ }
804
910
  return { success: true, message: `Installed ${skillName} v${manifest.version}` };
805
911
  }
806
912
  function uninstallSkill(skillName) {
@@ -810,19 +916,19 @@ function uninstallSkill(skillName) {
810
916
  return { success: false, message: `Skill '${skillName}' is not installed` };
811
917
  }
812
918
  const skillsPath = getSkillsInstallPath(config.platform);
813
- const skillDir = join6(skillsPath, skillName);
814
- if (existsSync4(skillDir)) {
815
- rmSync(skillDir, { recursive: true });
919
+ const skillDir = join7(skillsPath, skillName);
920
+ if (existsSync5(skillDir)) {
921
+ rmSync2(skillDir, { recursive: true });
816
922
  }
817
923
  const skillPath = findSkillPath(skillName);
818
924
  const commandsPath = getCommandsInstallPath(config.platform);
819
- const commandsSource = skillPath ? join6(skillPath.toolDir, "commands") : null;
820
- if (commandsSource && existsSync4(commandsSource)) {
925
+ const commandsSource = skillPath ? join7(skillPath.toolDir, "commands") : null;
926
+ if (commandsSource && existsSync5(commandsSource)) {
821
927
  const commandFiles = readdirSync3(commandsSource).filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md");
822
928
  for (const file of commandFiles) {
823
- const commandPath = join6(commandsPath, file);
824
- if (existsSync4(commandPath)) {
825
- rmSync(commandPath);
929
+ const commandPath = join7(commandsPath, file);
930
+ if (existsSync5(commandPath)) {
931
+ rmSync2(commandPath);
826
932
  }
827
933
  }
828
934
  }
@@ -872,13 +978,13 @@ var OPENCODE_SKILLS_PLUGIN = "opencode-skills";
872
978
  function configurePlatformPermissions(platform) {
873
979
  const added = [];
874
980
  if (platform === "claude-code" /* ClaudeCode */) {
875
- const settingsPath = join7(homedir3(), ".claude", "settings.json");
876
- const claudeDir = join7(homedir3(), ".claude");
877
- if (!existsSync5(claudeDir)) {
878
- mkdirSync4(claudeDir, { recursive: true });
981
+ const settingsPath = join8(homedir3(), ".claude", "settings.json");
982
+ const claudeDir = join8(homedir3(), ".claude");
983
+ if (!existsSync6(claudeDir)) {
984
+ mkdirSync5(claudeDir, { recursive: true });
879
985
  }
880
986
  let settings = {};
881
- if (existsSync5(settingsPath)) {
987
+ if (existsSync6(settingsPath)) {
882
988
  try {
883
989
  settings = JSON.parse(readFileSync6(settingsPath, "utf-8"));
884
990
  } catch {
@@ -909,13 +1015,13 @@ function configurePlatformPermissions(platform) {
909
1015
  return { added, alreadyPresent: added.length === 0 };
910
1016
  }
911
1017
  if (platform === "opencode" /* OpenCode */) {
912
- const globalConfigDir = join7(homedir3(), ".config", "opencode");
913
- const globalConfigPath = join7(globalConfigDir, "opencode.json");
914
- if (!existsSync5(globalConfigDir)) {
915
- mkdirSync4(globalConfigDir, { recursive: true });
1018
+ const globalConfigDir = join8(homedir3(), ".config", "opencode");
1019
+ const globalConfigPath = join8(globalConfigDir, "opencode.json");
1020
+ if (!existsSync6(globalConfigDir)) {
1021
+ mkdirSync5(globalConfigDir, { recursive: true });
916
1022
  }
917
1023
  let config = {};
918
- if (existsSync5(globalConfigPath)) {
1024
+ if (existsSync6(globalConfigPath)) {
919
1025
  try {
920
1026
  config = JSON.parse(readFileSync6(globalConfigPath, "utf-8"));
921
1027
  } catch {
@@ -1180,8 +1286,9 @@ async function promptForSkillConfig(skillName, configSchema, askFirst = true) {
1180
1286
  }
1181
1287
  if (Object.keys(overrides).length > 0) {
1182
1288
  saveSkillOverrides(skillName, overrides);
1289
+ const displayName = skillName.replace(/^droid-/, "");
1183
1290
  console.log(chalk4.green(`
1184
- \u2713 Configuration saved to ~/.droid/skills/${skillName}/overrides.yaml`));
1291
+ \u2713 Configuration saved to ~/.droid/skills/${displayName}/overrides.yaml`));
1185
1292
  } else {
1186
1293
  console.log(chalk4.gray("\nNo custom configuration set (using defaults)."));
1187
1294
  }
@@ -2240,8 +2347,8 @@ function ReadmeViewer({ title, content, onClose }) {
2240
2347
  // src/commands/tui/views/ToolExplorer.tsx
2241
2348
  import { Box as Box10, Text as Text11, useInput as useInput5 } from "ink";
2242
2349
  import { useState as useState5, useMemo as useMemo3 } from "react";
2243
- import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
2244
- import { join as join8 } from "path";
2350
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
2351
+ import { join as join9 } from "path";
2245
2352
  import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2246
2353
  function ToolExplorer({ tool, onViewSource, onClose }) {
2247
2354
  const [selectedIndex, setSelectedIndex] = useState5(0);
@@ -2252,21 +2359,21 @@ function ToolExplorer({ tool, onViewSource, onClose }) {
2252
2359
  result.push({
2253
2360
  type: "skill",
2254
2361
  name: skill.name,
2255
- path: join8(toolDir, tool.name, "skills", skill.name, "SKILL.md")
2362
+ path: join9(toolDir, tool.name, "skills", skill.name, "SKILL.md")
2256
2363
  });
2257
2364
  }
2258
2365
  for (const cmd of tool.includes.commands) {
2259
2366
  result.push({
2260
2367
  type: "command",
2261
2368
  name: `/${cmd}`,
2262
- path: join8(toolDir, tool.name, "commands", `${cmd}.md`)
2369
+ path: join9(toolDir, tool.name, "commands", `${cmd}.md`)
2263
2370
  });
2264
2371
  }
2265
2372
  for (const agent of tool.includes.agents) {
2266
2373
  result.push({
2267
2374
  type: "agent",
2268
2375
  name: agent,
2269
- path: join8(toolDir, tool.name, "agents", agent, "AGENT.md")
2376
+ path: join9(toolDir, tool.name, "agents", agent, "AGENT.md")
2270
2377
  });
2271
2378
  }
2272
2379
  return result;
@@ -2284,12 +2391,12 @@ function ToolExplorer({ tool, onViewSource, onClose }) {
2284
2391
  }
2285
2392
  if (key.return && items.length > 0) {
2286
2393
  const item = items[selectedIndex];
2287
- if (existsSync6(item.path)) {
2394
+ if (existsSync7(item.path)) {
2288
2395
  const content = readFileSync7(item.path, "utf-8");
2289
2396
  onViewSource(`${tool.name} / ${item.name}`, content);
2290
2397
  } else {
2291
2398
  const yamlPath = item.path.replace(".md", ".yaml");
2292
- if (existsSync6(yamlPath)) {
2399
+ if (existsSync7(yamlPath)) {
2293
2400
  const content = readFileSync7(yamlPath, "utf-8");
2294
2401
  onViewSource(`${tool.name} / ${item.name}`, content);
2295
2402
  }