@hanzlaa/rcode 3.2.0 → 3.3.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.
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Install-time generator: skill stubs that mirror slash commands.
4
+ *
5
+ * WHY: VS Code's Claude Code extension lists `.claude/skills/` in its
6
+ * sidebar, but slash commands at `.claude/commands/rihal/` are only
7
+ * reachable via the `/` autocomplete. Users coming from GSD (which ships
8
+ * a skill per command) expect to see lifecycle commands like `rihal-do`
9
+ * in the sidebar.
10
+ *
11
+ * This script creates ONE skill stub per slash command at install time,
12
+ * unless a real skill with the same name already exists at the source.
13
+ * The stubs live at the install destination only (`.claude/skills/`) —
14
+ * they are NEVER committed to the rcode source tree. That keeps the
15
+ * source codebase free of duplication while letting the sidebar feel
16
+ * full.
17
+ *
18
+ * Each generated stub is marked with `generated: true` and
19
+ * `generated-by: rcode-install` in frontmatter so it can be detected
20
+ * and refreshed on subsequent installs without confusing real skills.
21
+ *
22
+ * Run: node scripts/generate-command-skills.cjs <package-root> <target-skills-dir>
23
+ * (called from cli/install.js)
24
+ */
25
+
26
+ const fs = require('fs');
27
+ const path = require('path');
28
+
29
+ /**
30
+ * Curated list of commands that get skill stubs. Not every command
31
+ * deserves a sidebar entry — only the user-facing entry points and
32
+ * lifecycle verbs. Internal sub-commands stay slash-only.
33
+ */
34
+ const SIDEBAR_COMMANDS = new Set([
35
+ 'do', 'status', 'progress', 'next', 'plan', 'execute',
36
+ 'council', 'discuss', 'ship', 'audit', 'autonomous',
37
+ 'session-report', 'forensics', 'health', 'debug',
38
+ 'verify-phase', 'verify-work', 'review', 'code-review',
39
+ 'new-project', 'new-milestone', 'milestone-summary',
40
+ 'note', 'add-todo', 'check-todos', 'pause-work', 'resume-work',
41
+ ]);
42
+
43
+ function parseFrontmatter(text) {
44
+ if (!text.startsWith('---\n')) return {};
45
+ const end = text.indexOf('\n---\n', 4);
46
+ if (end === -1) return {};
47
+ const block = text.slice(4, end);
48
+ const fm = {};
49
+ for (const raw of block.split('\n')) {
50
+ const m = raw.match(/^([a-zA-Z_-]+):\s*(.+)$/);
51
+ if (m) fm[m[1].trim()] = m[2].trim().replace(/^["']|["']$/g, '');
52
+ }
53
+ return fm;
54
+ }
55
+
56
+ function discoverRealSkills(packageRoot) {
57
+ const out = new Set();
58
+ const buckets = ['core', 'agents'];
59
+ for (const bucket of buckets) {
60
+ const dir = path.join(packageRoot, 'rihal', 'skills', bucket);
61
+ if (!fs.existsSync(dir)) continue;
62
+ for (const entry of fs.readdirSync(dir)) {
63
+ if (entry.startsWith('rihal-')) out.add(entry);
64
+ }
65
+ }
66
+ // actions are nested by phase
67
+ const actionsDir = path.join(packageRoot, 'rihal', 'skills', 'actions');
68
+ if (fs.existsSync(actionsDir)) {
69
+ for (const phase of fs.readdirSync(actionsDir)) {
70
+ const phaseDir = path.join(actionsDir, phase);
71
+ if (!fs.statSync(phaseDir).isDirectory()) continue;
72
+ for (const entry of fs.readdirSync(phaseDir)) {
73
+ if (entry.startsWith('rihal-')) out.add(entry);
74
+ }
75
+ }
76
+ }
77
+ return out;
78
+ }
79
+
80
+ function generateStub(cmdName, commandFm, version) {
81
+ const desc = commandFm.description || `Slash command shortcut for /rihal:${cmdName}.`;
82
+ const triggers = [
83
+ `rihal ${cmdName}`,
84
+ `rihal:${cmdName}`,
85
+ `/rihal:${cmdName}`,
86
+ ];
87
+
88
+ return `---
89
+ name: rihal-${cmdName}
90
+ description: >
91
+ ${desc.replace(/\n/g, ' ')}
92
+ Sidebar entry — invokes the same workflow as /rihal:${cmdName}.
93
+ triggers:
94
+ ${triggers.map((t) => ` - "${t}"`).join('\n')}
95
+ user-invocable: true
96
+ generated: true
97
+ generated-by: rcode-install-v${version}
98
+ source: rihal/commands/${cmdName}.md
99
+ ---
100
+
101
+ <!--
102
+ AUTO-GENERATED at install time by scripts/generate-command-skills.cjs.
103
+ Do NOT edit this file directly — your changes will be overwritten on the next
104
+ install or update. To customise, create a sibling \`.local.md\` file (which
105
+ is preserved across installs) or modify the source command at
106
+ rihal/commands/${cmdName}.md.
107
+
108
+ This stub exists so the slash command /rihal:${cmdName} appears in VS Code's
109
+ Claude Code sidebar (which lists skills only, not slash commands). The
110
+ behaviour is identical to /rihal:${cmdName} — both invoke the workflow at
111
+ .rihal/workflows/${cmdName}.md.
112
+ -->
113
+
114
+ ## Overview
115
+
116
+ Sidebar entry for the \`/rihal:${cmdName}\` slash command. Phrase-activated alternative invocation route.
117
+
118
+ ## Workflow
119
+
120
+ Read and execute \`@.rihal/workflows/${cmdName}.md\` end-to-end. The behaviour is the same as invoking \`/rihal:${cmdName}\` directly.
121
+
122
+ ## Output Format
123
+
124
+ Identical to \`/rihal:${cmdName}\`. See the workflow file for the canonical output spec.
125
+
126
+ ## Examples
127
+
128
+ **Happy path** — say "rihal ${cmdName}" or "/rihal:${cmdName}" → workflow runs identically either way.
129
+
130
+ **Negative — looking for the canonical command file** — see \`rihal/commands/${cmdName}.md\` (the source of truth) and \`rihal/workflows/${cmdName}.md\` (the orchestration logic).
131
+
132
+ ## Memory Bank Hooks
133
+
134
+ - **Reads:** whatever \`.rihal/workflows/${cmdName}.md\` reads
135
+ - **Writes:** whatever the workflow writes
136
+ - This stub itself is read-only — it just dispatches to the workflow.
137
+ `;
138
+ }
139
+
140
+ function main(packageRoot, targetSkillsDir, version) {
141
+ if (!fs.existsSync(targetSkillsDir)) {
142
+ fs.mkdirSync(targetSkillsDir, { recursive: true });
143
+ }
144
+
145
+ const realSkills = discoverRealSkills(packageRoot);
146
+ const commandsDir = path.join(packageRoot, 'rihal', 'commands');
147
+ if (!fs.existsSync(commandsDir)) {
148
+ console.warn(`[generate-command-skills] commands dir not found: ${commandsDir}`);
149
+ return { generated: 0, skipped: 0 };
150
+ }
151
+
152
+ let generated = 0;
153
+ let skipped = 0;
154
+
155
+ for (const file of fs.readdirSync(commandsDir)) {
156
+ if (!file.endsWith('.md')) continue;
157
+ if (file.startsWith('_')) continue; // internal aliases / metadata
158
+ const cmdName = file.replace(/\.md$/, '');
159
+ if (!SIDEBAR_COMMANDS.has(cmdName)) { skipped++; continue; }
160
+
161
+ const skillName = `rihal-${cmdName}`;
162
+ if (realSkills.has(skillName)) {
163
+ // A real skill with this name exists in the source tree — don't shadow it
164
+ skipped++;
165
+ continue;
166
+ }
167
+
168
+ const cmdPath = path.join(commandsDir, file);
169
+ const cmdText = fs.readFileSync(cmdPath, 'utf8');
170
+ const cmdFm = parseFrontmatter(cmdText);
171
+
172
+ const stubDir = path.join(targetSkillsDir, skillName);
173
+ const stubFile = path.join(stubDir, 'SKILL.md');
174
+
175
+ // Idempotency: only overwrite if the file is missing OR is a previously
176
+ // generated stub (has the marker). Never clobber a user's hand-edited file.
177
+ if (fs.existsSync(stubFile)) {
178
+ const existing = fs.readFileSync(stubFile, 'utf8');
179
+ if (!/^generated:\s*true/m.test(existing)) {
180
+ skipped++;
181
+ continue;
182
+ }
183
+ }
184
+
185
+ fs.mkdirSync(stubDir, { recursive: true });
186
+ fs.writeFileSync(stubFile, generateStub(cmdName, cmdFm, version), 'utf8');
187
+ generated++;
188
+ }
189
+
190
+ return { generated, skipped };
191
+ }
192
+
193
+ if (require.main === module) {
194
+ const [packageRoot, targetSkillsDir, version = '0.0.0'] = process.argv.slice(2);
195
+ if (!packageRoot || !targetSkillsDir) {
196
+ console.error('Usage: generate-command-skills.cjs <package-root> <target-skills-dir> [version]');
197
+ process.exit(2);
198
+ }
199
+ const { generated, skipped } = main(packageRoot, targetSkillsDir, version);
200
+ console.log(`✓ ${generated} sidebar skill stub${generated === 1 ? '' : 's'} generated, ${skipped} skipped (already real skills or out of curated set)`);
201
+ }
202
+
203
+ module.exports = { main, SIDEBAR_COMMANDS };
package/cli/install.js CHANGED
@@ -415,8 +415,33 @@ function getPathsForIde(ide, target) {
415
415
  referencesDir: path.join(target, '.rihal', 'references'),
416
416
  binDir: path.join(target, '.rihal', 'bin'),
417
417
  };
418
+ case 'vscode':
419
+ // VS Code's Claude Code / Continue / Copilot extensions all read from
420
+ // .claude/ (Claude Code's canonical paths). We install there directly
421
+ // and additionally write a .vscode/rihal/ marker so VS Code workspace
422
+ // settings can pin behaviour.
423
+ return {
424
+ agentsDir: path.join(target, '.claude', 'agents'),
425
+ commandsDir: path.join(target, '.claude', 'commands', 'rihal'),
426
+ workflowsDir: path.join(target, '.rihal', 'workflows'),
427
+ referencesDir: path.join(target, '.rihal', 'references'),
428
+ binDir: path.join(target, '.rihal', 'bin'),
429
+ markerDir: path.join(target, '.vscode', 'rihal'),
430
+ };
431
+ case 'antigravity':
432
+ // Antigravity (Google's agentic IDE) — install to .antigravity/ mirroring
433
+ // the .gemini/ structure. Antigravity's plugin protocol is still firming
434
+ // up; the user can adjust paths via .rihal/config.yaml's `extra_install_paths`
435
+ // if Antigravity expects different routing.
436
+ return {
437
+ agentsDir: path.join(target, '.antigravity', 'rihal', 'agents'),
438
+ commandsDir: path.join(target, '.antigravity', 'rihal', 'commands'),
439
+ workflowsDir: path.join(target, '.rihal', 'workflows'),
440
+ referencesDir: path.join(target, '.rihal', 'references'),
441
+ binDir: path.join(target, '.rihal', 'bin'),
442
+ };
418
443
  default:
419
- throw new Error(`Unknown IDE: ${ide}. Supported: claude, cursor, gemini`);
444
+ throw new Error(`Unknown IDE: ${ide}. Supported: claude, cursor, gemini, vscode, antigravity`);
420
445
  }
421
446
  }
