@mfjjs/ruflo-setup 0.2.4 β†’ 0.2.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.2.6](///compare/v0.2.5...v0.2.6) (2026-03-20)
6
+
7
+
8
+ ### Features
9
+
10
+ * **cli:** add cleanup command to remove Ruflo packages from npm global registry. 5151c70
11
+
12
+ ### [0.2.5](///compare/v0.2.4...v0.2.5) (2026-03-17)
13
+
5
14
  ### [0.2.4](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.2.3...v0.2.4) (2026-03-17)
6
15
 
7
16
  ### [0.2.3](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.2.2...v0.2.3) (2026-03-14)
package/README.md CHANGED
@@ -16,7 +16,7 @@ Cross-platform npm CLI to bootstrap a project with Ruflo on Windows and Linux.
16
16
  <summary>Click to toggle visibility</summary>
17
17
 
18
18
  - Node.js 20+
19
- - pnpm available on PATH
19
+ - pnpm **10.32.1 or higher** available on PATH
20
20
 
21
21
  Quickest pnpm install by platform:
22
22
 
@@ -42,9 +42,12 @@ corepack prepare pnpm@latest --activate
42
42
  ## πŸ“¦ Installation
43
43
 
44
44
  ```powershell
45
- pnpm -i -g @mfjjs/ruflo-setup
45
+ pnpm add -g @mfjjs/ruflo-setup
46
+ ruflo-setup cleanup
46
47
  ```
47
48
 
49
+ > **Why run `cleanup` first?** If you previously installed any Ruflo packages via `npm install -g` (e.g. `ruflo`, `claude-flow`, `ruv-swarm`), those npm-global copies can shadow or conflict with the pnpm-managed versions. `ruflo-setup cleanup` removes them from the npm global registry before setup runs, giving you a clean slate.
50
+
48
51
  ## πŸ’‘ Why You Need This
49
52
 
50
53
  If you’re working on:
@@ -60,6 +63,20 @@ You only need to do this once in each folder. Just run the command and you’re
60
63
 
61
64
  ## πŸš€ Usage
62
65
 
66
+ ### Cleanup
67
+ Remove any previous npm global installs of Ruflo packages that could conflict with the pnpm-managed versions:
68
+
69
+ ```bash
70
+ ruflo-setup cleanup
71
+ ```
72
+
73
+ This uninstalls `ruflo`, `@mfjjs/ruflo-setup`, `ruflo-setup`, `claude-flow`, `@claude-flow/cli`, and `ruv-swarm` from the **npm** global registry. It does not touch pnpm globals. Run this before setup if you suspect stale npm globals are shadowing the pnpm-installed binaries.
74
+
75
+ ```bash
76
+ # preview what would be removed without making changes
77
+ ruflo-setup cleanup --dry-run
78
+ ```
79
+
63
80
  ### Status
64
81
  Check whether all Ruflo feature layers (0–8) are enabled in the current project:
65
82
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mfjjs/ruflo-setup",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Cross-platform setup CLI for Ruflo + Claude Flow projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,9 +26,14 @@
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "http:s://github.com/mfjassociates/ruflo-setup.git"
32
+ },
29
33
  "bugs": {
30
34
  "url": "https://github.com/mfjassociates/ruflo-setup/issues"
31
35
  },
36
+ "homepage": "https://github.com/mfjassociates/ruflo-setup#readme",
32
37
  "license": "MIT",
