@mfjjs/ruflo-setup 0.1.8 โ†’ 0.2.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
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.1](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.2.0...v0.2.1) (2026-03-14)
6
+
7
+
8
+ ### Features
9
+
10
+ * **docs:** update usage section by moving status command first ([e98f473](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/e98f473f25f53031d8cf08cf8d6bd3bfedcae949))
11
+
12
+ ## [0.2.0](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.1.9...v0.2.0) (2026-03-14)
13
+
14
+
15
+ ### โš  BREAKING CHANGES
16
+
17
+ * **cli:** The CLI now includes a new command which may affect existing scripts that rely on the previous command structure.
18
+
19
+ ### Features
20
+
21
+ * **cli:** add 'status' command to check feature status ([d551664](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/d551664619635e7efbbc9a9810266ecfe2212d1c))
22
+ * **docs:** add detailed agents and skills sections to Ruflo benefit documentation ([c66d212](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/c66d212f4ee25390ab139e43131ecb548b7bcb5c))
23
+ * **docs:** add link to ruflo-benefits.md and renamed to plural ([2820aeb](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/2820aeb5cebbfad0ac7b568291aa55a49076c6c3))
24
+ * **docs:** update Ruflo benefit documentation with agents and skills sections ([8feb883](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/8feb8836c88ec5096a907eb4c842b0b3b4c55b4c))
25
+ * **status:** enhance directory checks to display count of agents and skills ([3ade22b](https://gitlab.mfj.local:8022/mario/ruflo-setup/commit/3ade22b10ba1840f405b8f239f2a723f6d4089d7))
26
+
27
+ ### [0.1.9](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.1.8...v0.1.9) (2026-03-13)
28
+
5
29
  ### [0.1.8](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.1.7...v0.1.8) (2026-03-13)
6
30
 
7
31
  ### [0.1.7](https://gitlab.mfj.local:8022/mario/ruflo-setup/compare/v0.1.6...v0.1.7) (2026-03-13)
package/README.md CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  Cross-platform npm CLI to bootstrap a project with Ruflo on Windows and Linux.
4
4
 
5
- ## What this project is
5
+ > **Deep dive:** [`docs/ruflo-benefits.md`](docs/ruflo-benefits.md) is a comprehensive reference (~900 lines) covering every feature layer, the MinCut/RuVector/RVF internals, all 80+ agents, 33 skills, 65 slash commands, and how agents and skills are invoked. Not a quick read.
6
+
7
+ ## ๐Ÿ“˜ What this project is
6
8
 
7
9
  `@mfjjs/ruflo-setup` implements the setup with a Node-based CLI command:
8
10
 
9
11
  - Package name: `@mfjjs/ruflo-setup`
10
12
  - Command name: `ruflo-setup`
11
13
  - Platform support: Windows and Linux (plus macOS by default)
12
- ## Requirements
14
+ ## ๐Ÿ“‹ Requirements
13
15
  <details>
14
16
  <summary>Click to toggle visibility</summary>
15
17
 
@@ -37,13 +39,35 @@ corepack prepare pnpm@latest --activate
37
39
  ```
38
40
  </details>
39
41
 
40
- ## Installation
42
+ ## ๐Ÿ“ฆ Installation
41
43
 
42
44
  ```powershell
43
45
  pnpm -i -g @mfjjs/ruflo-setup
44
46
  ```
45
47
 
46
- ## Usage
48
+ ## ๐Ÿ’ก Why You Need This
49
+
50
+ If youโ€™re working on:
51
+
52
+ * A brownfield application that never had RuFlow configured, or
53
+ * A brandโ€‘new project that hasnโ€™t been set up with RuFlow yet,
54
+
55
+ โ€ฆthen you currently have to configure RuFlow manually in each project. That means recreating the same structure, wiring, and boilerplate over and over.
56
+
57
+ 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.
58
+
59
+ You only need to do this once in each folder. Just run the command and youโ€™re ready to go.
60
+
61
+ ## ๐Ÿš€ Usage
62
+
63
+ ### Status
64
+ Check whether all Ruflo feature layers (0โ€“8) are enabled in the current project:
65
+
66
+ ```bash
67
+ ruflo-setup status
68
+ ```
69
+
70
+ 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.
47
71
 
48
72
  ### Bootstrap
49
73
  Use this once if you want Claude Code to expose the `/ruflo-setup` command globally.
@@ -77,19 +101,20 @@ ruflo-setup hooks install
77
101
  ruflo-setup hooks status
78
102
  ```
79
103
 
80
- ## Project structure
104
+ ## ๐Ÿ—‚๏ธ Project structure
81
105
 
82
106
  - `package.json`: npm metadata, scripts, and `bin` mapping
83
107
  - `bin/ruflo-setup.js`: executable entry file the shell runs
84
108
  - `src/cli.js`: command router and argument handling
85
109
  - `src/setup.js`: setup workflow (`init`, `.mcp.json`, template copy)
110
+ - `src/status.js`: layer-by-layer feature status checker (Layers 0โ€“8)
86
111
  - `src/hooks.js`: global `check-ruflo` hook install/status
87
112
  - `src/utils.js`: reusable filesystem and argument helpers
88
113
  - `templates/CLAUDE.md`: bundled template copied into target project
89
114
  - `claude-hooks/check-ruflo.cjs`: SessionStart hook payload
90
115
  - `tests/cli.test.mjs`: smoke tests for CLI behavior
91
116
 
92
- ## What the command line calls
117
+ ## ๐Ÿ–ฅ๏ธ What the command line calls
93
118
 
94
119
  After install/link, `ruflo-setup` resolves to your package `bin` entry:
95
120
 
@@ -103,7 +128,7 @@ After install/link, `ruflo-setup` resolves to your package `bin` entry:
103
128
 
104
129
  The shell shim launches `bin/ruflo-setup.js`, which imports `src/cli.js`, which dispatches to setup or hook subcommands.
105
130
 
106
- ## How the CLI entry point works
131
+ ## โš™๏ธ How the CLI entry point works
107
132
 
108
133
  Flow:
109
134
 
@@ -117,7 +142,9 @@ Flow:
117
142
  - copies `templates/CLAUDE.md`
118
143
  - installs global SessionStart hook (unless skipped)
119
144
 
120
- ## Local development with pnpm
145
+ 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.
146
+
147
+ ## ๐Ÿ› ๏ธ Local development with pnpm
121
148
 
122
149
  From this repository root (`setup-ruflo/`):
123
150
 
@@ -127,7 +154,7 @@ pnpm test
127
154
  pnpm run test:cli
128
155
  ```
129
156
 
130
- ## Link locally so command works everywhere
157
+ ## ๐Ÿ”— Link locally so command works everywhere
131
158
 
132
159
  ```bash
133
160
  # from setup-ruflo/
@@ -139,7 +166,7 @@ ruflo-setup --dry-run --skip-init
139
166
 
140
167
  This is the fast edit loop: change files in `src/`, rerun `ruflo-setup`, and behavior updates immediately without reinstall.
141
168
 
142
- ## Simulate a real install (deploy-style testing)
169
+ ## ๐Ÿงช Simulate a real install (deploy-style testing)
143
170
 
144
171
  Create a tarball and install it into a clean test location.
145
172
 
@@ -154,7 +181,7 @@ ruflo-setup --dry-run --skip-init
154
181
 
155
182
  This tests exactly what users get from a package install.
156
183
 
157
- ## Global hook behavior
184
+ ## ๐Ÿช Global hook behavior
158
185
 
159
186
  `ruflo-setup` installs a global Claude SessionStart command hook that runs:
160
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mfjjs/ruflo-setup",
3
- "version": "0.1.8",
3
+ "version": "0.2.1",
4
4
  "description": "Cross-platform setup CLI for Ruflo + Claude Flow projects",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -18,6 +18,7 @@ function printHelp() {
18
18
 
19
19
  Usage:
20
20
  ruflo-setup [options]
21
+ ruflo-setup status
21
22
  ruflo-setup hooks install [options]
22
23
  ruflo-setup hooks status
23
24
 
@@ -32,6 +33,7 @@ Options:
32
33
 
33
34
  Examples:
34
35
  ruflo-setup
36
+ ruflo-setup status
35
37
  ruflo-setup --dry-run --skip-init
36
38
  ruflo-setup hooks status
37
39
  ruflo-setup hooks install --dry-run
@@ -58,6 +60,12 @@ export async function runCli(argv, cwd) {
58
60
  const packageRoot = packageRootFromModule();
59
61
  const flags = parseArgs(argv);
60
62
 
63
+ if (flags.command === 'status') {
64
+ const { runStatus } = await import('./status.js');
65
+ await runStatus({ cwd, packageRoot });
66
+ return 0;
67
+ }
68
+
61
69
  if (flags.command === 'hooks') {
62
70
  const subcommand = argv[1] || 'status';
63
71
  if (subcommand === 'status') {
package/src/status.js ADDED
@@ -0,0 +1,303 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { createRequire } from 'node:module';
6
+ import { readJsonSafe } from './utils.js';
7
+ import { getGlobalHookStatus } from './hooks.js';
8
+
9
+ const require = createRequire(import.meta.url);
10
+ const OK = '[OK]';
11
+ const MISS = '[--]';
12
+ const ERR = '[!!]';
13
+ const IS_WIN = process.platform === 'win32';
14
+
15
+ function spawn(cmd, args) {
16
+ try {
17
+ return spawnSync(cmd, args, {
18
+ stdio: ['ignore', 'pipe', 'ignore'],
19
+ encoding: 'utf8',
20
+ shell: IS_WIN
21
+ });
22
+ } catch {
23
+ return { status: 1, stdout: '' };
24
+ }
25
+ }
26
+
27
+ function dirExists(p) {
28
+ try {
29
+ return fs.statSync(p).isDirectory();
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ function fileExists(p) {
36
+ try {
37
+ return fs.statSync(p).isFile();
38
+ } catch {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ // Flatten npm/pnpm --json list result into a name->version map (1 level deep).
44
+ function buildPkgMap(jsonText) {
45
+ const map = {};
46
+ try {
47
+ const parsed = JSON.parse(jsonText || '{}');
48
+ // npm list -g returns an array with one element, pnpm returns an object
49
+ const root = Array.isArray(parsed) ? parsed[0] : parsed;
50
+ const deps = root?.dependencies ?? {};
51
+ for (const [name, info] of Object.entries(deps)) {
52
+ map[name] = info?.version ?? true;
53
+ for (const [nname, ninfo] of Object.entries(info?.dependencies ?? {})) {
54
+ if (!(nname in map)) map[nname] = ninfo?.version ?? true;
55
+ }
56
+ }
57
+ } catch {
58
+ // ignore parse errors
59
+ }
60
+ return map;
61
+ }
62
+
63
+ // Tries npm list -g first, falls back to pnpm list -g.
64
+ 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
+ const pnpmRes = spawn('pnpm', ['list', '-g', '--depth=1', '--json']);
71
+ if (pnpmRes.status === 0 && pnpmRes.stdout) {
72
+ return buildPkgMap(pnpmRes.stdout);
73
+ }
74
+ return {};
75
+ }
76
+
77
+ // Each checkLayer* returns { lines: string[], ok: number, total: number }
78
+
79
+ function checkLayer0() {
80
+ const lines = [];
81
+ let ok = 0;
82
+ const nodeMajor = parseInt(process.version.slice(1), 10);
83
+ if (nodeMajor >= 20) { lines.push(` ${OK} Node.js ${process.version} (>=20 required)`); ok += 1; }
84
+ else { lines.push(` ${ERR} Node.js ${process.version} (>=20 required โ€” upgrade Node.js)`); }
85
+
86
+ const pnpmRes = spawn('pnpm', ['--version']);
87
+ if (pnpmRes.status === 0 && pnpmRes.stdout.trim()) {
88
+ lines.push(` ${OK} pnpm ${pnpmRes.stdout.trim()}`); ok += 1;
89
+ } else {
90
+ lines.push(` ${MISS} pnpm (install: npm install -g pnpm)`);
91
+ }
92
+
93
+ const claudeRes = spawn('claude', ['--version']);
94
+ if (claudeRes.status === 0) {
95
+ const ver = (claudeRes.stdout || '').trim();
96
+ lines.push(` ${OK} Claude Code CLI${ver ? ` ${ver}` : ''}`); ok += 1;
97
+ } else {
98
+ lines.push(` ${MISS} Claude Code CLI (install: npm install -g @anthropic-ai/claude-code)`);
99
+ }
100
+
101
+ if (process.env.ANTHROPIC_API_KEY) {
102
+ lines.push(` ${OK} ANTHROPIC_API_KEY set`); ok += 1;
103
+ } else {
104
+ lines.push(` ${ERR} ANTHROPIC_API_KEY not set (required for LLM calls)`);
105
+ }
106
+
107
+ return { lines, ok, total: 4 };
108
+ }
109
+
110
+ function checkLayer1(pkgMap) {
111
+ const lines = [];
112
+ let ok = 0;
113
+ for (const name of ['ruflo', '@mfjjs/ruflo-setup']) {
114
+ const ver = pkgMap[name];
115
+ if (ver) { lines.push(` ${OK} ${name}${typeof ver === 'string' ? `@${ver}` : ''}`); ok += 1; }
116
+ else { lines.push(` ${MISS} ${name} (install: npm install -g ${name})`); }
117
+ }
118
+ return { lines, ok, total: 2 };
119
+ }
120
+
121
+ function checkLayer2(pkgMap) {
122
+ const lines = [];
123
+ let ok = 0;
124
+ const ATTENTION_WIN_NOTE = '(Windows: requires Windows 11 SDK for NAPI; WASM fallback available)';
125
+ const pkgs = [
126
+ '@claude-flow/memory', '@ruvector/attention', '@claude-flow/aidefence', 'agentic-flow',
127
+ '@ruvector/sona', '@ruvector/router', '@ruvector/learning-wasm',
128
+ '@claude-flow/embeddings', '@claude-flow/guidance', '@claude-flow/codex'
129
+ ];
130
+ for (const name of pkgs) {
131
+ const ver = pkgMap[name];
132
+ if (ver) { lines.push(` ${OK} ${name}${typeof ver === 'string' ? `@${ver}` : ''}`); ok += 1; }
133
+ else {
134
+ const note = (name === '@ruvector/attention' && IS_WIN) ? ` ${ATTENTION_WIN_NOTE}` : '';
135
+ lines.push(` ${MISS} ${name}${note}`);
136
+ }
137
+ }
138
+ return { lines, ok, total: pkgs.length };
139
+ }
140
+
141
+ function checkLayer3(mcpJson) {
142
+ const lines = [];
143
+ let ok = 0;
144
+ const servers = mcpJson?.mcpServers ?? {};
145
+
146
+ if (servers['claude-flow']) {
147
+ const args = servers['claude-flow']?.args ?? [];
148
+ const pkgArg = args.find((a) => typeof a === 'string' && a.includes('@claude-flow/cli')) ?? '@claude-flow/cli@latest';
149
+ lines.push(` ${OK} claude-flow (${pkgArg})`); ok += 1;
150
+ } else {
151
+ lines.push(` ${MISS} claude-flow (run ruflo-setup to configure)`);
152
+ }
153
+
154
+ if (servers['ruv-swarm']) { lines.push(` ${OK} ruv-swarm (optional)`); ok += 1; }
155
+ else { lines.push(` ${MISS} ruv-swarm (optional)`); }
156
+
157
+ if (servers['flow-nexus']) { lines.push(` ${OK} flow-nexus (optional)`); ok += 1; }
158
+ else { lines.push(` ${MISS} flow-nexus (optional โ€” needs Cognitum.One account)`); }
159
+
160
+ return { lines, ok, total: 3 };
161
+ }
162
+
163
+ function checkLayer4(mcpJson) {
164
+ const lines = [];
165
+ let ok = 0;
166
+ const cfEnv = mcpJson?.mcpServers?.['claude-flow']?.env ?? {};
167
+ const resolve = (k) => { const v = cfEnv[k] ?? process.env[k]; return v === undefined ? null : String(v).toLowerCase(); };
168
+
169
+ for (const g of ['INTELLIGENCE', 'AGENTS', 'MEMORY', 'DEVTOOLS']) {
170
+ if (resolve(`MCP_GROUP_${g}`) === 'false') { lines.push(` ${MISS} ${g} (disabled via MCP_GROUP_${g}=false)`); }
171
+ else { lines.push(` ${OK} ${g} (default on)`); ok += 1; }
172
+ }
173
+ for (const g of ['SECURITY', 'BROWSER', 'NEURAL', 'AGENTIC_FLOW']) {
174
+ if (resolve(`MCP_GROUP_${g}`) === 'true') { lines.push(` ${OK} ${g} (enabled)`); ok += 1; }
175
+ else { lines.push(` ${MISS} ${g} (set MCP_GROUP_${g}=true in .mcp.json env)`); }
176
+ }
177
+
178
+ return { lines, ok, total: 8 };
179
+ }
180
+
181
+ function checkLayer5() {
182
+ const lines = [];
183
+ let ok = 0;
184
+ const checks = [
185
+ { key: 'ANTHROPIC_API_KEY', req: true, note: '' },
186
+ { key: 'OPENAI_API_KEY', req: false, note: '(optional โ€” enables GPT + Codex)' },
187
+ { key: 'GOOGLE_API_KEY', req: false, note: '(optional โ€” enables Gemini)' },
188
+ { key: 'OPENROUTER_API_KEY', req: false, note: '(optional โ€” multi-provider proxy)' }
189
+ ];
190
+ for (const { key, req, note } of checks) {
191
+ if (process.env[key]) { lines.push(` ${OK} ${key}`); ok += 1; }
192
+ else if (req) { lines.push(` ${ERR} ${key} not set (required for LLM calls)`); }
193
+ else { lines.push(` ${MISS} ${key} ${note}`); }
194
+ }
195
+ return { lines, ok, total: checks.length };
196
+ }
197
+
198
+ function checkLayer6(packageRoot) {
199
+ const lines = [];
200
+ let ok = 0;
201
+ const homeDir = os.homedir();
202
+
203
+ try {
204
+ const hs = getGlobalHookStatus({ packageRoot });
205
+ const sp = hs.settingsPath ?? path.join(homeDir, '.claude', 'settings.json');
206
+ if (hs.installed) { lines.push(` ${OK} SessionStart hook (${sp})`); ok += 1; }
207
+ else { lines.push(` ${MISS} SessionStart hook (${sp})`); }
208
+ } catch {
209
+ lines.push(` ${MISS} SessionStart hook (could not read ~/.claude/settings.json)`);
210
+ }
211
+
212
+ const commandFile = path.join(homeDir, '.claude', 'commands', 'ruflo-setup.md');
213
+ if (fileExists(commandFile)) { lines.push(` ${OK} /ruflo-setup command (${commandFile})`); ok += 1; }
214
+ else { lines.push(` ${MISS} /ruflo-setup command (${commandFile})`); }
215
+
216
+ return { lines, ok, total: 2 };
217
+ }
218
+
219
+ function checkLayer7(cwd) {
220
+ const lines = [];
221
+ let ok = 0;
222
+ const files = ['.mcp.json', 'CLAUDE.md', path.join('.claude', 'settings.json')];
223
+ const dirs = [
224
+ { rel: path.join('.claude', 'agents'), hint: 'run: ruflo init --full' },
225
+ { rel: path.join('.claude', 'skills'), hint: null },
226
+ { rel: path.join('.claude', 'commands'), hint: null },
227
+ { rel: '.claude-flow', hint: null }
228
+ ];
229
+
230
+ for (const rel of files) {
231
+ if (fileExists(path.join(cwd, rel))) { lines.push(` ${OK} ${rel}`); ok += 1; }
232
+ else { lines.push(` ${MISS} ${rel}`); }
233
+ }
234
+ for (const { rel, hint } of dirs) {
235
+ const disp = `${rel}/`.replace(/\\/g, '/');
236
+ const full = path.join(cwd, rel);
237
+ if (dirExists(full)) {
238
+ let count = '';
239
+ if (rel.endsWith('agents') || rel.endsWith('skills')) {
240
+ try {
241
+ const n = fs.readdirSync(full).length;
242
+ const label = rel.endsWith('agents') ? 'agents' : 'skills';
243
+ count = ` (${n} ${label})`;
244
+ } catch { /* ignore */ }
245
+ }
246
+ lines.push(` ${OK} ${disp}${count}`); ok += 1;
247
+ } else {
248
+ lines.push(` ${MISS} ${disp}${hint ? ` (${hint})` : ''}`);
249
+ }
250
+ }
251
+
252
+ return { lines, ok, total: files.length + dirs.length };
253
+ }
254
+
255
+ function checkLayer8() {
256
+ const res = spawn('docker', ['--version']);
257
+ if (res.status === 0 && res.stdout.trim()) {
258
+ return { lines: [` ${OK} Docker ${res.stdout.trim()}`], ok: 1, total: 1 };
259
+ }
260
+ return { lines: [` ${MISS} Docker not detected (optional โ€” needed for ruvocal chat UI)`], ok: 0, total: 1 };
261
+ }
262
+
263
+ export async function runStatus({ cwd, packageRoot }) {
264
+ try {
265
+ const { version } = require('../package.json');
266
+ const mcpJson = readJsonSafe(path.join(cwd, '.mcp.json'), {});
267
+ const pkgMap = getGlobalPkgMap();
268
+
269
+ const layers = [
270
+ { title: 'Layer 0: Prerequisites', result: checkLayer0() },
271
+ { title: 'Layer 1: Global npm Packages', result: checkLayer1(pkgMap) },
272
+ { title: 'Layer 2: Optional Packages (WASM/ML) โ€” enables AI features', result: checkLayer2(pkgMap) },
273
+ { title: 'Layer 3: MCP Servers (.mcp.json)', result: checkLayer3(mcpJson) },
274
+ { title: 'Layer 4: MCP Tool Groups', result: checkLayer4(mcpJson) },
275
+ { title: 'Layer 5: Environment Variables', result: checkLayer5() },
276
+ { title: 'Layer 6: Claude Code Hooks', result: checkLayer6(packageRoot) },
277
+ { title: 'Layer 7: Project Scaffolding', result: checkLayer7(cwd) },
278
+ { title: 'Layer 8: Docker Chat UI (optional)', result: checkLayer8() }
279
+ ];
280
+
281
+ let totalOk = 0;
282
+ let totalChecks = 0;
283
+
284
+ process.stdout.write(`\nRuflo Feature Status (ruflo-setup v${version})\n`);
285
+ process.stdout.write(`Target: ${cwd}\n`);
286
+
287
+ for (const { title, result } of layers) {
288
+ process.stdout.write(`\n${title}\n`);
289
+ for (const line of result.lines) process.stdout.write(`${line}\n`);
290
+ totalOk += result.ok;
291
+ totalChecks += result.total;
292
+ }
293
+
294
+ process.stdout.write(`\nSummary: ${totalOk}/${totalChecks} features enabled\n`);
295
+ process.stdout.write(`For agents, skills, and slash commands reference: docs/ruflo-benefit.md\n`);
296
+
297
+ const hasRequiredMissing = parseInt(process.version.slice(1), 10) < 20 || !process.env.ANTHROPIC_API_KEY;
298
+ if (hasRequiredMissing) process.stdout.write(`Run 'ruflo-setup' to configure missing required features.\n`);
299
+ process.stdout.write('\n');
300
+ } catch (error) {
301
+ process.stderr.write(`status error: ${error.message}\n`);
302
+ }
303
+ }
package/src/utils.js CHANGED
@@ -90,7 +90,11 @@ export function toPlatformMcpConfig(platform) {
90
90
  CLAUDE_FLOW_HOOKS_ENABLED: 'true',
91
91
  CLAUDE_FLOW_TOPOLOGY: 'hierarchical-mesh',
92
92
  CLAUDE_FLOW_MAX_AGENTS: '15',
93
- CLAUDE_FLOW_MEMORY_BACKEND: 'hybrid'
93
+ CLAUDE_FLOW_MEMORY_BACKEND: 'hybrid',
94
+ MCP_GROUP_SECURITY: 'true',
95
+ MCP_GROUP_BROWSER: 'true',
96
+ MCP_GROUP_NEURAL: 'true',
97
+ MCP_GROUP_AGENTIC_FLOW: 'true'
94
98
  },
95
99
  autoStart: false
96
100
  },