@hanzlaa/rcode 4.1.1 → 4.1.2

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 (41) hide show
  1. package/AGENTS.md +1 -1
  2. package/CONTRIBUTING.md +3 -0
  3. package/README.md +3 -0
  4. package/cli/agent.js +3 -1
  5. package/cli/index.js +29 -0
  6. package/cli/install.js +58 -3
  7. package/cli/workflow.js +3 -1
  8. package/dist/rcode.js +171 -161
  9. package/package.json +1 -1
  10. package/rcode/bin/rcode-tools.cjs +15 -6
  11. package/rcode/commands/scaffold-project.md +2 -2
  12. package/rcode/skills/actions/2-plan/rcode-create-epics-and-stories/steps/step-04-final-validation.md +1 -1
  13. package/rcode/skills/actions/2-plan/rcode-create-milestone/steps/README.md +2 -2
  14. package/rcode/skills/actions/2-plan/rcode-create-milestone/steps/step-09-state-sync.md +1 -1
  15. package/rcode/skills/actions/4-implementation/rcode-code-review/steps/step-02-review.md +1 -1
  16. package/rcode/skills/actions/4-implementation/rcode-git-flow/SKILL.md +1 -1
  17. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/SKILL.md +39 -12
  18. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/steps/step-01-target.md +18 -3
  19. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/steps/step-02-safety.md +27 -3
  20. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/steps/step-03-brownfield.md +57 -0
  21. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/steps/step-03-clone.md +4 -1
  22. package/rcode/skills/actions/4-implementation/rcode-scaffold-project/steps/step-04-post-setup.md +15 -1
  23. package/rcode/skills/actions/4-implementation/rcode-trim/SKILL.md +1 -1
  24. package/rcode/workflows/audit-milestone.md +1 -1
  25. package/rcode/workflows/discuss-phase.md +1 -1
  26. package/rcode/workflows/execute-milestone.md +1 -1
  27. package/rcode/workflows/execute-regression-gates.md +3 -0
  28. package/rcode/workflows/execute-sprint.md +27 -1
  29. package/rcode/workflows/execute-waves.md +6 -0
  30. package/rcode/workflows/execute.md +13 -3
  31. package/rcode/workflows/new-milestone.md +2 -2
  32. package/rcode/workflows/new-project.md +4 -0
  33. package/rcode/workflows/plan-research-validation.md +1 -1
  34. package/rcode/workflows/plan-spawn-planner.md +2 -2
  35. package/rcode/workflows/plan.md +34 -15
  36. package/rcode/workflows/review.md +2 -0
  37. package/rcode/workflows/scaffold-project.md +5 -1
  38. package/rcode/workflows/session-report.md +1 -1
  39. package/rcode/workflows/ship.md +39 -0
  40. package/rcode/workflows/sprint-planning.md +27 -0
  41. package/rcode/workflows/status.md +3 -3
package/AGENTS.md CHANGED
@@ -24,7 +24,7 @@ If a user says "just keep going" or "don't stop until done", that authorization
24
24
 
