coder-config 0.44.38 → 0.44.40

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.
package/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.44.38';
5
+ const VERSION = '0.44.40';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.44.38",
3
+ "version": "0.44.40",
4
4
  "description": "Configuration manager for AI coding tools - Claude Code, Gemini CLI, Codex CLI, Antigravity. Manage MCPs, rules, permissions, memory, and workstreams.",
5
5
  "author": "regression.io",
6
6
  "main": "config-loader.js",
@@ -559,64 +559,93 @@ ${task}
559
559
  * Fix the ralph-loop plugin structure by converting commands to skills format
560
560
  * Claude Code expects skills/<name>/SKILL.md, but the plugin has commands/<name>.md
561
561
  * Also fixes frontmatter issues (hide-from-slash-command-tool -> name)
562
+ * Also fixes hooks.json to use absolute paths instead of ${CLAUDE_PLUGIN_ROOT}
562
563
  */
563
564
  function fixRalphLoopPluginStructure() {
564
- const pluginCacheDir = path.join(os.homedir(), '.claude', 'plugins', 'cache', 'claude-plugins-official', 'ralph-loop');
565
-
566
- if (!fs.existsSync(pluginCacheDir)) {
567
- return;
568
- }
569
-
570
- // Find all version directories
571
- const versions = fs.readdirSync(pluginCacheDir).filter(f => {
572
- const fullPath = path.join(pluginCacheDir, f);
573
- return fs.statSync(fullPath).isDirectory();
574
- });
575
-
576
- for (const version of versions) {
577
- const versionDir = path.join(pluginCacheDir, version);
578
- const commandsDir = path.join(versionDir, 'commands');
579
- const skillsDir = path.join(versionDir, 'skills');
565
+ // Fix both cache and marketplace directories
566
+ // Claude Code reads hooks from marketplace source, not cache
567
+ const pluginLocations = [
568
+ path.join(os.homedir(), '.claude', 'plugins', 'cache', 'claude-plugins-official', 'ralph-loop'),
569
+ path.join(os.homedir(), '.claude', 'plugins', 'marketplaces', 'claude-plugins-official', 'plugins', 'ralph-loop')
570
+ ];
580
571
 
581
- if (!fs.existsSync(commandsDir)) {
572
+ for (const pluginDir of pluginLocations) {
573
+ if (!fs.existsSync(pluginDir)) {
582
574
  continue;
583
575
  }
584
576
 
585
- // Remove old symlink if it exists
586
- if (fs.existsSync(skillsDir) && fs.lstatSync(skillsDir).isSymbolicLink()) {
587
- fs.unlinkSync(skillsDir);
588
- }
577
+ // Check if this is a versioned cache dir or direct marketplace dir
578
+ const hasVersionDirs = fs.readdirSync(pluginDir).some(f => {
579
+ const fullPath = path.join(pluginDir, f);
580
+ return fs.statSync(fullPath).isDirectory() && !['commands', 'skills', 'hooks', 'scripts', '.claude-plugin'].includes(f);
581
+ });
589
582
 
590
- // Create skills directory if it doesn't exist
591
- if (!fs.existsSync(skillsDir)) {
592
- fs.mkdirSync(skillsDir, { recursive: true });
593
- }
583
+ const dirsToFix = hasVersionDirs
584
+ ? fs.readdirSync(pluginDir).filter(f => {
585
+ const fullPath = path.join(pluginDir, f);
586
+ return fs.statSync(fullPath).isDirectory();
587
+ }).map(v => path.join(pluginDir, v))
588
+ : [pluginDir];
589
+
590
+ for (const versionDir of dirsToFix) {
591
+ const commandsDir = path.join(versionDir, 'commands');
592
+ const skillsDir = path.join(versionDir, 'skills');
593
+ const hooksDir = path.join(versionDir, 'hooks');
594
+
595
+ // Fix hooks.json - replace ${CLAUDE_PLUGIN_ROOT} with actual path
596
+ const hooksJsonPath = path.join(hooksDir, 'hooks.json');
597
+ if (fs.existsSync(hooksJsonPath)) {
598
+ try {
599
+ let hooksContent = fs.readFileSync(hooksJsonPath, 'utf8');
600
+ if (hooksContent.includes('${CLAUDE_PLUGIN_ROOT}')) {
601
+ hooksContent = hooksContent.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, versionDir);
602
+ fs.writeFileSync(hooksJsonPath, hooksContent, 'utf8');
603
+ }
604
+ } catch (e) {
605
+ // Ignore errors fixing hooks
606
+ }
607
+ }
594
608
 
595
- // Convert each command to skill format
596
- // commands/ralph-loop.md -> skills/ralph-loop/SKILL.md
597
- const commands = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
598
- for (const cmdFile of commands) {
599
- const skillName = cmdFile.replace('.md', '');
600
- const skillDir = path.join(skillsDir, skillName);
601
- const skillFile = path.join(skillDir, 'SKILL.md');
602
-
603
- // Create skill directory
604
- if (!fs.existsSync(skillDir)) {
605
- fs.mkdirSync(skillDir, { recursive: true });
609
+ if (!fs.existsSync(commandsDir)) {
610
+ continue;
606
611
  }
607
612
 
608
- // Read command file content
609
- const cmdPath = path.join(commandsDir, cmdFile);
610
- let content = fs.readFileSync(cmdPath, 'utf8');
613
+ // Remove old symlink if it exists
614
+ if (fs.existsSync(skillsDir) && fs.lstatSync(skillsDir).isSymbolicLink()) {
615
+ fs.unlinkSync(skillsDir);
616
+ }
611
617
 
612
- // Fix frontmatter: replace hide-from-slash-command-tool with name
613
- content = content.replace(
614
- /hide-from-slash-command-tool:\s*["']true["']/g,
615
- `name: ${skillName}`
616
- );
618
+ // Create skills directory if it doesn't exist
619
+ if (!fs.existsSync(skillsDir)) {
620
+ fs.mkdirSync(skillsDir, { recursive: true });
621
+ }
617
622
 
618
- // Write skill file (always overwrite to ensure fix is applied)
619
- fs.writeFileSync(skillFile, content, 'utf8');
623
+ // Convert each command to skill format
624
+ // commands/ralph-loop.md -> skills/ralph-loop/SKILL.md
625
+ const commands = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
626
+ for (const cmdFile of commands) {
627
+ const skillName = cmdFile.replace('.md', '');
628
+ const skillDir = path.join(skillsDir, skillName);
629
+ const skillFile = path.join(skillDir, 'SKILL.md');
630
+
631
+ // Create skill directory
632
+ if (!fs.existsSync(skillDir)) {
633
+ fs.mkdirSync(skillDir, { recursive: true });
634
+ }
635
+
636
+ // Read command file content
637
+ const cmdPath = path.join(commandsDir, cmdFile);
638
+ let content = fs.readFileSync(cmdPath, 'utf8');
639
+
640
+ // Fix frontmatter: replace hide-from-slash-command-tool with name
641
+ content = content.replace(
642
+ /hide-from-slash-command-tool:\s*["']true["']/g,
643
+ `name: ${skillName}`
644
+ );
645
+
646
+ // Write skill file (always overwrite to ensure fix is applied)
647
+ fs.writeFileSync(skillFile, content, 'utf8');
648
+ }
620
649
  }
621
650
  }
622
651
  }