@hanzlaa/rcode 3.4.17 → 3.4.18

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/cli/index.js CHANGED
@@ -91,9 +91,56 @@ Documentation: https://github.com/hanzlahabib/rihal-code
91
91
  `.trim());
92
92
  }
93
93
 
94
+ /**
95
+ * npm 10+ suppresses postinstall script output during global installs, so users
96
+ * who run `npm install -g @hanzlaa/rcode` see only "added 1 package" with no
97
+ * confirmation that 100+ commands and skills were installed. We detect a fresh
98
+ * install on the first `rcode <anything>` invocation by checking for a marker
99
+ * file under ~/.rihal/, print a one-time welcome banner, then drop the marker.
100
+ */
101
+ function maybeShowFirstRunBanner() {
102
+ const os = require('os');
103
+ const home = os.homedir();
104
+ const markerDir = path.join(home, '.rihal');
105
+ const marker = path.join(markerDir, '.welcome-shown');
106
+ if (fs.existsSync(marker)) return;
107
+
108
+ // Only show banner if global install actually ran — i.e. ~/.claude/commands/
109
+ // has rihal-*.md files. Otherwise this is a developer running from source.
110
+ const globalCommands = path.join(home, '.claude', 'commands');
111
+ let hasGlobalRihal = false;
112
+ try {
113
+ hasGlobalRihal = fs.existsSync(globalCommands) &&
114
+ fs.readdirSync(globalCommands).some(f => f.startsWith('rihal-') && f.endsWith('.md'));
115
+ } catch { /* unreadable */ }
116
+ if (!hasGlobalRihal) return;
117
+
118
+ console.log(`\nšŸ•Œ Rihal Code v${PACKAGE_JSON.version} — first run detected.\n`);
119
+ console.log(` āœ“ ${countGlobalRihal(globalCommands)} slash commands installed → ~/.claude/commands/`);
120
+ console.log(` āœ“ All /rihal-* commands available in every Claude Code project.`);
121
+ console.log(`\n To set up a project: cd my-project && rcode install`);
122
+ console.log(` Show all commands: rcode help`);
123
+ console.log(` Diagnose issues: rcode doctor\n`);
124
+
125
+ try {
126
+ fs.mkdirSync(markerDir, { recursive: true });
127
+ fs.writeFileSync(marker, `installed ${PACKAGE_JSON.version} at ${new Date().toISOString()}\n`);
128
+ } catch { /* if we can't write the marker, banner shows again next time — annoying but not broken */ }
129
+ }
130
+
131
+ function countGlobalRihal(dir) {
132
+ try {
133
+ return fs.readdirSync(dir).filter(f => f.startsWith('rihal-') && f.endsWith('.md')).length;
134
+ } catch { return 0; }
135
+ }
136
+
94
137
  async function main() {
95
138
  const [, , command = 'help', ...args] = process.argv;
96
139
 
140
+ // Show first-run banner before dispatching — npm hides postinstall output,
141
+ // so this is the user's first visible confirmation that the install worked.
142
+ maybeShowFirstRunBanner();
143
+
97
144
  const handler = COMMANDS[command];
98
145
  if (!handler) {
99
146
  console.error(`Unknown command: ${command}`);
package/cli/install.js CHANGED
@@ -177,6 +177,13 @@ function parseArgs(argv) {
177
177
  opts.target = path.resolve(positional[0]);
178
178
  opts.targetProvided = true;
179
179
  }
180
+ // --global without an explicit target means "install to ~/.claude/" — i.e.
181
+ // home dir. Without this, running `rcode install --global` from inside a
182
+ // project directory wrote rihal artifacts to that project, not to the user's
183
+ // home where Claude Code reads global commands from.
184
+ if (opts.global && !opts.targetProvided) {
185
+ opts.target = os.homedir();
186
+ }
180
187
  if (!opts.projectName) opts.projectName = path.basename(opts.target);
181
188
  return opts;
182
189
  }
package/dist/rcode.js CHANGED
@@ -15063,6 +15063,9 @@ var require_install = __commonJS({
15063
15063
  opts.target = path2.resolve(positional[0]);
15064
15064
  opts.targetProvided = true;
15065
15065
  }
15066
+ if (opts.global && !opts.targetProvided) {
15067
+ opts.target = os.homedir();
15068
+ }
15066
15069
  if (!opts.projectName) opts.projectName = path2.basename(opts.target);
15067
15070
  return opts;
15068
15071
  }
@@ -20945,8 +20948,46 @@ Getting started:
20945
20948
  Documentation: https://github.com/hanzlahabib/rihal-code
20946
20949
  `.trim());
20947
20950
  }
