@mfjjs/ruflo-setup 0.2.6 → 0.2.7

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,13 @@
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.7](///compare/v0.2.6...v0.2.7) (2026-03-20)
6
+
7
+
8
+ ### Features
9
+
10
+ * **cli:** add update command to upgrade ruflo-setup to the latest version 569bc0b
11
+
5
12
  ### [0.2.6](///compare/v0.2.5...v0.2.6) (2026-03-20)
6
13
 
7
14
 
package/README.md CHANGED
@@ -11,6 +11,20 @@ Cross-platform npm CLI to bootstrap a project with Ruflo on Windows and Linux.
11
11
  - Package name: `@mfjjs/ruflo-setup`
12
12
  - Command name: `ruflo-setup`
13
13
  - Platform support: Windows and Linux (plus macOS by default)
14
+
15
+ ## 💡 Why You Need This
16
+
17
+ If you're working on:
18
+
19
+ * A brownfield application that never had RuFlow configured, or
20
+ * A brand‑new project that hasn't been set up with RuFlow yet,
21
+
22
+ …then you currently have to configure RuFlow manually in each project. That means recreating the same structure, wiring, and boilerplate over and over.
23
+
24
+ `ruflo-setup` eliminates all of that. When you run it inside a project directory, it automatically generates the required RuFlow scaffolding — including all the files that belong in the `.claude/` folder — so every project starts from a clean, consistent baseline.
25
+
26
+ You only need to do this once per project. Just run the command and you're ready to go.
27
+
14
28
  ## 📋 Requirements
15
29
  <details>
16
30
  <summary>Click to toggle visibility</summary>
@@ -41,43 +55,50 @@ corepack prepare pnpm@latest --activate
41
55
 
42
56
  ## 📦 Installation
43
57
 
44
- ```powershell
58
+ Install the CLI globally once:
59
+
60
+ ```bash
45
61
  pnpm add -g @mfjjs/ruflo-setup
46
- ruflo-setup cleanup
47
62
  ```
48
63
 
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
-
51
- ## 💡 Why You Need This
64
+ ## 🚀 Usage
52
65
 
53
- If you’re working on:
66
+ ### Setup
54
67
 
55
- * A brownfield application that never had RuFlow configured, or
56
- * A brand‑new project that hasn’t been set up with RuFlow yet,
68
+ **First, change to your project directory**, then run:
57
69
 
58
- …then you currently have to configure RuFlow manually in each project. That means recreating the same structure, wiring, and boilerplate over and over.
70
+ ```bash
71
+ ruflo-setup
72
+ ```
59
73
 
60
- The new command eliminates all of that. When you run it inside a project, it automatically generates the required RuFlow scaffolding — including all the files that belong in the folder — so every project starts from a clean, consistent baseline.
74
+ That's it for most users. The command will:
75
+ 1. Check for a newer version of itself and offer to update before proceeding
76
+ 2. Install `ruflo@latest` globally and run `ruflo init --full` to scaffold your project
77
+ 3. Write a platform-aware `.mcp.json`
78
+ 4. Install a global Claude Code `SessionStart` hook
61
79
 
62
- You only need to do this once in each folder. Just run the command and you’re ready to go.
80
+ Additional options:
63
81
 
64
- ## 🚀 Usage
82
+ ```bash
83
+ # non-interactive (skip all prompts)
84
+ ruflo-setup --yes
65
85
 
66
- ### Cleanup
67
- Remove any previous npm global installs of Ruflo packages that could conflict with the pnpm-managed versions:
86
+ # preview what would happen without making any changes
87
+ ruflo-setup --dry-run
68
88
 
69
- ```bash
70
- ruflo-setup cleanup
71
- ```
89
+ # skip the ruflo global install step
90
+ ruflo-setup --skip-init
72
91
 
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.
92
+ # skip global hook installation
93
+ ruflo-setup --no-hooks
74
94
 
75
- ```bash
76
- # preview what would be removed without making changes
77
- ruflo-setup cleanup --dry-run
95
+ # hook operations
96
+ ruflo-setup hooks install
97
+ ruflo-setup hooks status
78
98
  ```
79
99
 
80
100
  ### Status
101
+
81
102
  Check whether all Ruflo feature layers (0–8) are enabled in the current project:
82
103
 
83
104
  ```bash
@@ -87,7 +108,8 @@ ruflo-setup status
87
108
  This prints a layer-by-layer report showing which features are active — prerequisites, global packages, optional WASM/ML packages, MCP servers, tool groups, environment variables, project scaffolding, and the Docker chat UI stack.
88
109
 
89
110
  ### Bootstrap
90
- Use this once if you want Claude Code to expose the `/ruflo-setup` command globally.
111
+
112
+ Use this once if you want Claude Code to expose the `/ruflo-setup` command globally, so you can run it from inside Claude Code chat without using the shell.
91
113
 
92
114
  ```bash
93
115
  ruflo-setup hooks init
@@ -95,27 +117,34 @@ ruflo-setup hooks init
95
117
 
96
118
  After that, when you open Claude Code in a project that does not already have Ruflo configured, you can run [**/ruflo-setup**](noop:) to start the setup flow.
97
119
 
98
- ### Setup
99
- Use these commands when you want to run the setup directly from a shell.
120
+ ### Update
100
121
 
101
- From the target project directory, run one of the following:
122
+ Update `@mfjjs/ruflo-setup` itself to the latest published version:
102
123
 
103
124
  ```bash
104
- # full setup
105
- ruflo-setup
125
+ ruflo-setup update
126
+ ```
106
127
 
107
- # non-interactive
108
- ruflo-setup --yes
128
+ It is best to always have the latest version before running setup. When you run `ruflo-setup` without arguments it automatically checks for a newer version and will prompt you to update if one is found, so in most cases you will not need to run this manually.
109
129
 
110
- # preview only
111
- ruflo-setup --dry-run --skip-init
130
+ ```bash
131
+ # preview without making changes
132
+ ruflo-setup update --dry-run
133
+ ```
112
134
 
113
- # skip global hook install
114
- ruflo-setup --no-hooks
135
+ ### Cleanup
115
136
 
116
- # hook operations
117
- ruflo-setup hooks install
118
- ruflo-setup hooks status
137
+ If you previously installed any Ruflo packages via `npm install -g`, those npm-global copies can shadow or conflict with the pnpm-managed versions. Run this to remove them and give yourself a clean slate:
138
+
139
+ ```bash
140
+ ruflo-setup cleanup
141
+ ```
142
+
143
+ This uninstalls `ruflo`, `@mfjjs/ruflo-setup`, `ruflo-setup`, `claude-flow`, `@claude-flow/cli`, and `ruv-swarm` from the **npm** global registry only — it does not touch pnpm globals.
144
+
145
+ ```bash
146
+ # preview what would be removed without making changes
147
+ ruflo-setup cleanup --dry-run
119
148
  ```
120
149
 
121
150
  ## 🗂️ Project structure
@@ -154,6 +183,7 @@ Flow:
154
183
  3. `bin/ruflo-setup.js` forwards args to `runCli(...)`.
155
184
  4. `src/cli.js` parses command and flags.
156
185
  5. `src/setup.js` runs setup steps:
186
+ - checks for a newer version of itself and prompts to update
157
187
  - optional `pnpm add -g ruflo@latest` then `ruflo init --full`
158
188
  - writes platform-aware `.mcp.json`
159
189
  - copies `templates/CLAUDE.md`
@@ -161,6 +191,10 @@ Flow:
161
191
 
162
192
  When called as `ruflo-setup status`, step 5 dispatches to `src/status.js` which checks all layers (0–8) and prints a feature status report.
163
193
 
194
+ When called as `ruflo-setup update`, it runs `pnpm add -g @mfjjs/ruflo-setup@latest` to update the tool itself.
195
+
196
+ When called as `ruflo-setup cleanup`, it removes Ruflo packages from the npm global registry to eliminate conflicts with pnpm-managed versions.
197
+
164
198
  ## 🛠️ Local development with pnpm
165
199
 
166
200
  From this repository root (`setup-ruflo/`):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mfjjs/ruflo-setup",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Cross-platform setup CLI for Ruflo + Claude Flow projects",
5
5
  "type": "module",
6
6
  "bin": {
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, runCleanup } from './setup.js';
5
+ import { runSetup, runCleanup, runUpdate } 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 update [--dry-run]
22
23
  ruflo-setup cleanup [--dry-run]
23
24
  ruflo-setup hooks install [options]
24
25
  ruflo-setup hooks status
@@ -33,11 +34,13 @@ Options:
33
34
  --verbose Extra output
34
35
 
35
36
  Commands:
37
+ update Update @mfjjs/ruflo-setup itself to the latest published version
36
38
  cleanup Remove all Ruflo packages from the npm global registry
37
39
  (ruflo, @mfjjs/ruflo-setup, claude-flow, @claude-flow/cli, ruv-swarm)
38
40
 
39
41
  Examples:
40
42
  ruflo-setup
43
+ ruflo-setup update
41
44
  ruflo-setup status
42
45
  ruflo-setup cleanup
43
46
  ruflo-setup cleanup --dry-run
@@ -100,6 +103,11 @@ export async function runCli(argv, cwd) {
100
103
  return 1;
101
104
  }
102
105
 
106
+ if (flags.command === 'update') {
107
+ runUpdate({ dryRun: flags.dryRun });
108
+ return 0;
109
+ }
110
+
103
111
  if (flags.command === 'cleanup') {
104
112
  if (!flags.dryRun && !flags.yes) {
105
113
  const { confirm } = await import('./utils.js');
package/src/setup.js CHANGED
@@ -171,6 +171,29 @@ function isAlreadyConfigured(cwd) {
171
171
  return pathExists(path.join(cwd, '.mcp.json')) || pathExists(path.join(cwd, '.claude', 'settings.json'));
172
172
  }
173
173
 
174
+ function getCurrentVersion(packageRoot) {
175
+ try {
176
+ const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
177
+ return pkg.version || '0.0.0';
178
+ } catch {
179
+ return '0.0.0';
180
+ }
181
+ }
182
+
183
+ function getLatestVersion() {
184
+ try {
185
+ const result = spawnSync('pnpm', ['view', '@mfjjs/ruflo-setup', 'version'], {
186
+ stdio: ['ignore', 'pipe', 'ignore'],
187
+ shell: process.platform === 'win32',
188
+ timeout: 8000
189
+ });
190
+ if (result.status !== 0 || result.error) return null;
191
+ return (result.stdout || '').toString().trim() || null;
192
+ } catch {
193
+ return null;
194
+ }
195
+ }
196
+
174
197
  export async function runSetup({
175
198
  cwd,
176
199
  packageRoot,
@@ -189,6 +212,24 @@ export async function runSetup({
189
212
  }
190
213
  logLine('');
191
214
 
215
+ // Check if a newer version of ruflo-setup itself is available.
216
+ if (!dryRun && !yes) {
217
+ const currentVersion = getCurrentVersion(packageRoot);
218
+ const latestVersion = getLatestVersion();
219
+ if (latestVersion && !semverGte(parseSemver(currentVersion), parseSemver(latestVersion))) {
220
+ logLine(`A newer version of ruflo-setup is available: ${latestVersion} (you have ${currentVersion}).`);
221
+ logLine('It is best to always have the latest version before running setup.');
222
+ const doUpdate = await confirm('Update @mfjjs/ruflo-setup now? [y/N] ');
223
+ if (doUpdate) {
224
+ runUpdate({ dryRun: false });
225
+ logLine('');
226
+ logLine('Please re-run ruflo-setup to continue with the updated version.');
227
+ return;
228
+ }
229
+ logLine('');
230
+ }
231
+ }
232
+
192
233
  logLine('Preflight: Syncing global /ruflo-setup command template ...');
193
234
  const preflightCommandResult = syncGlobalCommandTemplate({ packageRoot, dryRun });
194
235
  if (preflightCommandResult.changed) {
@@ -310,3 +351,30 @@ export function runCleanup({ dryRun = false } = {}) {
310
351
  logLine('');
311
352
  logLine('Cleanup complete.');
312
353
  }
354
+
355
+ export function runUpdate({ dryRun = false } = {}) {
356
+ logLine('');
357
+ logLine('Ruflo Setup Update');
358
+ logLine('');
359
+
360
+ if (dryRun) {
361
+ logLine('[DRY RUN] Would run: pnpm add -g @mfjjs/ruflo-setup@latest');
362
+ logLine('');
363
+ return;
364
+ }
365
+
366
+ ensurePnpmAvailable();
367
+
368
+ logLine('Updating @mfjjs/ruflo-setup to latest...');
369
+ const result = spawnSync('pnpm', ['add', '-g', '@mfjjs/ruflo-setup@latest'], {
370
+ stdio: 'inherit',
371
+ shell: process.platform === 'win32'
372
+ });
373
+
374
+ if (result.status !== 0) {
375
+ throw new Error(`pnpm add -g @mfjjs/ruflo-setup@latest failed with exit code ${result.status}`);
376
+ }
377
+
378
+ logLine('');
379
+ logLine('Update complete. Re-run ruflo-setup to continue with the updated version.');
380
+ }
package/src/status.js CHANGED
@@ -40,12 +40,11 @@ function fileExists(p) {
40
40
  }
41
41
  }
42
42
 
43
- // Flatten npm/pnpm --json list result into a name->version map (1 level deep).
43
+ // Flatten pnpm --json list result into a name->version map (1 level deep).
44
44
  function buildPkgMap(jsonText) {
45
45
  const map = {};
46
46
  try {
47
47
  const parsed = JSON.parse(jsonText || '{}');
48
- // npm list -g returns an array with one element, pnpm returns an object
49
48
  const root = Array.isArray(parsed) ? parsed[0] : parsed;
50
49
  const deps = root?.dependencies ?? {};
51
50
  for (const [name, info] of Object.entries(deps)) {
@@ -60,13 +59,7 @@ function buildPkgMap(jsonText) {
60
59
  return map;
61
60
  }
62
61
 
63
- // Tries npm list -g first, falls back to pnpm list -g.
64
62
  function getGlobalPkgMap() {
65
- const npmRes = spawn('npm', ['list', '-g', '--depth=1', '--json']);
66
- if (npmRes.status === 0 && npmRes.stdout) {
67
- const m = buildPkgMap(npmRes.stdout);
68
- if (Object.keys(m).length > 0) return m;
69
- }
70
63
  const pnpmRes = spawn('pnpm', ['list', '-g', '--depth=1', '--json']);
71
64
  if (pnpmRes.status === 0 && pnpmRes.stdout) {
72
65
  return buildPkgMap(pnpmRes.stdout);
@@ -95,7 +88,7 @@ function checkLayer0() {
95
88
  const ver = (claudeRes.stdout || '').trim();
96
89
  lines.push(` ${OK} Claude Code CLI${ver ? ` ${ver}` : ''}`); ok += 1;
97
90
  } else {
98
- lines.push(` ${MISS} Claude Code CLI (install: npm install -g @anthropic-ai/claude-code)`);
91
+ lines.push(` ${MISS} Claude Code CLI (install: pnpm add -g @anthropic-ai/claude-code)`);
99
92
  }
100
93
 
101
94
  if (process.env.ANTHROPIC_API_KEY) {
@@ -113,7 +106,7 @@ function checkLayer1(pkgMap) {
113
106
  for (const name of ['ruflo', '@mfjjs/ruflo-setup']) {
114
107
  const ver = pkgMap[name];
115
108
  if (ver) { lines.push(` ${OK} ${name}${typeof ver === 'string' ? `@${ver}` : ''}`); ok += 1; }
116
- else { lines.push(` ${MISS} ${name} (install: npm install -g ${name})`); }
109
+ else { lines.push(` ${MISS} ${name} (install: pnpm add -g ${name})`); }
117
110
  }
118
111
  return { lines, ok, total: 2 };
119
112
  }
@@ -268,7 +261,7 @@ export async function runStatus({ cwd, packageRoot }) {
268
261
 
269
262
  const layers = [
270
263
  { title: 'Layer 0: Prerequisites', result: checkLayer0() },
271
- { title: 'Layer 1: Global npm Packages', result: checkLayer1(pkgMap) },
264
+ { title: 'Layer 1: Global Packages', result: checkLayer1(pkgMap) },
272
265
  { title: 'Layer 2: Optional Packages (WASM/ML) — enables AI features', result: checkLayer2(pkgMap) },
273
266
  { title: 'Layer 3: MCP Servers (.mcp.json)', result: checkLayer3(mcpJson) },
274
267
  { title: 'Layer 4: MCP Tool Groups', result: checkLayer4(mcpJson) },