33
38
  "scripts": {
34
39
  "lint": "node --check ./src/cli.js && node --check ./src/setup.js && node --check ./src/hooks.js && node --check ./src/utils.js && node --check ./bin/ruflo-setup.js",
package/src/cli.js CHANGED
@@ -2,7 +2,7 @@ import path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { createRequire } from 'node:module';
4
4
  import { parseArgs } from './utils.js';
5
- import { runSetup } from './setup.js';
5
+ import { runSetup, runCleanup } from './setup.js';
6
6
  import { getGlobalHookStatus, installGlobalCheckRufloHook } from './hooks.js';
7
7
 
8
8
  const require = createRequire(import.meta.url);
@@ -19,6 +19,7 @@ function printHelp() {
19
19
  Usage:
20
20
  ruflo-setup [options]
21
21
  ruflo-setup status
22
+ ruflo-setup cleanup [--dry-run]
22
23
  ruflo-setup hooks install [options]
23
24
  ruflo-setup hooks status
24
25
 
@@ -31,9 +32,15 @@ Options:
31
32
  --version, -v Print version and exit
32
33
  --verbose Extra output
33
34
 
35
+ Commands:
36
+ cleanup Remove all Ruflo packages from the npm global registry
37
+ (ruflo, @mfjjs/ruflo-setup, claude-flow, @claude-flow/cli, ruv-swarm)
38
+
34
39
  Examples:
35
40
  ruflo-setup
36
41
  ruflo-setup status
42
+ ruflo-setup cleanup
43
+ ruflo-setup cleanup --dry-run
37
44
  ruflo-setup --dry-run --skip-init
38
45
  ruflo-setup hooks status
39
46
  ruflo-setup hooks install --dry-run
@@ -93,6 +100,19 @@ export async function runCli(argv, cwd) {
93
100
  return 1;
94
101
  }
95
102
 
103
+ if (flags.command === 'cleanup') {
104
+ if (!flags.dryRun && !flags.yes) {
105
+ const { confirm } = await import('./utils.js');
106
+ const ok = await confirm('Remove Ruflo packages from npm global registry? [y/N] ');
107
+ if (!ok) {
108
+ process.stdout.write('Aborted. No changes made.\n');
109
+ return 0;
110
+ }
111
+ }
112
+ runCleanup({ dryRun: flags.dryRun });
113
+ return 0;
114
+ }
115
+
96
116
  await runSetup({
97
117
  cwd,
98
118
  packageRoot,
package/src/setup.js CHANGED
@@ -33,30 +33,49 @@ function getPnpmInstallSuggestions(platform) {
33
33
  ];
34
34
  }
35
35
 
36
+ const MIN_PNPM_VERSION = '10.32.1';
37
+
38
+ function parseSemver(str) {
39
+ const [major = 0, minor = 0, patch = 0] = str.trim().split('.').map(Number);
40
+ return { major, minor, patch };
41
+ }
42
+
43
+ function semverGte(a, b) {
44
+ if (a.major !== b.major) return a.major > b.major;
45
+ if (a.minor !== b.minor) return a.minor > b.minor;
46
+ return a.patch >= b.patch;
47
+ }
48
+
36
49
  function ensurePnpmAvailable() {
37
50
  const check = spawnSync('pnpm', ['--version'], {
38
- stdio: 'ignore',
51
+ stdio: ['ignore', 'pipe', 'ignore'],
39
52
  shell: process.platform === 'win32'
40
53
  });
41
54
 
42
- if (check.status === 0 && !check.error) {
43
- return;
55
+ if (check.status !== 0 || check.error) {
56
+ const platformLabel = process.platform === 'win32'
57
+ ? 'Windows'
58
+ : process.platform === 'darwin'
59
+ ? 'macOS'
60
+ : 'Linux';
61
+ const suggestions = getPnpmInstallSuggestions(process.platform)
62
+ .map((command) => ` - ${command}`)
63
+ .join('\n');
64
+
65
+ throw new Error(
66
+ `pnpm is required but was not found in PATH.\n` +
67
+ `Install pnpm, then re-run ruflo-setup.\n` +
68
+ `Quick install options for ${platformLabel}:\n${suggestions}`
69
+ );
44
70
  }
45
71
 
46
- const platformLabel = process.platform === 'win32'
47
- ? 'Windows'
48
- : process.platform === 'darwin'
49
- ? 'macOS'
50
- : 'Linux';
51
- const suggestions = getPnpmInstallSuggestions(process.platform)
52
- .map((command) => ` - ${command}`)
53
- .join('\n');
54
-
55
- throw new Error(
56
- `pnpm is required but was not found in PATH.\n` +
57
- `Install pnpm, then re-run ruflo-setup.\n` +
58
- `Quick install options for ${platformLabel}:\n${suggestions}`
59
- );
72
+ const version = (check.stdout || '').toString().trim();
73
+ if (!semverGte(parseSemver(version), parseSemver(MIN_PNPM_VERSION))) {
74
+ throw new Error(
75
+ `pnpm ${MIN_PNPM_VERSION} or higher is required, but found ${version}.\n` +
76
+ `Upgrade with: pnpm self-update`
77
+ );
78
+ }
60
79
  }
61
80
 
62
81
  function runPnpmInit({ force, cwd, dryRun }) {
@@ -67,22 +86,46 @@ function runPnpmInit({ force, cwd, dryRun }) {
67
86
 
68
87
  if (dryRun) {
69
88
  logLine(` [DRY RUN] Would run: pnpm add -g ruflo@latest`);
89
+ logLine(` [DRY RUN] Would run: pnpm approve-builds -g --all (if changes detected)`);
70
90
  logLine(` [DRY RUN] Would run: ruflo ${initArgs.join(' ')}`);
71
91
  return;
72
92
  }
73
93
 
74
94
  ensurePnpmAvailable();
75
95
 
96
+ // Capture stdout to detect whether pnpm installed/updated anything.
97
+ // Progress spinners go to stderr (still shown to user); stdout has the summary.
76
98
  const install = spawnSync('pnpm', ['add', '-g', 'ruflo@latest'], {
77
99
  cwd,
78
- stdio: 'inherit',
100
+ stdio: ['inherit', 'pipe', 'inherit'],
79
101
  shell: process.platform === 'win32'
80
102
  });
81
103
 
104
+ const installOutput = (install.stdout || '').toString();
105
+ if (installOutput) {
106
+ process.stdout.write(installOutput);
107
+ }
108
+
82
109
  if (install.status !== 0) {
83
110
  throw new Error(`pnpm add -g ruflo@latest failed with exit code ${install.status}`);
84
111
  }
85
112
 
113
+ // pnpm prints a "Packages:" summary line and "+ pkg version" lines when
114
+ // something is actually installed or updated. When already up to date the
115
+ // stdout is empty or contains only "Already up to date".
116
+ const somethingChanged = /Packages:/i.test(installOutput) || /^\+\s/m.test(installOutput);
117
+ if (somethingChanged) {
118
+ logLine(' Changes detected β€” running pnpm approve-builds -g --all ...');
119
+ const approve = spawnSync('pnpm', ['approve-builds', '-g', '--all'], {
120
+ cwd,
121
+ stdio: 'inherit',
122
+ shell: process.platform === 'win32'
123
+ });
124
+ if (approve.status !== 0) {
125
+ throw new Error(`pnpm approve-builds -g --all failed with exit code ${approve.status}`);
126
+ }
127
+ }
128
+
86
129
  const run = spawnSync('ruflo', initArgs, {
87
130
  cwd,
88
131
  stdio: 'inherit',
@@ -233,3 +276,37 @@ export async function runSetup({
233
276
  logLine(' 2. Run: claude');
234
277
  logLine(' 3. Verify hooks: ruflo-setup hooks status');
235
278
  }
279
+
280
+ const CLEANUP_NPM_PACKAGES = [
281
+ 'ruflo',
282
+ '@mfjjs/ruflo-setup',
283
+ 'ruflo-setup',
284
+ 'claude-flow',
285
+ '@claude-flow/cli',
286
+ 'ruv-swarm'
287
+ ];
288
+
289
+ export function runCleanup({ dryRun = false } = {}) {
290
+ logLine('');
291
+ logLine('Ruflo Cleanup β€” removing from npm global registry');
292
+ logLine(`Packages: ${CLEANUP_NPM_PACKAGES.join(', ')}`);
293
+ logLine('');
294
+
295
+ if (dryRun) {
296
+ logLine(` [DRY RUN] Would run: npm uninstall -g ${CLEANUP_NPM_PACKAGES.join(' ')}`);
297
+ logLine('');
298
+ return;
299
+ }
300
+
301
+ const result = spawnSync('npm', ['uninstall', '-g', ...CLEANUP_NPM_PACKAGES], {
302
+ stdio: 'inherit',
303
+ shell: process.platform === 'win32'
304
+ });
305
+
306
+ if (result.status !== 0) {
307
+ throw new Error(`npm uninstall -g failed with exit code ${result.status}`);
308
+ }
309
+
310
+ logLine('');
311
+ logLine('Cleanup complete.');
312
+ }
@@ -5,7 +5,7 @@ Set up Ruflo + Claude Flow V3 in the current project directory.
5
5
  ## Requirements
6
6
 
7
7
  - Node.js 20+
8
- - pnpm installed and available on PATH
8
+ - pnpm 10.32.1+ installed and available on PATH
9
9
 
10
10
  Quickest pnpm install by platform:
11
11
 
@@ -41,15 +41,50 @@ Runs `pnpm add -g @mfjjs/ruflo-setup` then `ruflo-setup` which:
41
41
  3. Installs a global `SessionStart` hook in `~/.claude/settings.json` that warns when Ruflo is not configured
42
42
  4. May refresh `~/.claude/commands/ruflo-setup.md` from the latest packaged template when differences are detected
43
43
 
44
+ ## Options
45
+
46
+ ### cleanup
47
+
48
+ Removes all Ruflo-related packages from the **npm** global registry (does not touch pnpm globals).
49
+
50
+ Packages removed: `ruflo`, `@mfjjs/ruflo-setup`, `ruflo-setup`, `claude-flow`, `@claude-flow/cli`, `ruv-swarm`
51
+
44
52
  ## Instructions for Claude
45
53
 
46
54
  When the user runs /ruflo-setup:
47
55
 
56
+ ### Default (no arguments) β€” install
57
+
48
58
  1. Confirm the current working directory with the user
49
59
  2. Check if `.mcp.json` already exists β€” if so, warn and ask before overwriting
50
- 3. Run the setup CLI:
60
+ 3. Check pnpm version is at least 10.32.1:
61
+ ```bash
62
+ pnpm --version
63
+ ```
64
+ If the version is lower than 10.32.1, stop and tell the user to upgrade pnpm before continuing.
65
+ 4. Run the setup CLI and capture output to detect whether pnpm modified anything:
51
66
  ```bash
52
67
  pnpm add -g @mfjjs/ruflo-setup
68
+ pnpm add -g ruflo@latest 2>&1 | tee /tmp/ruflo-pnpm-add.log
69
+ ```
70
+ After the `pnpm add -g ruflo@latest` step, inspect the output. If pnpm installed or updated any packages (i.e. the output does NOT contain "Already up to date" or an equivalent no-change message), run:
71
+ ```bash
72
+ pnpm approve-builds -g --all
73
+ ```
74
+ Skip `approve-builds` if nothing changed.
75
+ 5. Run the setup tool:
76
+ ```bash
53
77
  ruflo-setup
54
78
  ```
55
- 4. Report what was installed and remind the user to restart Claude Code to load the new MCP servers
79
+ 6. Report what was installed and remind the user to restart Claude Code to load the new MCP servers
80
+
81
+ ### cleanup
82
+
83
+ When the user runs `/ruflo-setup cleanup`:
84
+
85
+ 1. Warn the user that this will remove Ruflo packages from the **npm** global registry and ask for confirmation
86
+ 2. On confirmation, run:
87
+ ```bash
88
+ ruflo-setup cleanup
89
+ ```
90
+ 3. Report which packages were removed and which were not found (not found is fine β€” it means they were already clean)