422
447
 
@@ -1231,27 +1256,28 @@ async function install(opts) {
1231
1256
  }
1232
1257
 
1233
1258
  // Validate IDE — structured error for unsupported editors (#197).
1234
- if (!['claude', 'cursor', 'gemini'].includes(opts.ide)) {
1259
+ if (!['claude', 'cursor', 'gemini', 'vscode', 'antigravity'].includes(opts.ide)) {
1235
1260
  console.error(`✖ --ide ${opts.ide} is not supported in v${readPackageVersion()}.`);
1236
1261
  console.error('');
1237
1262
  console.error(' Currently supported:');
1238
- console.error(' claude — Claude Code native (recommended)');
1239
- console.error(' cursor — Cursor IDE');
1240
- console.error(' gemini — Gemini CLI');
1263
+ console.error(' claude — Claude Code native (recommended)');
1264
+ console.error(' cursor — Cursor IDE');
1265
+ console.error(' gemini — Gemini CLI');
1266
+ console.error(' vscode — VS Code (with Claude Code / Continue / Copilot extension)');
1267
+ console.error(' antigravity — Antigravity (experimental)');
1241
1268
  console.error('');
1242
- console.error(' Tracked for v3.0 (see issue #182):');
1243
- console.error(' vscodeVS Code native extension');
1244
- console.error(' jetbrains IntelliJ / PyCharm');
1245
- console.error(' zed — Zed editor');
1269
+ console.error(' Tracked for future:');
1270
+ console.error(' jetbrainsIntelliJ / PyCharm');
1271
+ console.error(' zed Zed editor');
1246
1272
  console.error('');
1247
- if (/^(vscode|vs-code|code)$/i.test(opts.ide)) {
1248
- console.error(' Workaround: if you use VS Code WITH the Claude Code extension,');
1249
- console.error(' run `--ide claude` — the extension reads from .claude/ too.');
1250
- console.error('');
1251
- }
1252
1273
  return 1;
1253
1274
  }
1254
1275
 
1276
+ // VS Code installs to .claude/ paths (extension reads from there). Inform the user.
1277
+ if (opts.ide === 'vscode') {
1278
+ console.log(' ' + dim('VS Code → installing to .claude/ paths (read by Claude Code / Continue / Copilot extensions).'));
1279
+ }
1280
+
1255
1281
  // Gemini IDE support deferred
1256
1282
  if (opts.ide === 'gemini') {
1257
1283
  console.log(`\n⚠️ Gemini CLI install not yet implemented\n`);
@@ -1261,6 +1287,12 @@ async function install(opts) {
1261
1287
  return 1;
1262
1288
  }
1263
1289
 
1290
+ // Antigravity install is experimental — best-effort path, user may need to adjust
1291
+ if (opts.ide === 'antigravity') {
1292
+ console.log(' ' + warn('Antigravity install is experimental. Files land at .antigravity/rihal/{agents,commands}/.'));
1293
+ console.log(' ' + dim('If Antigravity expects a different path, adjust .rihal/config.yaml and re-run.'));
1294
+ }
1295
+
1264
1296
  // Validate requested modules exist
1265
1297
  if (opts.modules.length > 0) {
1266
1298
  const available = listAvailableModules();
@@ -1587,7 +1619,24 @@ async function install(opts) {
1587
1619
 
1588
1620
  // Install v1-style phrase-activated skills (scaffold-project, create-prd,
1589
1621
  // retrospective, etc.) into .claude/skills/ alongside the v2 agents/commands.
1590
- const skillsInstalled = installSkills(PACKAGE_ROOT, opts.target);
1622
+ let skillsInstalled = installSkills(PACKAGE_ROOT, opts.target);
1623
+
1624
+ // Generate install-time skill stubs that mirror sidebar-worthy slash commands.
1625
+ // Source codebase stays clean — these stubs only exist at the install
1626
+ // destination, marked with `generated: true` so they refresh idempotently.
1627
+ // See cli/generate-command-skills.cjs for rationale.
1628
+ try {
1629
+ const { main: generateCommandSkills } = require(path.join(PACKAGE_ROOT, 'cli', 'generate-command-skills.cjs'));
1630
+ const stubsDir = path.join(opts.target, '.claude', 'skills');
1631
+ const result = generateCommandSkills(PACKAGE_ROOT, stubsDir, readPackageVersion());
1632
+ if (result.generated > 0) {
1633
+ console.log(' ' + dim(`${result.generated} sidebar skill stub${result.generated === 1 ? '' : 's'} generated for command discoverability`));
1634
+ skillsInstalled += result.generated;
1635
+ }
1636
+ } catch (err) {
1637
+ // Non-fatal: install succeeds without sidebar stubs
1638
+ console.log(' ' + dim(`(sidebar stub generation skipped: ${err.message})`));
1639
+ }
1591
1640
 
1592
1641
  // Seed .planning/ with starter ROADMAP + STATE so workflows work immediately
1593
1642
  const starterSeeded = seedStarterPlanning(opts.target, opts.projectName);
@@ -1667,16 +1716,19 @@ async function install(opts) {
1667
1716
  console.log('');
1668
1717
  }
1669
1718
 
1670
- // Count installed agents + commands dynamically (#190).
1671
- const agentsDir = path.join(opts.target, '.claude', 'agents');
1672
- const commandsDir = path.join(opts.target, '.claude', 'commands', 'rihal');
1719
+ // Count installed agents + commands dynamically (#190). Reads from the
1720
+ // IDE-specific install paths so cursor/gemini/vscode/antigravity don't
1721
+ // false-fail the health check.
1722
+ const idePaths = getPathsForIde(opts.ide, opts.target);
1723
+ const agentsDir = idePaths.agentsDir;
1724
+ const commandsDir = idePaths.commandsDir;
1673
1725
  let agentCount = 0, commandCount = 0;
1674
1726
  try {
1675
1727
  if (fs.existsSync(agentsDir)) {
1676
- agentCount = fs.readdirSync(agentsDir).filter(f => f.startsWith('rihal-') && f.endsWith('.md')).length;
1728
+ agentCount = fs.readdirSync(agentsDir).filter(f => (f.startsWith('rihal-') || f.startsWith('rcode-')) && (f.endsWith('.md') || f.endsWith('.mdc'))).length;
1677
1729
  }
1678
1730
  if (fs.existsSync(commandsDir)) {
1679
- commandCount = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md')).length;
1731
+ commandCount = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md') || f.endsWith('.mdc')).length;
1680
1732
  }
1681
1733
  } catch {}
1682
1734
 
@@ -1688,9 +1740,12 @@ async function install(opts) {
1688
1740
  console.log(` ${bold('Mode:')} ${opts.mode} ${dim('(guided=confirm at gates, yolo=autonomous)')}`);
1689
1741
  console.log(` ${bold('Planning:')} ${opts.commitPlanning !== false ? 'committed' : 'gitignored'} ${dim('(flip: rihal-tools gitignore refresh)')}`);
1690
1742
  console.log('');
1691
- console.log(` ${bold('Agents:')} ${pc.green(String(agentCount))} in .claude/agents/`);
1692
- console.log(` ${bold('Commands:')} ${pc.green(String(commandCount))} slash commands in .claude/commands/rihal/`);
1693
- if (skillsInstalled > 0) console.log(` ${bold('Skills:')} ${pc.green(String(skillsInstalled))} phrase-activated in .claude/skills/`);
1743
+ // Show the actual install paths so cursor/gemini/antigravity output is accurate
1744
+ const relAgents = path.relative(opts.target, idePaths.agentsDir) || idePaths.agentsDir;
1745
+ const relCommands = path.relative(opts.target, idePaths.commandsDir) || idePaths.commandsDir;
1746
+ console.log(` ${bold('Agents:')} ${pc.green(String(agentCount))} in ${relAgents}/`);
1747
+ console.log(` ${bold('Commands:')} ${pc.green(String(commandCount))} slash commands in ${relCommands}/`);
1748
+ if (skillsInstalled > 0) console.log(` ${bold('Skills:')} ${pc.green(String(skillsInstalled))} phrase-activated`);
1694
1749
  console.log('');
1695
1750
  if (starterSeeded) {
1696
1751
  console.log(' ' + ok('Starter planning scaffolded in .planning/ (ROADMAP, STATE, PROJECT)'));
package/dist/rcode.js CHANGED
@@ -16065,8 +16065,25 @@ Installs (IDE-specific):
16065
16065
  referencesDir: path2.join(target, ".rihal", "references"),
16066
16066
  binDir: path2.join(target, ".rihal", "bin")
16067
16067
  };
16068
+ case "vscode":
16069
+ return {
16070
+ agentsDir: path2.join(target, ".claude", "agents"),
16071
+ commandsDir: path2.join(target, ".claude", "commands", "rihal"),
16072
+ workflowsDir: path2.join(target, ".rihal", "workflows"),
16073
+ referencesDir: path2.join(target, ".rihal", "references"),
16074
+ binDir: path2.join(target, ".rihal", "bin"),
16075
+ markerDir: path2.join(target, ".vscode", "rihal")
16076
+ };
16077
+ case "antigravity":
16078
+ return {
16079
+ agentsDir: path2.join(target, ".antigravity", "rihal", "agents"),
16080
+ commandsDir: path2.join(target, ".antigravity", "rihal", "commands"),
16081
+ workflowsDir: path2.join(target, ".rihal", "workflows"),
16082
+ referencesDir: path2.join(target, ".rihal", "references"),
16083
+ binDir: path2.join(target, ".rihal", "bin")
16084
+ };
16068
16085
  default:
16069
- throw new Error(`Unknown IDE: ${ide}. Supported: claude, cursor, gemini`);
16086
+ throw new Error(`Unknown IDE: ${ide}. Supported: claude, cursor, gemini, vscode, antigravity`);
16070
16087
  }
16071
16088
  }
16072
16089
  function walkFiles(dir, extraIgnore = []) {
@@ -16700,26 +16717,25 @@ Say "plan a sprint" or run \`/rihal:sprint-planning\` to break Phase 01 into sto
16700
16717
  console.error(`\u2716 Source tree not found at ${SOURCE_ROOT}. Running from wrong dir?`);
16701
16718
  return 1;
16702
16719
  }
16703
- if (!["claude", "cursor", "gemini"].includes(opts.ide)) {
16720
+ if (!["claude", "cursor", "gemini", "vscode", "antigravity"].includes(opts.ide)) {
16704
16721
  console.error(`\u2716 --ide ${opts.ide} is not supported in v${readPackageVersion()}.`);
16705
16722
  console.error("");
16706
16723
  console.error(" Currently supported:");
16707
- console.error(" claude \u2014 Claude Code native (recommended)");
16708
- console.error(" cursor \u2014 Cursor IDE");
16709
- console.error(" gemini \u2014 Gemini CLI");
16724
+ console.error(" claude \u2014 Claude Code native (recommended)");
16725
+ console.error(" cursor \u2014 Cursor IDE");
16726
+ console.error(" gemini \u2014 Gemini CLI");
16727
+ console.error(" vscode \u2014 VS Code (with Claude Code / Continue / Copilot extension)");
16728
+ console.error(" antigravity \u2014 Antigravity (experimental)");
16710
16729
  console.error("");
16711
- console.error(" Tracked for v3.0 (see issue #182):");
16712
- console.error(" vscode \u2014 VS Code native extension");
16713
- console.error(" jetbrains \u2014 IntelliJ / PyCharm");
16714
- console.error(" zed \u2014 Zed editor");
16730
+ console.error(" Tracked for future:");
16731
+ console.error(" jetbrains \u2014 IntelliJ / PyCharm");
16732
+ console.error(" zed \u2014 Zed editor");
16715
16733
  console.error("");
16716
- if (/^(vscode|vs-code|code)$/i.test(opts.ide)) {
16717
- console.error(" Workaround: if you use VS Code WITH the Claude Code extension,");
16718
- console.error(" run `--ide claude` \u2014 the extension reads from .claude/ too.");
16719
- console.error("");
16720
- }
16721
16734
  return 1;
16722
16735
  }
16736
+ if (opts.ide === "vscode") {
16737
+ console.log(" " + dim("VS Code \u2192 installing to .claude/ paths (read by Claude Code / Continue / Copilot extensions)."));
16738
+ }
16723
16739
  if (opts.ide === "gemini") {
16724
16740
  console.log(`
16725
16741
  \u26A0\uFE0F Gemini CLI install not yet implemented
@@ -16731,6 +16747,10 @@ Say "plan a sprint" or run \`/rihal:sprint-planning\` to break Phase 01 into sto
16731
16747
  `);
16732
16748
  return 1;
16733
16749
  }
16750
+ if (opts.ide === "antigravity") {
16751
+ console.log(" " + warn("Antigravity install is experimental. Files land at .antigravity/rihal/{agents,commands}/."));
16752
+ console.log(" " + dim("If Antigravity expects a different path, adjust .rihal/config.yaml and re-run."));
16753
+ }
16734
16754
  if (opts.modules.length > 0) {
16735
16755
  const available = listAvailableModules();
16736
16756
  const unknownModules = opts.modules.filter((m) => !available.includes(m));
@@ -16995,7 +17015,18 @@ Say "plan a sprint" or run \`/rihal:sprint-planning\` to break Phase 01 into sto
16995
17015
  path2.join(configDir, "files-manifest.csv"),
16996
17016
  generateFilesManifest(plan, opts.target)
16997
17017
  );
16998
- const skillsInstalled = installSkills(PACKAGE_ROOT2, opts.target);
17018
+ let skillsInstalled = installSkills(PACKAGE_ROOT2, opts.target);
17019
+ try {
17020
+ const { main: generateCommandSkills } = require(path2.join(PACKAGE_ROOT2, "cli", "generate-command-skills.cjs"));
17021
+ const stubsDir = path2.join(opts.target, ".claude", "skills");
17022
+ const result = generateCommandSkills(PACKAGE_ROOT2, stubsDir, readPackageVersion());
17023
+ if (result.generated > 0) {
17024
+ console.log(" " + dim(`${result.generated} sidebar skill stub${result.generated === 1 ? "" : "s"} generated for command discoverability`));
17025
+ skillsInstalled += result.generated;
17026
+ }
17027
+ } catch (err) {
17028
+ console.log(" " + dim(`(sidebar stub generation skipped: ${err.message})`));
17029
+ }
16999
17030
  const starterSeeded = seedStarterPlanning(opts.target, opts.projectName);
17000
17031
  installBrainScaffold(PACKAGE_ROOT2, opts.target);
17001
17032
  const gitignoreReport = ensureRcodeGitignore(opts.target, { commitPlanning: opts.commitPlanning });
@@ -17059,15 +17090,16 @@ Say "plan a sprint" or run \`/rihal:sprint-planning\` to break Phase 01 into sto
17059
17090
  console.log(dim(" To overwrite: re-run with --force-overwrite | To see full diffs: --show-diff"));
17060
17091
  console.log("");
17061
17092
  }
17062
- const agentsDir = path2.join(opts.target, ".claude", "agents");
17063
- const commandsDir = path2.join(opts.target, ".claude", "commands", "rihal");
17093
+ const idePaths = getPathsForIde(opts.ide, opts.target);
17094
+ const agentsDir = idePaths.agentsDir;
17095
+ const commandsDir = idePaths.commandsDir;
17064
17096
  let agentCount = 0, commandCount = 0;
17065
17097
  try {
17066
17098
  if (fs2.existsSync(agentsDir)) {
17067
- agentCount = fs2.readdirSync(agentsDir).filter((f) => f.startsWith("rihal-") && f.endsWith(".md")).length;
17099
+ agentCount = fs2.readdirSync(agentsDir).filter((f) => (f.startsWith("rihal-") || f.startsWith("rcode-")) && (f.endsWith(".md") || f.endsWith(".mdc"))).length;
17068
17100
  }
17069
17101
  if (fs2.existsSync(commandsDir)) {
17070
- commandCount = fs2.readdirSync(commandsDir).filter((f) => f.endsWith(".md")).length;
17102
+ commandCount = fs2.readdirSync(commandsDir).filter((f) => f.endsWith(".md") || f.endsWith(".mdc")).length;
17071
17103
  }
17072
17104
  } catch {
17073
17105
  }
@@ -17079,9 +17111,11 @@ Say "plan a sprint" or run \`/rihal:sprint-planning\` to break Phase 01 into sto
17079
17111
  console.log(` ${bold("Mode:")} ${opts.mode} ${dim("(guided=confirm at gates, yolo=autonomous)")}`);
17080
17112
  console.log(` ${bold("Planning:")} ${opts.commitPlanning !== false ? "committed" : "gitignored"} ${dim("(flip: rihal-tools gitignore refresh)")}`);
17081
17113
  console.log("");
17082
- console.log(` ${bold("Agents:")} ${pc.green(String(agentCount))} in .claude/agents/`);
17083
- console.log(` ${bold("Commands:")} ${pc.green(String(commandCount))} slash commands in .claude/commands/rihal/`);
17084
- if (skillsInstalled > 0) console.log(` ${bold("Skills:")} ${pc.green(String(skillsInstalled))} phrase-activated in .claude/skills/`);
17114
+ const relAgents = path2.relative(opts.target, idePaths.agentsDir) || idePaths.agentsDir;
17115
+ const relCommands = path2.relative(opts.target, idePaths.commandsDir) || idePaths.commandsDir;
17116
+ console.log(` ${bold("Agents:")} ${pc.green(String(agentCount))} in ${relAgents}/`);
17117
+ console.log(` ${bold("Commands:")} ${pc.green(String(commandCount))} slash commands in ${relCommands}/`);
17118
+ if (skillsInstalled > 0) console.log(` ${bold("Skills:")} ${pc.green(String(skillsInstalled))} phrase-activated`);
17085
17119
  console.log("");
17086
17120
  if (starterSeeded) {
17087
17121
  console.log(" " + ok("Starter planning scaffolded in .planning/ (ROADMAP, STATE, PROJECT)"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzlaa/rcode",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "rcode — the memory bank for AI-driven SaaS teams. Persistent project context, distinctive engineering personas, and phase-based workflows. Built by Rihal. Works in Claude Code, Cursor, Gemini, VS Code, and Antigravity.",
5
5
  "main": "cli/index.js",
6
6
  "bin": {