@hanzlaa/rcode 3.3.2 → 3.4.1

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.
Files changed (111) hide show
  1. package/README.md +23 -38
  2. package/cli/index.js +0 -0
  3. package/cli/install.js +37 -29
  4. package/cli/update.js +17 -20
  5. package/dist/rcode.js +52 -48
  6. package/package.json +10 -10
  7. package/rihal/agents/rihal-assumptions-analyzer.md +1 -1
  8. package/rihal/agents/rihal-fatima.md +1 -0
  9. package/rihal/agents/rihal-integration-checker.md +1 -0
  10. package/rihal/agents/rihal-khalid.md +1 -0
  11. package/rihal/agents/rihal-noor.md +1 -0
  12. package/rihal/agents/rihal-project-researcher.md +1 -0
  13. package/rihal/agents/rihal-research-synthesizer.md +1 -0
  14. package/rihal/agents/rihal-waleed.md +1 -0
  15. package/rihal/skills/actions/1-analysis/research/rihal-domain-research/SKILL.md +2 -0
  16. package/rihal/skills/actions/1-analysis/research/rihal-market-research/SKILL.md +2 -0
  17. package/rihal/skills/actions/1-analysis/research/rihal-technical-research/SKILL.md +2 -0
  18. package/rihal/skills/actions/1-analysis/rihal-document-project/SKILL.md +2 -0
  19. package/rihal/skills/actions/1-analysis/rihal-prfaq/SKILL.md +2 -0
  20. package/rihal/skills/actions/1-analysis/rihal-product-brief/SKILL.md +2 -0
  21. package/rihal/skills/actions/2-plan/rihal-create-epics-and-stories/SKILL.md +2 -0
  22. package/rihal/skills/actions/2-plan/rihal-create-milestone/SKILL.md +2 -0
  23. package/rihal/skills/actions/2-plan/rihal-create-prd/SKILL.md +2 -0
  24. package/rihal/skills/actions/2-plan/rihal-create-story/SKILL.md +2 -0
  25. package/rihal/skills/actions/2-plan/rihal-create-ux-design/SKILL.md +2 -0
  26. package/rihal/skills/actions/2-plan/rihal-edit-prd/SKILL.md +2 -0
  27. package/rihal/skills/actions/2-plan/rihal-frontend-design/SKILL.md +2 -0
  28. package/rihal/skills/actions/2-plan/rihal-validate-prd/SKILL.md +2 -0
  29. package/rihal/skills/actions/3-solutioning/rihal-check-implementation-readiness/SKILL.md +2 -0
  30. package/rihal/skills/actions/3-solutioning/rihal-create-architecture/SKILL.md +2 -0
  31. package/rihal/skills/actions/3-solutioning/rihal-generate-project-context/SKILL.md +2 -0
  32. package/rihal/skills/actions/4-implementation/rihal-browser-verify/SKILL.md +2 -0
  33. package/rihal/skills/actions/4-implementation/rihal-ci/SKILL.md +2 -0
  34. package/rihal/skills/actions/4-implementation/rihal-code-review/SKILL.md +2 -0
  35. package/rihal/skills/actions/4-implementation/rihal-correct-course/SKILL.md +2 -0
  36. package/rihal/skills/actions/4-implementation/rihal-debug/SKILL.md +2 -0
  37. package/rihal/skills/actions/4-implementation/rihal-dev-story/SKILL.md +2 -0
  38. package/rihal/skills/actions/4-implementation/rihal-git-flow/SKILL.md +2 -0
  39. package/rihal/skills/actions/4-implementation/rihal-harden/SKILL.md +2 -0
  40. package/rihal/skills/actions/4-implementation/rihal-incremental/SKILL.md +2 -0
  41. package/rihal/skills/actions/4-implementation/rihal-migrate/SKILL.md +2 -0
  42. package/rihal/skills/actions/4-implementation/rihal-perf/SKILL.md +2 -0
  43. package/rihal/skills/actions/4-implementation/rihal-prove-it/SKILL.md +2 -0
  44. package/rihal/skills/actions/4-implementation/rihal-qa-generate-e2e-tests/SKILL.md +2 -0
  45. package/rihal/skills/actions/4-implementation/rihal-retrospective/SKILL.md +2 -0
  46. package/rihal/skills/actions/4-implementation/rihal-scaffold-project/SKILL.md +2 -0
  47. package/rihal/skills/actions/4-implementation/rihal-source-truth/SKILL.md +2 -0
  48. package/rihal/skills/actions/4-implementation/rihal-sprint-planning/SKILL.md +2 -0
  49. package/rihal/skills/actions/4-implementation/rihal-sprint-status/SKILL.md +2 -0
  50. package/rihal/skills/actions/4-implementation/rihal-trim/SKILL.md +2 -0
  51. package/rihal/skills/agents/ahmed-hassani-director/SKILL.md +2 -0
  52. package/rihal/skills/agents/dalil-scout/SKILL.md +2 -0
  53. package/rihal/skills/agents/fatima-qa/SKILL.md +2 -0
  54. package/rihal/skills/agents/haitham-frontend/SKILL.md +2 -0
  55. package/rihal/skills/agents/hanzla-engineer/SKILL.md +2 -0
  56. package/rihal/skills/agents/hussain-pm/SKILL.md +2 -0
  57. package/rihal/skills/agents/hussain-sm/SKILL.md +2 -0
  58. package/rihal/skills/agents/layla-designer/SKILL.md +2 -0
  59. package/rihal/skills/agents/majlis-council/SKILL.md +2 -0
  60. package/rihal/skills/agents/mariam-marketing/SKILL.md +2 -0
  61. package/rihal/skills/agents/nasser-eng-manager/SKILL.md +2 -0
  62. package/rihal/skills/agents/noor-writer/SKILL.md +2 -0
  63. package/rihal/skills/agents/raees-orchestrator/SKILL.md +2 -0
  64. package/rihal/skills/agents/sadiq-analyst/SKILL.md +2 -0
  65. package/rihal/skills/agents/waleed-architect/SKILL.md +2 -0
  66. package/rihal/skills/agents/yousef-backend/SKILL.md +2 -0
  67. package/rihal/skills/agents/zahra-branding/SKILL.md +2 -0
  68. package/rihal/skills/agents/zayd-ml/SKILL.md +2 -0
  69. package/rihal/skills/core/rihal-advanced-elicitation/SKILL.md +2 -0
  70. package/rihal/skills/core/rihal-auth-audit/SKILL.md +2 -0
  71. package/rihal/skills/core/rihal-brainstorming/SKILL.md +2 -0
  72. package/rihal/skills/core/rihal-client-gate/SKILL.md +2 -0
  73. package/rihal/skills/core/rihal-clone-website/SKILL.md +2 -0
  74. package/rihal/skills/core/rihal-deploy-unify/SKILL.md +2 -0
  75. package/rihal/skills/core/rihal-distillator/SKILL.md +2 -0
  76. package/rihal/skills/core/rihal-editorial-review-prose/SKILL.md +2 -0
  77. package/rihal/skills/core/rihal-editorial-review-structure/SKILL.md +2 -0
  78. package/rihal/skills/core/rihal-help/SKILL.md +2 -0
  79. package/rihal/skills/core/rihal-incident-record/SKILL.md +2 -0
  80. package/rihal/skills/core/rihal-index-docs/SKILL.md +2 -0
  81. package/rihal/skills/core/rihal-init/SKILL.md +2 -0
  82. package/rihal/skills/core/rihal-memory-audit/SKILL.md +2 -0
  83. package/rihal/skills/core/rihal-memory-distill/SKILL.md +2 -0
  84. package/rihal/skills/core/rihal-memory-init/SKILL.md +2 -0
  85. package/rihal/skills/core/rihal-memory-update/SKILL.md +2 -0
  86. package/rihal/skills/core/rihal-mvp-graduate/SKILL.md +2 -0
  87. package/rihal/skills/core/rihal-ocr-consistency/SKILL.md +2 -0
  88. package/rihal/skills/core/rihal-party-mode/SKILL.md +2 -0
  89. package/rihal/skills/core/rihal-rebrand/SKILL.md +2 -0
  90. package/rihal/skills/core/rihal-review-adversarial-general/SKILL.md +2 -0
  91. package/rihal/skills/core/rihal-review-edge-case-hunter/SKILL.md +2 -0
  92. package/rihal/skills/core/rihal-shard-doc/SKILL.md +2 -0
  93. package/rihal/skills/core/rihal-theme-system/SKILL.md +2 -0
  94. package/rihal/workflows/add-tests.md +1 -0
  95. package/rihal/workflows/audit-fix.md +2 -0
  96. package/rihal/workflows/autonomous.md +1 -0
  97. package/rihal/workflows/code-review-fix.md +2 -1
  98. package/rihal/workflows/debug.md +1 -0
  99. package/rihal/workflows/dev-story.md +1 -0
  100. package/rihal/workflows/execute-sprint.md +1 -0
  101. package/rihal/workflows/execute.md +1 -0
  102. package/rihal/workflows/init.md +82 -0
  103. package/rihal/workflows/plan.md +1 -0
  104. package/rihal/workflows/ship.md +2 -0
  105. package/rihal/workflows/sprint-planning.md +1 -0
  106. package/rihal/workflows/validate-phase.md +1 -0
  107. package/rihal/workflows/verify-phase.md +1 -0
  108. package/server/lib/api.js +49 -0
  109. package/server/lib/html/client.js +100 -10
  110. package/server/lib/html/css.js +64 -1
  111. package/server/lib/html/shell.js +11 -5