20951
+ function maybeShowFirstRunBanner() {
20952
+ const os = require("os");
20953
+ const home = os.homedir();
20954
+ const markerDir = path.join(home, ".rihal");
20955
+ const marker = path.join(markerDir, ".welcome-shown");
20956
+ if (fs.existsSync(marker)) return;
20957
+ const globalCommands = path.join(home, ".claude", "commands");
20958
+ let hasGlobalRihal = false;
20959
+ try {
20960
+ hasGlobalRihal = fs.existsSync(globalCommands) && fs.readdirSync(globalCommands).some((f) => f.startsWith("rihal-") && f.endsWith(".md"));
20961
+ } catch {
20962
+ }
20963
+ if (!hasGlobalRihal) return;
20964
+ console.log(`
20965
+ \u{1F54C} Rihal Code v${PACKAGE_JSON.version} \u2014 first run detected.
20966
+ `);
20967
+ console.log(` \u2713 ${countGlobalRihal(globalCommands)} slash commands installed \u2192 ~/.claude/commands/`);
20968
+ console.log(` \u2713 All /rihal-* commands available in every Claude Code project.`);
20969
+ console.log(`
20970
+ To set up a project: cd my-project && rcode install`);
20971
+ console.log(` Show all commands: rcode help`);
20972
+ console.log(` Diagnose issues: rcode doctor
20973
+ `);
20974
+ try {
20975
+ fs.mkdirSync(markerDir, { recursive: true });
20976
+ fs.writeFileSync(marker, `installed ${PACKAGE_JSON.version} at ${(/* @__PURE__ */ new Date()).toISOString()}
20977
+ `);
20978
+ } catch {
20979
+ }
20980
+ }
20981
+ function countGlobalRihal(dir) {
20982
+ try {
20983
+ return fs.readdirSync(dir).filter((f) => f.startsWith("rihal-") && f.endsWith(".md")).length;
20984
+ } catch {
20985
+ return 0;
20986
+ }
20987
+ }
20948
20988
  async function main() {
20949
20989
  const [, , command = "help", ...args] = process.argv;
20990
+ maybeShowFirstRunBanner();
20950
20991
  const handler = COMMANDS[command];
20951
20992
  if (!handler) {
20952
20993
  console.error(`Unknown command: ${command}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzlaa/rcode",
3
- "version": "3.4.17",
3
+ "version": "3.4.18",
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": {
@@ -2390,6 +2390,11 @@ function cmdState(subArgs) {
2390
2390
  // Format B — heading style: ## Phase 01 — Name / ### Phase 01: Name
2391
2391
  // Milestone heading is also matched in any of: "## Milestone M1", "## Milestone v1.0 — Name",
2392
2392
  // "**Milestone: v1.0 — Name**".
2393
+
2394
+ // Issue #651 — must be declared in outer scope. The prune step at end of
2395
+ // sync references seenNums even when roadmap_exists is false (no-op prune
2396
+ // path), causing 'seenNums is not defined' crash.
2397
+ const seenNums = new Set();
2393
2398
  if (parsed.roadmap_exists) {
2394
2399
  const roadmap = fs.readFileSync(roadmapPath, 'utf8');
2395
2400
  const milestoneMatches = [
@@ -2425,8 +2430,6 @@ function cmdState(subArgs) {
2425
2430
  parsed.phases_normalized = beforeClean - cleaned.length;
2426
2431
  state.phases = cleaned;
2427
2432
 
2428
- const seenNums = new Set();
2429
-
2430
2433
  const upsertPhase = (phaseNum, phaseName, phaseGoal) => {
2431
2434
  if (!/^\d/.test(phaseNum)) return;
2432
2435
  if (phaseName.toLowerCase() === 'phase') return;
@@ -573,7 +573,8 @@ If `CODE_REVIEW_ENABLED` is `"false"`: display "Code review skipped (workflow.co
573
573
  REVIEWER_MODEL=$(node ".rihal/bin/rihal-tools.cjs" resolve-model code-reviewer 2>/dev/null | node -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{try{console.log(JSON.parse(d).model)}catch{console.log('')}})" || echo "sonnet")
574
574
  REVIEWER_MODEL=${REVIEWER_MODEL:-sonnet}
575
575
  REVIEWER_SKILLS=$(node ".rihal/bin/rihal-tools.cjs" agent-skills rihal-code-reviewer 2>/dev/null || echo "")
576
- PADDED=$(printf "%02d" "${PHASE_NUMBER}")
576
+ # Issue #652 — no leading zeros. Variable name kept for backward compat in this workflow.
577
+ PADDED="${PHASE_NUMBER}"
577
578
  REVIEW_FILE="${PHASE_DIR}/${PADDED}-REVIEW.md"
578
579
  ```
579
580
 
@@ -209,8 +209,9 @@ Exit workflow.
209
209
 
210
210
  ```bash
211
211
  EXISTING_PLAN_COUNT=$(ls "${PHASE_DIR}"/*-SPRINT.md 2>/dev/null | wc -l | tr -d ' ')
212
- NEXT_PLAN_NUMBER=$(printf "%02d" $((EXISTING_PLAN_COUNT + 1)))
213
- PADDED_PHASE=$(printf "%02d" "${PHASE}")
212
+ # Issue #652 — no leading zeros in planning artifacts. Phase 8 not 08, plan 2 not 02.
213
+ NEXT_PLAN_NUMBER=$((EXISTING_PLAN_COUNT + 1))
214
+ PADDED_PHASE="${PHASE}"
214
215
  GAP_PLAN_FILENAME="${PADDED_PHASE}-${NEXT_PLAN_NUMBER}-SPRINT.md"
215
216
  GAP_PLAN_PATH="${PHASE_DIR}/${GAP_PLAN_FILENAME}"
216
217
  ```