25
25
  - Follow [Conventional Commits](https://www.conventionalcommits.org/) format: `type(scope): subject`
26
26
  - Types allowed: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `perf`, `revert`
27
- - Scopes allowed: `agents`, `skills`, `workflows`, `templates`, `dashboard`, `docs`, `config`, `github`, `commands`, `memory`, `brand`, `cli`, `ci`, `release`, `meta`, `tasks`, `migrations`, `refs`, `state`, `hooks`, `install`, `parity`, `triggers`, `dogfood`, `namespace`, `planning`, `insights`, `help`, `roadmap`, `session`, `audits`, `execute`, `executor`, `plan`, `planner`, `readme`, `sync`, `sprint`, `agent-exp`, `extensibility`, `lens-audit`, `tiers`, `build`, `council`, `doctor`, `postinstall`, `progress`, `security`, `tools`, `uninstall`, `update`, `test`, `changelog`, `scopes`, `phases`, `references`, `kanban`, `orchestrator`, `orchpanel`, `status`, `bin`, `brain`, `dogfeed`, `new-project`, `package`, `rcode-tools`, `rihal-tools`, `team`, `usp`, `v4`, `observability`, `audit`, `agent-rules`, `cursor`, `i18n`, `phase`, plus numeric phase/sprint scopes (e.g. `docs(15)`, `feat(8.3)`)
27
+ - Scopes allowed: `agents`, `skills`, `workflows`, `templates`, `dashboard`, `docs`, `config`, `github`, `commands`, `memory`, `brand`, `cli`, `ci`, `release`, `meta`, `tasks`, `migrations`, `refs`, `state`, `hooks`, `install`, `parity`, `triggers`, `dogfood`, `namespace`, `planning`, `insights`, `help`, `roadmap`, `session`, `audits`, `execute`, `executor`, `plan`, `planner`, `readme`, `sync`, `sprint`, `agent-exp`, `extensibility`, `lens-audit`, `tiers`, `build`, `council`, `doctor`, `postinstall`, `progress`, `security`, `tools`, `uninstall`, `update`, `test`, `changelog`, `scopes`, `phases`, `references`, `kanban`, `orchestrator`, `orchpanel`, `status`, `bin`, `brain`, `dogfeed`, `new-project`, `package`, `rcode-tools`, `rihal-tools`, `team`, `usp`, `v4`, `observability`, `audit`, `agent-rules`, `cursor`, `i18n`, `phase`, `scaffold`, `campaign`, `ship`, plus numeric phase/sprint scopes (e.g. `docs(15)`, `feat(8.3)`)
28
28
  - Subject: lowercase first letter, imperative mood, no trailing period, under 72 chars
29
29
  - **NEVER add Claude/AI attribution to commit messages.** No "Generated with Claude Code", no "Co-Authored-By: Claude", no "šŸ¤– Generated". The user does not want this.
30
30
  - **NEVER use `--no-verify`** to bypass hooks. If hooks fail, fix the underlying issue.
package/CONTRIBUTING.md CHANGED
@@ -349,6 +349,9 @@ We use [Conventional Commits](https://www.conventionalcommits.org/) format. The
349
349
  - `cursor` — Cursor IDE rules under `.cursor/rules/rcode/`
350
350
  - `i18n` — internationalization, brand strings, and user-visible copy
351
351
  - `phase` — phase-lifecycle changes (variable renames, phase-loop fixes); use numeric `<phase-id>` for in-phase commits
352
+ - `scaffold` — scaffold-project workflow changes
353
+ - `campaign` — fix-campaign orchestration tracking files
354
+ - `ship` — ship workflow changes
352
355
  - `<phase-id>` — numeric phase scope when committing inside a phase (e.g. `docs(15)`, `feat(8.3)`)
353
356
  - `<sprint-id>` — numeric sprint scope inside a phase (e.g. `feat(15.1)`)
354
357
 
package/README.md CHANGED
@@ -117,6 +117,9 @@ pnpm dlx @hanzlaa/rcode install
117
117
  /rcode-init
118
118
  ```
119
119
 
120
+ > **Don't have pnpm?** On Node 18+ / npm 11.x we recommend pnpm to avoid `npx` cache issues:
121
+ > `npm install -g pnpm`
122
+
120
123
  `/rcode-init` detects your project state (fresh / existing / returning) and routes to the right first action. For a greenfield project it auto-routes to `/rcode-new-project`.
121
124
 
122
125
  ### The full loop
package/cli/agent.js CHANGED
@@ -24,7 +24,9 @@ module.exports = function agent(args, { packageRoot }) {
24
24
  }
25
25
 
26
26
  const name = args[0];
27
- const agentName = `rcode-${name}`;
27
+ // Strip rcode- prefix if already provided so rcode agent rcode-executor works (#882)
28
+ const bare = name.startsWith('rcode-') ? name.slice('rcode-'.length) : name;
29
+ const agentName = `rcode-${bare}`;
28
30
 
29
31
  // Validate agent file exists
30
32
  const agentFile = path.join(agentDir, `${agentName}.md`);
package/cli/index.js CHANGED
@@ -34,6 +34,10 @@ const COMMANDS = {
34
34
  agent: require('./agent'),
35
35
  doctor: require('./doctor'),
36
36
  workflow: require('./workflow'), // lifecycle bridge for non-Claude runtimes
37
+ // Thin lifecycle aliases — delegate to workflow show <name> (#883)
38
+ plan: (args, ctx) => lifecycleAlias('plan', args, ctx),
39
+ execute: (args, ctx) => lifecycleAlias('execute-sprint', args, ctx),
40
+ ship: (args, ctx) => lifecycleAlias('ship', args, ctx),
37
41
  'set-profile': require('./set-profile'),
38
42
  'set-mode': require('./set-mode'),
39
43
  config: require('./config'),
@@ -70,6 +74,9 @@ Usage:
70
74
  github-sync Sync .rcode/ phases/epics/stories to GitHub (dry-run default)
71
75
 
72
76
  šŸ”„ LIFECYCLE (Codex / Copilot / Grok bridge)
77
+ plan Print the plan workflow (alias for workflow show plan)
78
+ execute Print the execute-sprint workflow
79
+ ship Print the ship workflow
73
80
  workflow list List all lifecycle workflow names
74
81
  workflow show <name> Print a workflow's full instructions to stdout
75
82
  workflow show new-project → project setup + ROADMAP
@@ -82,6 +89,7 @@ Usage:
82
89
  workflow show ship → deploy / release workflow
83
90
 
84
91
  Non-Claude agents: pipe to your agent instead of using slash commands.
92
+ Example: rcode plan | codex run -
85
93
  Example: rcode workflow show plan | codex run -
86
94
 
87
95
  šŸ‘„ TEAM
@@ -91,6 +99,7 @@ Usage:
91
99
  rcode agent --list to see available agents
92
100
  show-model Show which model each agent uses in the current profile
93
101
  dashboard Start the Diwan view-only dashboard (port 7717)
102
+ Starts a view-only dashboard at http://localhost:7717. No write access.
94
103
  serve Alias for dashboard
95
104
 
96
105
  āš™ļø META
@@ -111,6 +120,26 @@ Documentation: https://github.com/hanzlahabib/rihal-code
111
120
  `.trim());
112
121
  }