package/README.md CHANGED
@@ -2,9 +2,17 @@
2
2
 
3
3
  <div dir="rtl">طريقة رحال</div>
4
4
 
5
- > **rcode is the memory bank for AI-driven SaaS teams — your project's context, structured, visible, and never lost.**
6
- >
7
- > Built by Rihal. Designed for solo devs, startup teams, and SaaS builders. Install once, and your AI assistant gets a persistent project brain: structured memory, decisions log, distinctive personas, and phase-based workflows. Works in Claude Code, Cursor, and any compatible AI IDE.
5
+ > **The AI team that never forgets.** Persistent memory, 45 specialist agents, 95 commandsinstall once, and your AI IDE gets a project brain that survives every session reset.
6
+
7
+ ```bash
8
+ npx @hanzlaa/rcode install # one command, zero dependencies
9
+ ```
10
+
11
+ [![npm version](https://img.shields.io/npm/v/@hanzlaa/rcode)](https://www.npmjs.com/package/@hanzlaa/rcode)
12
+ [![downloads](https://img.shields.io/npm/dw/@hanzlaa/rcode)](https://www.npmjs.com/package/@hanzlaa/rcode)
13
+
14
+ <!-- TODO: Replace with actual demo GIF once recorded (story 05.1.03) -->
15
+ <!-- ![rcode demo](docs/assets/demo.gif) -->
8
16
 
9
17
  ---
10
18
 
@@ -27,8 +35,6 @@ Every project carries unwritten context — how the team reviews PRs, what "done
27
35
 
28
36
  **rcode fixes that.** One install, and the AI knows. Every session. Every repo. Every contributor.
29
37
 
30
- See [`docs/what-is-rihal-code.md`](docs/what-is-rihal-code.md) for the full story, and [`docs/ROADMAP.md`](docs/ROADMAP.md) for where this is going (next: live MCP server in v3.0).
31
-
32
38
  ---
33
39
 
34
40
  ## 🚦 Start Here
@@ -44,7 +50,7 @@ Rihal Code packages a lot. To keep things approachable, everything is organized
44
50
 
45
51
  **Brand new?** Do the [Golden Path](docs/TIERS.md#-starter--the-golden-path): scaffold → PRD → stories → sprint → dev → review → status. Seven skills, one project, end-to-end.
46
52
 
47
- > **v2.0 — Rihal Brain.** v1 was a generic AI-engineering methodology. v2 keeps all of that and adds the Rihal context layer on top: standards, guides, and institutional knowledge pulled fresh from Rihal's own repos on install and on `/rihal-update`. See [`CHANGELOG.md`](CHANGELOG.md) and the [v2.0 milestone](https://github.com/hanzlahabib/rihal-code/milestone/4).
53
+ > **v3 — Rihal Brain.** v1 was a generic AI-engineering methodology. v2 added the Rihal context layer. v3 ships it as a single npm package with a Memory Bank, live dashboard, and 134 automated tests. See [`CHANGELOG.md`](CHANGELOG.md).
48
54
 
49
55
  ---
50
56
 
@@ -54,7 +60,8 @@ Most AI tools give you one assistant pretending to be everything. **Rihal Code g
54
60
 
55
61
  - **45 agents** with clear roles, cultural identity (Arabic names), and hard scope boundaries
56
62
  - **95 slash commands** covering research, planning, execution, verification, and recovery
57
- - **80 skills** including Memory Bank primitives, 11 engineering-rigor skills (TDD, harden, perf, debug, trim, etc.), and 8 real-pain skills (auth-audit, mvp-graduate, deploy-unify, etc.)
63
+ - **105 skills** including Memory Bank primitives, 11 engineering-rigor skills (TDD, harden, perf, debug, trim, etc.), and 8 real-pain skills (auth-audit, mvp-graduate, deploy-unify, etc.)
64
+ - **102 workflows** — the execution backbone behind every slash command
58
65
  - **Persistent project memory** at `.rihal/memory/` — checked into git, visible in the Diwan dashboard, lossless distillates for fast LLM hydration
59
66
  - **3 execution modes**: parallel debate (`/rihal-council`), sequential pipelines (`/rihal-chain`), and quick-sync (`/rihal-discuss`)
60
67
  - **File-based state** in `.rihal/` that every workflow reads and updates
@@ -79,14 +86,14 @@ In any project directory (existing codebase OR empty folder):
79
86
  npx @hanzlaa/rcode install
80
87
  ```
81
88
 
82
- [Live on npm](https://www.npmjs.com/package/@hanzlaa/rcode) as `@hanzlaa/rcode` · current version `v2.1.0`. See [`docs/install.md`](docs/install.md) for flavors (module subsets, IDE options, version pinning, yolo mode).
89
+ [Live on npm](https://www.npmjs.com/package/@hanzlaa/rcode) as `@hanzlaa/rcode`. See [`docs/install.md`](docs/install.md) for flavors (module subsets, IDE options, version pinning, yolo mode).
83
90
 
84
91
  One unified installer. Pure file shipping, no runtime dependencies. Installs into:
85
92
 
86
93
  - `.rihal/` — config, workflows, references, bin (Rihal infrastructure)
87
94
  - `.claude/agents/` — 45 first-class subagents
88
95
  - `.claude/commands/rihal/` — 95 slash commands
89
- - `.claude/skills/` — 80 phrase-activated skills (scaffold-project, create-prd, prfaq, memory-init, retrospective, etc.)
96
+ - `.claude/skills/` — 105 phrase-activated skills (scaffold-project, create-prd, prfaq, memory-init, retrospective, etc.)
90
97
  - `rihal/brain/` — Rihal standards pulled from upstream (PR / commit / architecture docs)
91
98
  - `.planning/` — where your artifacts land (council sessions, plans, chains, summaries)
92
99
 
@@ -148,7 +155,7 @@ npx @hanzlaa/rcode install --ide gemini
148
155
  bin/
149
156
  rihal-tools.cjs — CLI helper (state read/write, panel scoring, etc.)
150
157
  lib/council-panel.cjs — deterministic panel scorer
151
- workflows/ — 69 slash command workflows
158
+ workflows/ — 102 slash command workflows
152
159
  references/ — shared contracts (council-protocol, gates, karpathy-guidelines, etc.)
153
160
  agents-rules/ — lazy-loaded agent rule files (planner, executor, debugger)
154
161
  ```
@@ -308,26 +315,6 @@ Amazon's "Working Backwards" method: write the finished-product press release *b
308
315
 
309
316
  ---
310
317
 
311
- ## What's new in v2-prototype
312
-
313
- Recent additions in this session:
314
-
315
- - **69 slash commands** across 3 modes and 3 modules (up from 64)
316
- - **Numeric ID system** — milestones (M1, M2), phases (01, 02, 02.1), plans (01.01, 02.03), tasks (01.01.01) with decimal insertion for urgent inserts
317
- - **Intent guards** (`Step 0.5`) — every workflow detects mismatched intent and redirects instead of failing
318
- - **Plan-checker loop** — `/rihal-plan` now verifies file existence and symbol definitions; loops back to planner on validation failure
319
- - **Post-execute gates** — `/rihal-execute` runs integration-checker (E2E) and nyquist-auditor (coverage) as hard gates
320
- - **Multilingual classifier** — Roman Urdu, Arabic, English with cultural signal routing (Mariam leads GCC/MENA)
321
- - **Karpathy guidelines enforcement** — 4 coding principles baked into every code-writing agent
322
- - **Global agents** — customize agents in `~/.rihal/agents/` without forking the repo
323
- - **Multi-IDE installer** — support for Claude Code, Cursor, Gemini CLI
324
- - **Hooks system** — opt-in pre-edit, pre-workflow, post-commit enforcement
325
- - **Session pause/resume** — `/rihal-pause-work` + `/rihal-resume-work` with HANDOFF.json
326
- - **Workspace isolation** — `/rihal-new-workspace` for parallel tracks
327
- - **Decimal phase insertion** — `/rihal-insert-phase` for urgent mid-cycle work
328
-
329
- ---
330
-
331
318
  ## Full command surface (95 commands)
332
319
 
333
320
  ### Router + lifecycle
@@ -428,18 +415,18 @@ Installs 3 opt-in hooks into `.claude/settings.json`:
428
415
  | **execution** | Executor, planner, verifier + checker agents, `/rihal-execute`, `/rihal-plan`, `/rihal-quick`, `/rihal-debug`, `/rihal-audit-fix`, `/rihal-undo` |
429
416
  | **discovery** | Codebase-mapper, project-researcher, roadmapper, `/rihal-new-project`, `/rihal-map-codebase`, `/rihal-scan`, `/rihal-explore`, `/rihal-code-review`, `/rihal-docs-update` |
430
417
 
431
- Full install = all 3 modules = 201 files.
418
+ Full install = all 3 modules = 700+ files.
432
419
 
433
420
  ---
434
421
 
435
422
  ## Testing
436
423
 
437
424
  ```bash
438
- node --test # full suite (95 tests, ~1s)
425
+ node --test # full suite (134 tests, ~2s)
439
426
  node --test --test-reporter=spec # verbose output with test names
440
427
  ```
441
428
 
442
- **95 tests · 0 failures · pure Node stdlib (no test runner install needed)**
429
+ **134 tests · pure Node stdlib (no test runner install needed)**
443
430
 
444
431
  ### Test scenarios
445
432
 
@@ -466,7 +453,7 @@ Every install runs 5 automated smoke tests before exiting:
466
453
  ✓ .rihal/config.yaml present — 412 bytes
467
454
  ✓ .rihal/state.json parses — valid JSON
468
455
  ✓ agents installed — 45
469
- ✓ skills + commands installed — 80 skills + 95 commands
456
+ ✓ skills + commands installed — 105 skills + 95 commands
470
457
  ```
471
458
 
472
459
  A failed check prints the debug command and returns exit code 1 so CI catches broken installs.
@@ -508,12 +495,10 @@ node --test test/lib/manifest.test.cjs # install verification only
508
495
 
509
496
  ## License
510
497
 
511
- MIT
498
+ UNLICENSED — proprietary. All rights reserved.
512
499
 
513
500
  ---
514
501
 
515
502
  ## Roadmap
516
503
 
517
- See [GitHub Issues](https://github.com/hanzlahabib/rihal-code/issues) for tracked work. Current branch: `v2-prototype` under active development. Main branch will track stable releases.
518
-
519
- **This branch is pre-release.** For production, wait for `v0.2.0` on main.
504
+ See [GitHub Issues](https://github.com/hanzlahabib/rihal-code/issues) for tracked work. Current focus: marketing launch, MCP server, dashboard enhancements.
package/cli/index.js CHANGED
File without changes
package/cli/install.js CHANGED
@@ -299,20 +299,19 @@ function detectIdeSignals(target) {
299
299
  * actually wanted cursor or gemini.
300
300
  */
301
301
  async function resolveIde(opts) {
302
- if (opts.ideProvided) return opts.ide; // user passed --ide, respect it
303
- if (opts.yes || !process.stdin.isTTY) return opts.ide || 'claude';
302
+ if (opts.ideProvided) return [opts.ide]; // user passed --ide, respect it
303
+ if (opts.yes || !process.stdin.isTTY) return [opts.ide || 'claude'];
304
304
 
305
305
  const signals = detectIdeSignals(opts.target);
306
306
  const detected = ['claude', 'cursor', 'gemini', 'vscode'].filter(k => signals[k]);
307
307
 
308
- // Pick a default: prefer the single detected IDE; otherwise claude
309
- let defaultValue = 'claude';
310
- if (detected.length === 1) defaultValue = detected[0];
308
+ // Pre-select detected IDEs, or default to claude
309
+ const initialValues = detected.length > 0 ? detected : ['claude'];
311
310
 
312
- // Use @clack/prompts for arrow-key navigation. Closes #449 / #450.
313
- const choice = await clack.select({
314
- message: '🎯 Which editor will you use rcode with?',
315
- initialValue: defaultValue,
311
+ // Use @clack/prompts multiselect for multi-editor support. Closes #449 / #450.
312
+ const choices = await clack.multiselect({
313
+ message: '🎯 Which editor(s) will you use rcode with?',
314
+ initialValues,
316
315
  options: [
317
316
  { value: 'claude', label: 'Claude Code', hint: signals.claude ? '(detected)' : undefined },
318
317
  { value: 'cursor', label: 'Cursor', hint: signals.cursor ? '(detected)' : undefined },
@@ -320,15 +319,16 @@ async function resolveIde(opts) {
320
319
  { value: 'vscode', label: 'VS Code', hint: signals.vscode ? '(detected)' : '(via Continue / Copilot extensions)' },
321
320
  { value: 'antigravity', label: 'Antigravity', hint: '(experimental — installs to .antigravity/)' },
322
321
  ],
322
+ required: true,
323
323
  });
324
324
 
325
325
  // Handle Ctrl-C cleanly
326
- if (clack.isCancel(choice)) {
326
+ if (clack.isCancel(choices)) {
327
327
  clack.cancel('Install cancelled.');
328
328
  process.exit(0);
329
329
  }
330
330
 
331
- return choice;
331
+ return choices;
332
332
  }
333
333
 
334
334
  /**
@@ -1226,7 +1226,7 @@ async function install(opts) {
1226
1226
  if (isInteractive) printInstallHeader(pkgVersion);
1227
1227
 
1228
1228
  // Resolve target IDE (interactive prompt unless --ide flag, --yes, or non-TTY).
1229
- opts.ide = await resolveIde(opts);
1229
+ opts.ides = await resolveIde(opts);
1230
1230
 
1231
1231
  // Resolve commit-planning preference (interactive prompt or flag) — #189.
1232
1232
  opts.commitPlanning = await resolveCommitPlanning(opts);
@@ -1255,9 +1255,11 @@ async function install(opts) {
1255
1255
  return 1;
1256
1256
  }
1257
1257
 
1258
- // Validate IDE — structured error for unsupported editors (#197).
1259
- if (!['claude', 'cursor', 'gemini', 'vscode', 'antigravity'].includes(opts.ide)) {
1260
- console.error(`✖ --ide ${opts.ide} is not supported in v${readPackageVersion()}.`);
1258
+ // Validate IDE(s) — structured error for unsupported editors (#197).
1259
+ const SUPPORTED_IDES = ['claude', 'cursor', 'gemini', 'vscode', 'antigravity'];
1260
+ const unsupported = opts.ides.filter(ide => !SUPPORTED_IDES.includes(ide));
1261
+ if (unsupported.length > 0) {
1262
+ console.error(`✖ --ide ${unsupported.join(', ')} is not supported in v${readPackageVersion()}.`);
1261
1263
  console.error('');
1262
1264
  console.error(' Currently supported:');
1263
1265
  console.error(' claude — Claude Code native (recommended)');
@@ -1274,21 +1276,23 @@ async function install(opts) {
1274
1276
  }
1275
1277
 
1276
1278
  // VS Code installs to .claude/ paths (extension reads from there). Inform the user.
1277
- if (opts.ide === 'vscode') {
1279
+ if (opts.ides.includes('vscode')) {
1278
1280
  console.log(' ' + dim('VS Code → installing to .claude/ paths (read by Claude Code / Continue / Copilot extensions).'));
1279
1281
  }
1280
1282
 
1281
1283
  // Gemini IDE support deferred
1282
- if (opts.ide === 'gemini') {
1284
+ if (opts.ides.includes('gemini')) {
1283
1285
  console.log(`\n⚠️ Gemini CLI install not yet implemented\n`);
1284
1286
  console.log(`Gemini IDE requires aggregating all agents and commands into a single GEMINI.md file.`);
1285
1287
  console.log(`This feature is planned but not yet available.\n`);
1286
1288
  console.log(`For now, use: --ide claude or --ide cursor\n`);
1287
- return 1;
1289
+ // Remove gemini from the list so install can continue for other IDEs
1290
+ opts.ides = opts.ides.filter(e => e !== 'gemini');
1291
+ if (opts.ides.length === 0) return 1;
1288
1292
  }
1289
1293
 
1290
1294
  // Antigravity install is experimental — best-effort path, user may need to adjust
1291
- if (opts.ide === 'antigravity') {
1295
+ if (opts.ides.includes('antigravity')) {
1292
1296
  console.log(' ' + warn('Antigravity install is experimental. Files land at .antigravity/rihal/{agents,commands}/.'));
1293
1297
  console.log(' ' + dim('If Antigravity expects a different path, adjust .rihal/config.yaml and re-run.'));
1294
1298
  }
@@ -1304,7 +1308,7 @@ async function install(opts) {
1304
1308
  }
1305
1309
  }
1306
1310
 
1307
- const fullPlan = buildInstallPlan(opts.ide, opts.target);
1311
+ const fullPlan = buildInstallPlan(opts.ides, opts.target);
1308
1312
  const plan = filterPlanByModules(fullPlan, opts.modules);
1309
1313
  if (plan.length === 0) {
1310
1314
  console.error('✖ Nothing to install — install plan is empty.');
@@ -1719,7 +1723,8 @@ async function install(opts) {
1719
1723
  // Count installed agents + commands dynamically (#190). Reads from the
1720
1724
  // IDE-specific install paths so cursor/gemini/vscode/antigravity don't
1721
1725
  // false-fail the health check.
1722
- const idePaths = getPathsForIde(opts.ide, opts.target);
1726
+ const primaryIde = opts.ides[0];
1727
+ const idePaths = getPathsForIde(primaryIde, opts.target);
1723
1728
  const agentsDir = idePaths.agentsDir;
1724
1729
  const commandsDir = idePaths.commandsDir;
1725
1730
  let agentCount = 0, commandCount = 0;
@@ -1735,7 +1740,7 @@ async function install(opts) {
1735
1740
  const version = readPackageVersion();
1736
1741
  console.log('');
1737
1742
  console.log(` ${bold('Version:')} ${pc.cyan('@hanzlaa/rcode@' + version)}`);
1738
- console.log(` ${bold('IDE:')} ${opts.ide}`);
1743
+ console.log(` ${bold('IDE:')} ${opts.ides.join(', ')}`);
1739
1744
  console.log(` ${bold('Language:')} ${opts.language} ${dim('(change in .rihal/config.yaml)')}`);
1740
1745
  console.log(` ${bold('Mode:')} ${opts.mode} ${dim('(guided=confirm at gates, yolo=autonomous)')}`);
1741
1746
  console.log(` ${bold('Planning:')} ${opts.commitPlanning !== false ? 'committed' : 'gitignored'} ${dim('(flip: rihal-tools gitignore refresh)')}`);
@@ -1898,7 +1903,7 @@ async function main() {
1898
1903
  * Mutates opts in-place. Exits 0 on cancel.
1899
1904
  */
1900
1905
  async function runInstallWizard(opts) {
1901
- const { intro, outro, text, select, confirm, isCancel, cancel, note } = clack;
1906
+ const { intro, outro, text, select, multiselect, confirm, isCancel, cancel, note } = clack;
1902
1907
  const pkgVersion = readPackageVersion();
1903
1908
 
1904
1909
  console.log('');
@@ -1919,17 +1924,20 @@ async function runInstallWizard(opts) {
1919
1924
  }
1920
1925
 
1921
1926
  // ── 2. Editor / LLM ──────────────────────────────────────────────────
1922
- const editorChoice = await select({
1923
- message: 'Which editor are you installing for?',
1927
+ const editorChoices = await multiselect({
1928
+ message: 'Which editor(s) are you installing for?',
1924
1929
  options: [
1925
1930
  { value: 'claude', label: 'Claude Code', hint: 'recommended' },
1926
1931
  { value: 'cursor', label: 'Cursor' },
1927
1932
  { value: 'gemini', label: 'Gemini CLI', hint: 'coming soon' },
1933
+ { value: 'vscode', label: 'VS Code', hint: 'via Continue / Copilot extensions' },
1934
+ { value: 'antigravity', label: 'Antigravity', hint: 'experimental' },
1928
1935
  ],
1929
- initialValue: opts.ide || 'claude',
1936
+ initialValues: opts.ide ? [opts.ide] : ['claude'],
1937
+ required: true,
1930
1938
  });
1931
- if (isCancel(editorChoice)) { cancel('Installation cancelled.'); process.exit(0); }
1932
- opts.ide = editorChoice;
1939
+ if (isCancel(editorChoices)) { cancel('Installation cancelled.'); process.exit(0); }
1940
+ opts.ides = editorChoices;
1933
1941
 
1934
1942
  // ── 3. Communication language ─────────────────────────────────────────
1935
1943
  const langChoice = await select({
@@ -1984,7 +1992,7 @@ async function runInstallWizard(opts) {
1984
1992
  note(
1985
1993
  [
1986
1994
  `${pc.dim('Directory:')} ${opts.target}`,
1987
- `${pc.dim('Editor:')} ${opts.ide}`,
1995
+ `${pc.dim('Editor:')} ${opts.ides.join(', ')}`,
1988
1996
  `${pc.dim('Language:')} ${opts.language}`,
1989
1997
  `${pc.dim('Mode:')} ${opts.mode}`,
1990
1998
  `${pc.dim('Planning:')} ${opts.commitPlanning ? 'committed to git' : 'kept local (gitignored)'}`,
package/cli/update.js CHANGED
@@ -31,7 +31,8 @@
31
31
  const fs = require('fs');
32
32
  const path = require('path');
33
33
  const { spawnSync } = require('child_process');
34
- const { askConfirm, askChoice, PromptAbortError } = require('./lib/prompts.cjs');
34
+ const clack = require('@clack/prompts');
35
+ const { PromptAbortError } = require('./lib/prompts.cjs');
35
36
  const { writeJsonAtomic } = require('./lib/fsutil.cjs');
36
37
  const { verifyInstall, formatReport } = require('./lib/manifest.cjs');
37
38
  const install = require('./install');
@@ -273,21 +274,17 @@ async function runUpdate(args, { packageRoot, packageJson }) {
273
274
  const ALL_EDITORS = ['claude', 'cursor', 'gemini'];
274
275
  const missing = ALL_EDITORS.filter(e => !editors.includes(e));
275
276
  if (missing.length > 0) {
276
- const choices = [
277
- { id: 'no', label: `No — refresh existing only (${editors.join(', ')})` },
278
- ...missing.map(e => ({ id: e, label: `Add ${e}` })),
279
- { id: 'all', label: 'Add all missing editors' },
280
- ];
281
- const answer = await askChoice(
282
- `Add support for additional editors?`,
283
- { choices, default: 'no' }
284
- );
285
- const picked = answer[0];
286
- if (picked === 'all') {
287
- for (const e of missing) editors.push(e);
288
- } else if (picked !== 'no') {
289
- editors.push(picked);
277
+ const editorLabels = { claude: 'Claude Code', cursor: 'Cursor', gemini: 'Gemini CLI' };
278
+ const selected = await clack.multiselect({
279
+ message: 'Add support for additional editors?',
280
+ options: missing.map(e => ({ value: e, label: editorLabels[e] || e })),
281
+ required: false,
282
+ });
283
+ if (clack.isCancel(selected)) {
284
+ clack.cancel('Update cancelled.');
285
+ process.exit(0);
290
286
  }
287
+ for (const e of selected) editors.push(e);
291
288
  console.log(` Editors to update: ${editors.join(', ')}`);
292
289
  console.log();
293
290
  }
@@ -295,11 +292,11 @@ async function runUpdate(args, { packageRoot, packageJson }) {
295
292
 
296
293
  // ------ Confirm ------
297
294
  if (!opts.yes) {
298
- const proceed = await askConfirm(
299
- `Proceed with update? [y/N] `,
300
- { default: 'n' },
301
- );
302
- if (!proceed) {
295
+ const proceed = await clack.confirm({
296
+ message: 'Proceed with update?',
297
+ initialValue: false,
298
+ });
299
+ if (clack.isCancel(proceed) || !proceed) {
303
300
  console.log(`\n❌ Update cancelled. Nothing changed.`);
304
301
  return;
305
302
  }
package/dist/rcode.js CHANGED
@@ -15972,28 +15972,28 @@ var require_install = __commonJS({
15972
15972
  return signals;
15973
15973
  }
15974
15974
  async function resolveIde(opts) {
15975
- if (opts.ideProvided) return opts.ide;
15976
- if (opts.yes || !process.stdin.isTTY) return opts.ide || "claude";
15975
+ if (opts.ideProvided) return [opts.ide];
15976
+ if (opts.yes || !process.stdin.isTTY) return [opts.ide || "claude"];
15977
15977
  const signals = detectIdeSignals(opts.target);
15978
15978
  const detected = ["claude", "cursor", "gemini", "vscode"].filter((k) => signals[k]);
15979
- let defaultValue = "claude";
15980
- if (detected.length === 1) defaultValue = detected[0];
15981
- const choice = await clack.select({
15982
- message: "\u{1F3AF} Which editor will you use rcode with?",
15983
- initialValue: defaultValue,
15979
+ const initialValues = detected.length > 0 ? detected : ["claude"];
15980
+ const choices = await clack.multiselect({
15981
+ message: "\u{1F3AF} Which editor(s) will you use rcode with?",
15982
+ initialValues,
15984
15983
  options: [
15985
15984
  { value: "claude", label: "Claude Code", hint: signals.claude ? "(detected)" : void 0 },
15986
15985
  { value: "cursor", label: "Cursor", hint: signals.cursor ? "(detected)" : void 0 },
15987
15986
  { value: "gemini", label: "Gemini CLI", hint: signals.gemini ? "(detected)" : "(beta \u2014 limited)" },
15988
15987
  { value: "vscode", label: "VS Code", hint: signals.vscode ? "(detected)" : "(via Continue / Copilot extensions)" },
15989
15988
  { value: "antigravity", label: "Antigravity", hint: "(experimental \u2014 installs to .antigravity/)" }
15990
- ]
15989
+ ],
15990
+ required: true
15991
15991
  });
15992
- if (clack.isCancel(choice)) {
15992
+ if (clack.isCancel(choices)) {
15993
15993
  clack.cancel("Install cancelled.");
15994
15994
  process.exit(0);
15995
15995
  }
15996
- return choice;
15996
+ return choices;
15997
15997
  }
15998
15998
  async function resolveCommitPlanning(opts) {
15999
15999
  if (opts.commitPlanning !== null) return opts.commitPlanning;
@@ -16695,7 +16695,7 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
16695
16695
  const pkgVersion = readPackageVersion();
16696
16696
  const isInteractive = process.stdin.isTTY && !opts.yes;
16697
16697
  if (isInteractive) printInstallHeader(pkgVersion);
16698
- opts.ide = await resolveIde(opts);
16698
+ opts.ides = await resolveIde(opts);
16699
16699
  opts.commitPlanning = await resolveCommitPlanning(opts);
16700
16700
  console.log(`
16701
16701
  \u{1F54C} ${bold("Rihal Code")} ${pc.cyan("v" + pkgVersion)} ${dim("\u2192")} ${opts.target}`);
@@ -16717,8 +16717,10 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
16717
16717
  console.error(`\u2716 Source tree not found at ${SOURCE_ROOT}. Running from wrong dir?`);
16718
16718
  return 1;
16719
16719
  }
16720
- if (!["claude", "cursor", "gemini", "vscode", "antigravity"].includes(opts.ide)) {
16721
- console.error(`\u2716 --ide ${opts.ide} is not supported in v${readPackageVersion()}.`);
16720
+ const SUPPORTED_IDES = ["claude", "cursor", "gemini", "vscode", "antigravity"];
16721
+ const unsupported = opts.ides.filter((ide) => !SUPPORTED_IDES.includes(ide));
16722
+ if (unsupported.length > 0) {
16723
+ console.error(`\u2716 --ide ${unsupported.join(", ")} is not supported in v${readPackageVersion()}.`);
16722
16724
  console.error("");
16723
16725
  console.error(" Currently supported:");
16724
16726
  console.error(" claude \u2014 Claude Code native (recommended)");
@@ -16733,10 +16735,10 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
16733
16735
  console.error("");
16734
16736
  return 1;
16735
16737
  }
16736
- if (opts.ide === "vscode") {
16738
+ if (opts.ides.includes("vscode")) {
16737
16739
  console.log(" " + dim("VS Code \u2192 installing to .claude/ paths (read by Claude Code / Continue / Copilot extensions)."));
16738
16740
  }
16739
- if (opts.ide === "gemini") {
16741
+ if (opts.ides.includes("gemini")) {
16740
16742
  console.log(`
16741
16743
  \u26A0\uFE0F Gemini CLI install not yet implemented
16742
16744
  `);
@@ -16745,9 +16747,10 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
16745
16747
  `);
16746
16748
  console.log(`For now, use: --ide claude or --ide cursor
16747
16749
  `);
16748
- return 1;
16750
+ opts.ides = opts.ides.filter((e) => e !== "gemini");
16751
+ if (opts.ides.length === 0) return 1;
16749
16752
  }
16750
- if (opts.ide === "antigravity") {
16753
+ if (opts.ides.includes("antigravity")) {
16751
16754
  console.log(" " + warn("Antigravity install is experimental. Files land at .antigravity/rihal/{agents,commands}/."));
16752
16755
  console.log(" " + dim("If Antigravity expects a different path, adjust .rihal/config.yaml and re-run."));
16753
16756
  }
@@ -16760,7 +16763,7 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
16760
16763
  return 1;
16761
16764
  }
16762
16765
  }
16763
- const fullPlan = buildInstallPlan(opts.ide, opts.target);
16766
+ const fullPlan = buildInstallPlan(opts.ides, opts.target);
16764
16767
  const plan = filterPlanByModules(fullPlan, opts.modules);
16765
16768
  if (plan.length === 0) {
16766
16769
  console.error("\u2716 Nothing to install \u2014 install plan is empty.");
@@ -17090,7 +17093,8 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
17090
17093
  console.log(dim(" To overwrite: re-run with --force-overwrite | To see full diffs: --show-diff"));
17091
17094
  console.log("");
17092
17095
  }
17093
- const idePaths = getPathsForIde(opts.ide, opts.target);
17096
+ const primaryIde = opts.ides[0];
17097
+ const idePaths = getPathsForIde(primaryIde, opts.target);
17094
17098
  const agentsDir = idePaths.agentsDir;
17095
17099
  const commandsDir = idePaths.commandsDir;
17096
17100
  let agentCount = 0, commandCount = 0;
@@ -17106,7 +17110,7 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
17106
17110
  const version = readPackageVersion();
17107
17111
  console.log("");
17108
17112
  console.log(` ${bold("Version:")} ${pc.cyan("@hanzlaa/rcode@" + version)}`);
17109
- console.log(` ${bold("IDE:")} ${opts.ide}`);
17113
+ console.log(` ${bold("IDE:")} ${opts.ides.join(", ")}`);
17110
17114
  console.log(` ${bold("Language:")} ${opts.language} ${dim("(change in .rihal/config.yaml)")}`);
17111
17115
  console.log(` ${bold("Mode:")} ${opts.mode} ${dim("(guided=confirm at gates, yolo=autonomous)")}`);
17112
17116
  console.log(` ${bold("Planning:")} ${opts.commitPlanning !== false ? "committed" : "gitignored"} ${dim("(flip: rihal-tools gitignore refresh)")}`);
@@ -17243,7 +17247,7 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
17243
17247
  }
17244
17248
  }
