@lifeaitools/rdc-skills 0.17.1 → 0.18.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdc",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight unattended builds with work-item tracking and TDD enforcement.",
5
5
  "author": {
6
6
  "name": "LIFEAI",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -52,9 +52,19 @@ const codexIdx = args.indexOf('--codex-root');
52
52
  const codexRoot = codexIdx >= 0
53
53
  ? path.resolve(args[codexIdx + 1])
54
54
  : (() => {
55
- if (projectRootArg) return null;
56
- const sibling = path.resolve(repoRoot, '..', 'regen-root');
57
- return fs.existsSync(path.join(sibling, '.agents')) ? sibling : null;
55
+ // Auto-detect the consuming project's .agents tree so a plain `install`
56
+ // refreshes Codex without needing --codex-root. Check, in order: an
57
+ // explicit --project-root, the current working directory, then the
58
+ // regen-root sibling of this repo. First one with a `.agents` wins.
59
+ const candidates = [
60
+ projectRootArg ? path.resolve(projectRootArg) : null,
61
+ process.cwd(),
62
+ path.resolve(repoRoot, '..', 'regen-root'),
63
+ ].filter(Boolean);
64
+ for (const c of candidates) {
65
+ if (fs.existsSync(path.join(c, '.agents'))) return c;
66
+ }
67
+ return null;
58
68
  })();
59
69
  const codexSkillDirIdx = args.indexOf('--codex-skill-dir');
60
70
  const explicitCodexSkillDir = codexSkillDirIdx >= 0
@@ -117,7 +127,13 @@ function copyDirRecursive(src, dst) {
117
127
  const s = path.join(src, entry.name);
118
128
  const d = path.join(dst, entry.name);
119
129
  if (entry.isDirectory()) copyDirRecursive(s, d);
120
- else fs.copyFileSync(s, d);
130
+ else {
131
+ // Atomic write (temp + rename) so a live Claude Code / Codex session never
132
+ // reads a half-written skill file when the installer runs over a live box.
133
+ const tmp = `${d}.tmp-${process.pid}`;
134
+ fs.copyFileSync(s, tmp);
135
+ fs.renameSync(tmp, d);
136
+ }
121
137
  }
122
138
  }
123
139
 
@@ -507,6 +523,46 @@ function addCodexTarget(targets, label, targetDir) {
507
523
  targets.push({ label, targetDir: resolved });
508
524
  }
509
525
 
526
+ // Register the rdc-skills MCP endpoint at the USER/GLOBAL level for every client
527
+ // so all Claude Code projects and all Codex sessions can reach the skills via MCP
528
+ // (not just where a project .mcp.json exists). Idempotent + non-fatal. Mirrors the
529
+ // existing clauth/codeflow entries exactly. claude.ai web still needs the one-time
530
+ // connector add in its UI (no programmatic API).
531
+ function registerMcpEndpoints() {
532
+ const MCP_URL = 'https://rdc-skills.regendevcorp.com/mcp';
533
+ const out = [];
534
+
535
+ // Claude Code — user-level ~/.claude.json mcpServers (covers EVERY project).
536
+ try {
537
+ const claudeJson = path.join(os.homedir(), '.claude.json');
538
+ if (fs.existsSync(claudeJson)) {
539
+ const data = readJson(claudeJson);
540
+ if (!data.mcpServers || typeof data.mcpServers !== 'object') data.mcpServers = {};
541
+ const cur = data.mcpServers['rdc-skills'];
542
+ if (!cur || cur.url !== MCP_URL) {
543
+ data.mcpServers['rdc-skills'] = { type: 'http', url: MCP_URL };
544
+ writeJson(claudeJson, data, 2);
545
+ out.push('claude(~/.claude.json)');
546
+ }
547
+ }
548
+ } catch (e) { out.push(`claude WARN:${e.message}`); }
549
+
550
+ // Codex — append [mcp_servers.rdc-skills] to ~/.codex/config.toml if absent.
551
+ try {
552
+ const codexToml = path.join(os.homedir(), '.codex', 'config.toml');
553
+ if (fs.existsSync(codexToml)) {
554
+ const toml = fs.readFileSync(codexToml, 'utf8');
555
+ if (!/\[mcp_servers\.rdc-skills\]/.test(toml)) {
556
+ const block = `\n[mcp_servers.rdc-skills]\nurl = '${MCP_URL}'\n`;
557
+ fs.writeFileSync(codexToml, toml.replace(/\s*$/, '\n') + block);
558
+ out.push('codex(~/.codex/config.toml)');
559
+ }
560
+ }
561
+ } catch (e) { out.push(`codex WARN:${e.message}`); }
562
+
563
+ return out;
564
+ }
565
+
510
566
  function findCodexTargets() {
511
567
  const targets = [];
512
568
  if (codexRoot) {
@@ -918,6 +974,15 @@ async function main() {
918
974
  info('[2.5] Codex — skipped (no Codex skill dirs found; use --codex-root or --codex-skill-dir)');
919
975
  }
920
976
 
977
+ // 2.6. Register the rdc-skills MCP endpoint globally (Claude Code + Codex) so
978
+ // EVERY agent can reach the skills via MCP, not only where a project .mcp.json exists.
979
+ const mcpReg = registerMcpEndpoints();
980
+ if (mcpReg.length > 0) {
981
+ ok(`[2.6] MCP — registered rdc-skills endpoint: ${mcpReg.join(', ')}`);
982
+ } else {
983
+ info('[2.6] MCP — rdc-skills endpoint already registered (claude + codex)');
984
+ }
985
+
921
986
  // 2.7. Symlinks in regen-root/.claude/skills/ (FS MCP + claude.ai access)
922
987
  if (codexRoot) {
923
988
  const skillsLinkDir = path.join(codexRoot, '.claude', 'skills');