@lifeaitools/rdc-skills 0.9.17 → 0.9.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.9.17",
3
+ "version": "0.9.19",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -6,12 +6,14 @@
6
6
  * node scripts/install-rdc-skills.js ← standard
7
7
  * node scripts/install-rdc-skills.js --skip-hooks ← skip hook wiring
8
8
  * node scripts/install-rdc-skills.js --claude-home <path> ← custom CLI home
9
+ * node scripts/install-rdc-skills.js --codex-root <path> ← also install to .agents/skills/user/
9
10
  * node scripts/install-rdc-skills.js --migrate <path> ← migrate docs/ → .rdc/
10
11
  *
11
12
  * What it does:
12
13
  * 1. git pull (latest commands + guides)
13
14
  * 2. CLI plugin — registers in ~/.claude/plugins/ + settings.json
14
15
  * 3. Cowork — registers in Desktop cowork_plugins/ + cowork_settings.json
16
+ * 3.5 Codex — copies skills to <project>/.agents/skills/user/rdc-<name>/
15
17
  * 4. Hook files — copies hooks/*.js → ~/.claude/hooks/
16
18
  * 5. Hook wiring — wires hooks into ~/.claude/settings.json
17
19
  * 6. Zip — builds dist/rdc-skills-plugin.zip for claude.ai / distribution
@@ -36,6 +38,14 @@ const doMigrate = migrateIdx >= 0;
36
38
  const migratePath = doMigrate ? (args[migrateIdx + 1] || process.cwd()) : null;
37
39
 
38
40
  const repoRoot = path.resolve(__dirname, '..');
41
+
42
+ const codexIdx = args.indexOf('--codex-root');
43
+ const codexRoot = codexIdx >= 0
44
+ ? path.resolve(args[codexIdx + 1])
45
+ : (() => {
46
+ const sibling = path.resolve(repoRoot, '..', 'regen-root');
47
+ return fs.existsSync(path.join(sibling, '.agents')) ? sibling : null;
48
+ })();
39
49
  const hooksSrc = path.join(repoRoot, 'hooks');
40
50
  const hooksDst = path.join(claudeHome, 'hooks');
41
51
  const settingsPath = path.join(claudeHome, 'settings.json');
@@ -342,6 +352,43 @@ function registerCowork(version, gitSha) {
342
352
  return bases.length;
343
353
  }
344
354
 
355
+ // ── Codex registration (→ <project>/.agents/skills/user/rdc-*/) ─────────────
356
+ function registerCodex(codexProjectRoot) {
357
+ const targetDir = path.join(codexProjectRoot, '.agents', 'skills', 'user');
358
+ fs.mkdirSync(targetDir, { recursive: true });
359
+
360
+ // Clean: remove dirs that are rdc skills — by prefix OR by frontmatter name
361
+ let removed = 0;
362
+ for (const entry of fs.readdirSync(targetDir, { withFileTypes: true })) {
363
+ if (!entry.isDirectory()) continue;
364
+ const candidate = path.join(targetDir, entry.name);
365
+ if (/^rdc-/.test(entry.name)) {
366
+ fs.rmSync(candidate, { recursive: true, force: true });
367
+ removed++;
368
+ } else {
369
+ const fm = readFrontmatter(path.join(candidate, 'SKILL.md'));
370
+ if (fm.name && fm.name.startsWith('rdc:')) {
371
+ fs.rmSync(candidate, { recursive: true, force: true });
372
+ removed++;
373
+ }
374
+ }
375
+ }
376
+
377
+ // Copy: each source skill dir that has a SKILL.md → rdc-<name>/
378
+ const skillsSrc = path.join(repoRoot, 'skills');
379
+ let copied = 0;
380
+ for (const entry of fs.readdirSync(skillsSrc, { withFileTypes: true })) {
381
+ if (!entry.isDirectory()) continue;
382
+ const skillFile = path.join(skillsSrc, entry.name, 'SKILL.md');
383
+ if (!fs.existsSync(skillFile)) continue;
384
+ const dst = path.join(targetDir, `rdc-${entry.name}`);
385
+ copyDirRecursive(path.join(skillsSrc, entry.name), dst);
386
+ copied++;
387
+ }
388
+
389
+ return { removed, copied };
390
+ }
391
+
345
392
  // ── Step 6: Zip for claude.ai / distribution ─────────────────────────────────
346
393
  function buildZip(version) {
347
394
  const distDir = path.join(repoRoot, 'dist');
@@ -582,6 +629,52 @@ async function main() {
582
629
  warn('[2/6] Cowork — no Desktop workspaces found (open Claude Desktop once to create them)');
583
630
  }
584
631
 
632
+ // 2.5. Codex registration
633
+ if (codexRoot) {
634
+ const { removed, copied } = registerCodex(codexRoot);
635
+ const codexTarget = path.join(codexRoot, '.agents', 'skills', 'user');
636
+ ok(`[2.5] Codex — ${copied} skill(s) installed, ${removed} stale removed`);
637
+ info(` target : ${codexTarget}`);
638
+ } else {
639
+ info('[2.5] Codex — skipped (no .agents/ found; use --codex-root <path>)');
640
+ }
641
+
642
+ // 2.7. Symlinks in regen-root/.claude/skills/ (FS MCP + claude.ai access)
643
+ if (codexRoot) {
644
+ const skillsLinkDir = path.join(codexRoot, '.claude', 'skills');
645
+ const skillsSrc = path.join(repoRoot, 'skills');
646
+ fs.mkdirSync(skillsLinkDir, { recursive: true });
647
+ let linked = 0;
648
+ for (const entry of fs.readdirSync(skillsSrc, { withFileTypes: true })) {
649
+ if (!entry.isDirectory()) continue;
650
+ if (!fs.existsSync(path.join(skillsSrc, entry.name, 'SKILL.md'))) continue;
651
+ const linkPath = path.join(skillsLinkDir, entry.name);
652
+ const target = path.join(skillsSrc, entry.name);
653
+ try {
654
+ if (fs.existsSync(linkPath) || (() => { try { fs.lstatSync(linkPath); return true; } catch { return false; } })()) {
655
+ fs.rmSync(linkPath, { recursive: true, force: true });
656
+ }
657
+ } catch {}
658
+ try {
659
+ if (process.platform === 'win32') {
660
+ const winLink = linkPath.replace(/\//g, '\\');
661
+ const winTarget = target.replace(/\//g, '\\');
662
+ execSync(`cmd /c mklink /J "${winLink}" "${winTarget}"`, { stdio: 'pipe' });
663
+ } else {
664
+ fs.symlinkSync(target, linkPath, 'dir');
665
+ }
666
+ linked++;
667
+ } catch {}
668
+ }
669
+ if (linked > 0) {
670
+ ok(`[2.7] Symlinks — ${linked} skill link(s) in ${skillsLinkDir}`);
671
+ } else {
672
+ info('[2.7] Symlinks — no rdc skill links created (skills may already be linked)');
673
+ }
674
+ } else {
675
+ info('[2.7] Symlinks — skipped (no codex root found)');
676
+ }
677
+
585
678
  // 3. Hook files
586
679
  const hookCount = copyDir(hooksSrc, hooksDst, '.js');
587
680
  ok(`[3/6] Hook files — ${hookCount} file(s) → ${hooksDst}`);