113
122
 
123
+ /**
124
+ * Lifecycle aliases (plan/execute/ship): show the workflow then print actionable
125
+ * next-step guidance so the user knows how to actually run it.
126
+ */
127
+ function lifecycleAlias(workflowName, args, ctx) {
128
+ require('./workflow')(['show', workflowName, ...args], ctx);
129
+
130
+ const hasAuto = args.includes('--auto') || args.includes('--run');
131
+
132
+ console.log('\n─────────────────────────────────────────────');
133
+ console.log(`ā–¶ To run: paste the above into Claude Code as /${workflowName === 'execute-sprint' ? 'rcode-execute-sprint' : `rcode-${workflowName}`}`);
134
+ console.log(' or pipe it directly: rcode ' + (workflowName === 'execute-sprint' ? 'execute' : workflowName) + ' | cld --model sonnet');
135
+
136
+ if (hasAuto) {
137
+ console.log('\n AUTO mode detected — in Claude Code run: /rcode-' +
138
+ (workflowName === 'execute-sprint' ? 'execute-sprint' : workflowName) +
139
+ ' --auto (applies yolo defaults, skips confirmation prompts)');
140
+ }
141
+ }
142
+
114
143
  /**
115
144
  * npm 10+ suppresses postinstall script output during global installs, so users
116
145
  * who run `npm install -g @hanzlaa/rcode` see only "added 1 package" with no
package/cli/install.js CHANGED
@@ -89,7 +89,7 @@ const SOURCE_ROOT = path.join(PACKAGE_ROOT, 'rcode');
89
89
  * detectIdeSignals, plus a row to runInstallWizard's multiselect — three
90
90
  * sites instead of ten.
91
91
  */
92
- const SUPPORTED_IDES = Object.freeze(['claude', 'cursor', 'gemini', 'vscode', 'antigravity', 'windsurf']);
92
+ const SUPPORTED_IDES = Object.freeze(['claude', 'cursor', 'gemini', 'vscode', 'antigravity', 'windsurf', 'codex']);
93
93
 
94
94
  /**
95
95
  * Resolve the stable on-disk location of this package so config.yaml
@@ -197,6 +197,9 @@ function parseArgs(argv) {
197
197
  silent: false,
198
198
  // noPrompt — skip all interactive prompts (used by postinstall auto-run)
199
199
  noPrompt: false,
200
+ // dry-run / list-files — preview paths that would be written, then exit
201
+ dryRun: false,
202
+ listFiles: false,
200
203
  };
201
204
  const positional = [];
202
205
  for (let i = 0; i < argv.length; i++) {
@@ -231,6 +234,8 @@ function parseArgs(argv) {
231
234
  else if (arg === '--global') opts.global = true;
232
235
  else if (arg === '--silent') opts.silent = true;
233
236
  else if (arg === '--no-prompt') opts.noPrompt = true;
237
+ else if (arg === '--dry-run') opts.dryRun = true;
238
+ else if (arg === '--list-files') opts.listFiles = true;
234
239
  else if (!arg.startsWith('--')) positional.push(arg);
235
240
  }
236
241
  if (positional[0]) {
@@ -372,7 +377,7 @@ function printInstallHeader(targetVersion) {
372
377
  * Returns a set like { claude: true, cursor: false, gemini: false }.
373
378
  */