17245
17249
  async function runInstallWizard(opts) {
17246
- const { intro, outro, text, select, confirm, isCancel, cancel, note } = clack;
17250
+ const { intro, outro, text, select, multiselect, confirm, isCancel, cancel, note } = clack;
17247
17251
  const pkgVersion = readPackageVersion();
17248
17252
  console.log("");
17249
17253
  intro(pc.bold("\u{1F54C} Rihal Code") + pc.dim(` v${pkgVersion}`));
@@ -17262,20 +17266,23 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
17262
17266
  opts.target = resolved;
17263
17267
  opts.projectName = path2.basename(resolved);
17264
17268
  }
17265
- const editorChoice = await select({
17266
- message: "Which editor are you installing for?",
17269
+ const editorChoices = await multiselect({
17270
+ message: "Which editor(s) are you installing for?",
17267
17271
  options: [
17268
17272
  { value: "claude", label: "Claude Code", hint: "recommended" },
17269
17273
  { value: "cursor", label: "Cursor" },
17270
- { value: "gemini", label: "Gemini CLI", hint: "coming soon" }
17274
+ { value: "gemini", label: "Gemini CLI", hint: "coming soon" },
17275
+ { value: "vscode", label: "VS Code", hint: "via Continue / Copilot extensions" },
17276
+ { value: "antigravity", label: "Antigravity", hint: "experimental" }
17271
17277
  ],
17272
- initialValue: opts.ide || "claude"
17278
+ initialValues: opts.ide ? [opts.ide] : ["claude"],
17279
+ required: true
17273
17280
  });
17274
- if (isCancel(editorChoice)) {
17281
+ if (isCancel(editorChoices)) {
17275
17282
  cancel("Installation cancelled.");
17276
17283
  process.exit(0);
17277
17284
  }
17278
- opts.ide = editorChoice;
17285
+ opts.ides = editorChoices;
17279
17286
  const langChoice = await select({
17280
17287
  message: "Communication language?",
17281
17288
  options: [
@@ -17332,7 +17339,7 @@ Say "plan a sprint" or run \`/rihal-sprint-planning\` to break Phase 01 into sto
17332
17339
  note(
17333
17340
  [
17334
17341
  `${pc.dim("Directory:")} ${opts.target}`,
17335
- `${pc.dim("Editor:")} ${opts.ide}`,
17342
+ `${pc.dim("Editor:")} ${opts.ides.join(", ")}`,
17336
17343
  `${pc.dim("Language:")} ${opts.language}`,
17337
17344
  `${pc.dim("Mode:")} ${opts.mode}`,
17338
17345
  `${pc.dim("Planning:")} ${opts.commitPlanning ? "committed to git" : "kept local (gitignored)"}`,
@@ -17767,7 +17774,8 @@ var require_update = __commonJS({
17767
17774
  var fs2 = require("fs");
17768
17775
  var path2 = require("path");
17769
17776
  var { spawnSync } = require("child_process");
17770
- var { askConfirm, askChoice, PromptAbortError } = require_prompts();
17777
+ var clack = require_dist3();
17778
+ var { PromptAbortError } = require_prompts();
17771
17779
  var { writeJsonAtomic } = require_fsutil();
17772
17780
  var { verifyInstall, formatReport } = require_manifest();
17773
17781
  var install = require_install();
@@ -17964,31 +17972,27 @@ var require_update = __commonJS({
17964
17972
  const ALL_EDITORS = ["claude", "cursor", "gemini"];
17965
17973
  const missing = ALL_EDITORS.filter((e) => !editors.includes(e));
17966
17974
  if (missing.length > 0) {
17967
- const choices = [
17968
- { id: "no", label: `No \u2014 refresh existing only (${editors.join(", ")})` },
17969
- ...missing.map((e) => ({ id: e, label: `Add ${e}` })),
17970
- { id: "all", label: "Add all missing editors" }
17971
- ];
17972
- const answer = await askChoice(
17973
- `Add support for additional editors?`,
17974
- { choices, default: "no" }
17975
- );
17976
- const picked = answer[0];
17977
- if (picked === "all") {
17978
- for (const e of missing) editors.push(e);
17979
- } else if (picked !== "no") {
17980
- editors.push(picked);
17975
+ const editorLabels = { claude: "Claude Code", cursor: "Cursor", gemini: "Gemini CLI" };
17976
+ const selected = await clack.multiselect({
17977
+ message: "Add support for additional editors?",
17978
+ options: missing.map((e) => ({ value: e, label: editorLabels[e] || e })),
17979
+ required: false
17980
+ });
17981
+ if (clack.isCancel(selected)) {
17982
+ clack.cancel("Update cancelled.");
17983
+ process.exit(0);
17981
17984
  }
17985
+ for (const e of selected) editors.push(e);
17982
17986
  console.log(` Editors to update: ${editors.join(", ")}`);
17983
17987
  console.log();
17984
17988
  }
17985
17989
  }
17986
17990
  if (!opts.yes) {
17987
- const proceed = await askConfirm(
17988
- `Proceed with update? [y/N] `,
17989
- { default: "n" }
17990
- );
17991
- if (!proceed) {
17991
+ const proceed = await clack.confirm({
17992
+ message: "Proceed with update?",
17993
+ initialValue: false
17994
+ });
17995
+ if (clack.isCancel(proceed) || !proceed) {
17992
17996
  console.log(`
17993
17997
  \u274C Update cancelled. Nothing changed.`);
17994
17998
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzlaa/rcode",
3
- "version": "3.3.2",
3
+ "version": "3.4.1",
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": {
@@ -8,14 +8,6 @@
8
8
  "rihal": "dist/rcode.js",
9
9
  "rihal-code": "dist/rcode.js"
10
10
  },
11
- "scripts": {
12
- "dashboard": "node server/dashboard.js",
13
- "test": "node --test",
14
- "test:ci": "node --test --test-reporter=spec",
15
- "postinstall": "node cli/postinstall.js",
16
- "build:cli": "node scripts/build.cjs",
17
- "build": "node scripts/build.cjs"
18
- },
19
11
  "files": [
20
12
  "cli/",
21
13
  "rihal/",
@@ -70,5 +62,13 @@
70
62
  },
71
63
  "publishConfig": {
72
64
  "access": "public"
65
+ },
66
+ "scripts": {
67
+ "dashboard": "node server/dashboard.js",
68
+ "test": "node --test",
69
+ "test:ci": "node --test --test-reporter=spec",
70
+ "postinstall": "node cli/postinstall.js",
71
+ "build:cli": "node scripts/build.cjs",
72
+ "build": "node scripts/build.cjs"
73
73
  }
74
- }
74
+ }
@@ -6,6 +6,7 @@ color: cyan
6
6
  ---
7
7
 
8
8
  @.rihal/references/response-style.md
9
+ @.rihal/references/karpathy-guidelines.md
9
10
 
10
11
 
11
12
 
@@ -114,4 +115,3 @@ ecosystem best practices, etc. Leave empty if codebase provides enough evidence.
114
115
  - validate assumptions against available evidence
115
116
  - document assumption risk and impact
116
117
  - preserve plan context and objectives
117
- - return clear assumption list with validation status