374
379
  function detectIdeSignals(target) {
375
- const signals = { claude: false, cursor: false, gemini: false, vscode: false, antigravity: false, windsurf: false };
380
+ const signals = { claude: false, cursor: false, gemini: false, vscode: false, antigravity: false, windsurf: false, codex: false };
376
381
  // 1. Project-local install dirs (strongest signal — they already use one)
377
382
  if (fs.existsSync(path.join(target, '.claude'))) signals.claude = true;
378
383
  if (fs.existsSync(path.join(target, '.cursor'))) signals.cursor = true;
@@ -396,6 +401,7 @@ function detectIdeSignals(target) {
396
401
  if (process.env.CLAUDECODE === '1' || process.env.CLAUDE_CODE_ENTRYPOINT) signals.claude = true;
397
402
  if (process.env.VSCODE_PID || /vscode/i.test(process.env.TERM_PROGRAM || '')) signals.vscode = true;
398
403
  if (/windsurf/i.test(process.env.TERM_PROGRAM || '')) signals.windsurf = true;
404
+ if (process.env.CODEX_ENV || /codex/i.test(process.env.TERM_PROGRAM || '')) signals.codex = true;
399
405
  return signals;
400
406
  }
401
407
 
@@ -442,6 +448,7 @@ async function resolveIde(opts) {
442
448
  options: [
443
449
  { value: 'claude', label: 'Claude Code', hint: signals.claude ? '(detected)' : undefined },
444
450
  { value: 'cursor', label: 'Cursor', hint: signals.cursor ? '(detected)' : undefined },
451
+ { value: 'codex', label: 'Codex (OpenAI CLI)', hint: signals.codex ? '(detected)' : '(uses AGENTS.md + workflow bridge)' },
445
452
  { value: 'gemini', label: 'Gemini CLI', hint: signals.gemini ? '(detected)' : '(beta — limited)' },
446
453
  { value: 'vscode', label: 'VS Code', hint: signals.vscode ? '(detected)' : '(via Continue / Copilot extensions)' },
447
454
  { value: 'antigravity', label: 'Antigravity', hint: '(experimental — installs to .antigravity/)' },
@@ -522,6 +529,8 @@ Options:
522
529
  --language <lang> set communication_language (default: English)
523
530
  --mode <guided|yolo> default mode (default: guided)
524
531
  --ide <name> target IDE (claude, cursor, gemini; default: claude)
532
+ --dry-run preview what would be written; exit without writing any files
533
+ --list-files alias for --dry-run
525
534
  --help this text
526
535
 
527
536
  Installs (IDE-specific):
@@ -601,6 +610,18 @@ function getPathsForIde(ide, target) {
601
610
  referencesDir: path.join(target, '.rcode', 'references'),
602
611
  binDir: path.join(target, '.rcode', 'bin'),
603
612
  };
613
+ case 'codex':
614
+ // OpenAI Codex CLI reads AGENTS.md from the project root (written by the
615
+ // claude/vscode install paths). We install agent + command files to .claude/
616
+ // so multi-IDE installs share files, and the rcode workflow bridge gives
617
+ // Codex access to lifecycle workflows via `rcode workflow show <name>` (#883).
618
+ return {
619
+ agentsDir: path.join(target, '.claude', 'agents'),
620
+ commandsDir: path.join(target, '.claude', 'commands'),
621
+ workflowsDir: path.join(target, '.rcode', 'workflows'),
622
+ referencesDir: path.join(target, '.rcode', 'references'),
623
+ binDir: path.join(target, '.rcode', 'bin'),
624
+ };
604
625
  default:
605
626
  throw new Error(`Unknown IDE: ${ide}. Supported: ${SUPPORTED_IDES.join(', ')}`);
606
627
  }
@@ -1929,7 +1950,8 @@ async function installInner(opts) {
1929
1950
  console.error(' Currently supported:');
1930
1951
  console.error(' claude — Claude Code native (recommended)');
1931
1952
  console.error(' cursor — Cursor IDE');
1932
- console.error(' gemini — Gemini CLI');
1953
+ console.error(' codex — Codex CLI');
1954
+ console.error(' gemini — Gemini CLI (planned — not yet implemented)');
1933
1955
  console.error(' vscode — VS Code (with Claude Code / Continue / Copilot extension)');
1934
1956
  console.error(' windsurf — Windsurf (Codeium)');
1935
1957
  console.error(' antigravity — Antigravity (experimental)');
@@ -1946,6 +1968,11 @@ async function installInner(opts) {
1946
1968
  console.log(' ' + dim('VS Code → installing to .claude/ paths (read by Claude Code / Continue / Copilot extensions).'));
1947
1969
  }
1948
1970
 
1971
+ // Codex installs to .claude/ and AGENTS.md; lifecycle via rcode workflow bridge.
1972
+ if (opts.ides.includes('codex')) {
1973
+ console.log(' ' + dim('Codex → installing to .claude/ paths + AGENTS.md. Use `rcode workflow show <name>` to feed workflows to Codex.'));
1974
+ }
1975
+
1949
1976
  // Gemini IDE support deferred
1950
1977
  if (opts.ides.includes('gemini')) {
1951
1978
  console.log(`\nāš ļø Gemini CLI install not yet implemented\n`);
@@ -1994,6 +2021,15 @@ async function installInner(opts) {
1994
2021
  console.log(` Modules: ${opts.modules.join(', ')}`);
1995
2022
  }
1996
2023
 
2024
+ // Dry run / list-files — list paths that would be written and exit without writing
2025
+ if (opts.dryRun || opts.listFiles) {
2026
+ console.log('DRY RUN: the following paths would be written:');
2027
+ for (const entry of plan) {
2028
+ console.log(' + ' + entry.rel);
2029
+ }
2030
+ return 0;
2031
+ }
2032
+
1997
2033
  // Force-overwrite backup — closes #381. Without this, customized
1998
2034
  // .claude/agents/rcode-*.md and similar package-managed files were silently
1999
2035
  // clobbered with no recovery path. Now every --force-overwrite run creates
@@ -2667,6 +2703,24 @@ async function installInner(opts) {
2667
2703
  console.error('[install] installInner: failed to count installed agents/commands:', err?.message || err);
2668
2704
  }
2669
2705
 
2706
+ // Duplicate-namespace detection: warn when both rcode-* and rihal-* entries exist.
2707
+ // Having both doubles the roster size with near-identical content.
2708
+ try {
2709
+ const skillsDir = path.join(opts.target, '.rcode', 'skills');
2710
+ const claudeCommandsDir = path.join(opts.target, '.claude', 'commands');
2711
+ const dirsToCheck = [skillsDir, claudeCommandsDir];
2712
+ let hasRcode = false, hasRihal = false;
2713
+ for (const dir of dirsToCheck) {
2714
+ if (!fs.existsSync(dir)) continue;
2715
+ const entries = fs.readdirSync(dir);
2716
+ if (entries.some(e => e.startsWith('rcode-'))) hasRcode = true;
2717
+ if (entries.some(e => e.startsWith('rihal-'))) hasRihal = true;
2718
+ }
2719
+ if (hasRcode && hasRihal) {
2720
+ process.stderr.write(pc.yellow('WARNING: rcode-* and rihal-* namespaces both detected — consider removing one to reduce roster size.') + '\n');
2721
+ }
2722
+ } catch { /* non-fatal */ }
2723
+
2670
2724
  const version = readPackageVersion();
2671
2725
  console.log('');
2672
2726
  console.log(` ${bold('Version:')} ${pc.cyan('@hanzlaa/rcode@' + version)}`);
@@ -2915,6 +2969,7 @@ async function runInstallWizard(opts) {
2915
2969
  options: [
2916
2970
  { value: 'claude', label: 'Claude Code', hint: 'recommended' },
2917
2971
  { value: 'cursor', label: 'Cursor' },
2972
+ { value: 'codex', label: 'Codex (OpenAI CLI)', hint: 'AGENTS.md + workflow bridge' },
2918
2973
  { value: 'gemini', label: 'Gemini CLI', hint: 'coming soon' },
2919
2974
  { value: 'vscode', label: 'VS Code', hint: 'via Continue / Copilot extensions' },
2920
2975
  { value: 'antigravity', label: 'Antigravity', hint: 'experimental' },
package/cli/workflow.js CHANGED
@@ -73,9 +73,11 @@ function listWorkflows(workflowsDir) {
73
73
  }
74
74
 
75
75
  function showWorkflow(workflowsDir, name) {
76
+ // Normalise: strip rcode- prefix so both `plan` and `rcode-plan` resolve (#883)
77
+ const bare = name.startsWith('rcode-') ? name.slice('rcode-'.length) : name;
76
78
  const candidates = [
79
+ path.join(workflowsDir, `${bare}.md`),
77
80
  path.join(workflowsDir, `${name}.md`),
78
- path.join(workflowsDir, `rcode-${name}.md`),
79
81
  ];
80
82
 
81
83
  for (const p of candidates) {