@fluentcommerce/ai-skills 0.8.2 → 0.8.3

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 (31) hide show
  1. package/README.md +79 -29
  2. package/bin/cli.mjs +278 -10
  3. package/content/cli/skills/fluent-cli-mcp-cicd/SKILL.md +6 -3
  4. package/content/cli/skills/fluent-connect/SKILL.md +1 -1
  5. package/content/dev/skills/fluent-e2e-test/SKILL.md +3 -1
  6. package/content/dev/skills/fluent-event-api/SKILL.md +1 -0
  7. package/content/dev/skills/fluent-feature-explain/SKILL.md +1 -0
  8. package/content/dev/skills/fluent-feature-plan/SKILL.md +1 -0
  9. package/content/dev/skills/fluent-mystique-builder/SKILL.md +2 -3
  10. package/content/dev/skills/fluent-mystique-scaffold/SDK_REFERENCE.md +2 -2
  11. package/content/dev/skills/fluent-mystique-scaffold/TEMPLATES.md +1 -2
  12. package/content/dev/skills/fluent-mystique-sdk-reference/SKILL.md +2 -2
  13. package/content/dev/skills/fluent-pre-deploy-check/SKILL.md +25 -0
  14. package/content/dev/skills/fluent-sourcing/SKILL.md +4 -0
  15. package/content/dev/skills/fluent-test-data/SKILL.md +4 -0
  16. package/content/dev/skills/fluent-trace/SKILL.md +16 -1
  17. package/content/dev/skills/fluent-workflow-builder/SKILL.md +11 -1
  18. package/content/dev/skills/fluent-workflow-deploy/SKILL.md +27 -0
  19. package/content/knowledge/index.md +2 -0
  20. package/content/knowledge/platform/create-order-reference.md +797 -0
  21. package/content/knowledge/platform/domain-model.md +1 -1
  22. package/content/knowledge/platform/workflow-design.md +18 -0
  23. package/content/mcp-extn/skills/fluent-mcp-core/SKILL.md +1 -1
  24. package/content/mcp-extn/skills/fluent-mcp-tools/SKILL.md +1 -1
  25. package/docs/dev-workflow.md +5 -2
  26. package/docs/fluent-ai-skills-reference.md +2 -2
  27. package/docs/getting-started.md +2 -2
  28. package/docs/use-cases.md +1 -1
  29. package/docs/workflow-reference.md +4 -2
  30. package/metadata.json +1 -1
  31. package/package.json +1 -1
package/README.md CHANGED
@@ -23,8 +23,9 @@ Teach your AI assistant to work with [Fluent Commerce](https://fluentcommerce.co
23
23
  ## Quick Start (copy-paste)
24
24
 
25
25
  ```bash
26
- # 1. Install Fluent CLI + Claude Code (skip if already installed)
27
- npm install -g @fluentcommerce/cli @anthropic-ai/claude-code
26
+ # 1. Install prerequisites (skip if already installed)
27
+ # Fluent CLI: https://docs.fluentcommerce.com/building-blocks/fluent-cli-package
28
+ npm install -g @anthropic-ai/claude-code
28
29
 
29
30
  # 2. Create a Fluent CLI profile (get values from your Fluent account team)
30
31
  fluent profile create MY_PROFILE \
@@ -178,7 +179,7 @@ See all 27 scenarios with exact prompts: [docs/use-cases.md](docs/use-cases.md)
178
179
  | Requirement | How to install | Verify |
179
180
  |---|---|---|
180
181
  | **Node.js 20+** | [nodejs.org](https://nodejs.org) | `node --version` |
181
- | **Fluent CLI 2.0+** | `npm install -g @fluentcommerce/cli` | `fluent --version` |
182
+ | **Fluent CLI 2.0+** | [Install guide](https://docs.fluentcommerce.com/building-blocks/fluent-cli-package) | `fluent --version` |
182
183
  | **Claude Code** | `npm install -g @anthropic-ai/claude-code` | `claude --version` |
183
184
  | **A Fluent Commerce account** | Contact your Fluent account team | You'll need the 5 values below |
184
185
 
@@ -274,19 +275,37 @@ my-fluent-workspace/
274
275
  | **Local** (`.agents/skills`) | Fluent Codex skills for this workspace only (`--target codex --scope project`) | No — one per workspace |
275
276
  | **Local** (this folder) | `.mcp.json` — MCP server config pointing to your Fluent account | No — one per workspace |
276
277
  | **Local** (this folder) | `knowledge/` — platform knowledge (domain model, SDK patterns, rule contracts) | No — managed by installer, refreshed on reinstall |
277
- | **Optional local** (this folder) | `CLAUDE.md` — repo/workspace instructions you maintain | No — one per workspace |
278
+ | **Local** (this folder) | `CLAUDE.md` — starter workspace instructions (auto-generated, safe to edit; [details](#claudemd-workspace-instructions)) | No — one per workspace |
278
279
  | **Local** (this folder) | `accounts/` — workflows, features, source code (created in Step 3) | No — one per workspace |
279
280
 
280
281
  You can have multiple workspaces (e.g., one per client) each with different profiles and retailers. Skills are shared; everything else is workspace-specific.
281
282
 
282
283
  ### Verify the installation
283
284
 
285
+ **Run `doctor` — it checks everything in one shot:**
286
+
287
+ ```bash
288
+ npx @fluentcommerce/ai-skills doctor
289
+ ```
290
+
291
+ `doctor` validates: Node.js version, Fluent CLI installed, Claude Code installed, skills installed, `.mcp.json` present with correct server config, `knowledge/` docs present, Fluent CLI profile exists and can authenticate, and MCP extension reachable. Fix anything it flags before proceeding.
292
+
293
+ **Quick status check (skills only):**
294
+
284
295
  ```bash
285
296
  npx @fluentcommerce/ai-skills status
286
297
  ```
287
298
 
288
299
  Shows which skill groups are installed and their install method (marketplace or file-copy). If something is missing, re-run `npx @fluentcommerce/ai-skills install --profile MY_PROFILE --profile-retailer "My Retailer"`.
289
300
 
301
+ **If you need to wire MCP separately** (e.g., changed profile, new workspace, or skipped `--profile` during install):
302
+
303
+ ```bash
304
+ npx @fluentcommerce/ai-skills mcp-setup --profile MY_PROFILE
305
+ ```
306
+
307
+ This generates `.mcp.json` in the current folder pointing to your Fluent account. Without it, the AI has no live API access.
308
+
290
309
  To verify MCP servers are actually **reachable** (run inside Claude Code chat, not in terminal):
291
310
  ```
292
311
  "Test my MCP connection" → AI calls health_ping, confirms live API access
@@ -316,48 +335,54 @@ This creates the full `accounts/` directory tree, downloads all workflows from y
316
335
 
317
336
  #### Workspace directory layout
318
337
 
338
+ Legend: **[auto]** = created by CLI/skills, **[you]** = you create/populate, **[ai]** = AI generates during sessions
339
+
319
340
  ```
320
341
  <project-root>/ <- any directory where you run the installer
321
- +-- .mcp.json <- MCP server config (auto-generated, gitignored)
322
- +-- knowledge/ <- Platform knowledge docs (domain model, SDK, patterns) — copied on install
342
+ +-- .mcp.json [auto] MCP server config (generated by install/mcp-setup)
343
+ +-- CLAUDE.md [auto] Starter workspace instructions (auto-generated, safe to edit)
344
+ +-- knowledge/ [auto] Platform knowledge docs — copied from package on install
345
+ | (domain model, SDK patterns, rule contracts, order patterns)
323
346
  +-- accounts/
324
- +-- MY_PROFILE/
347
+ +-- MY_PROFILE/ [auto] Created by /fluent-connect or install --profile
325
348
  |
326
- +-- SOURCE/ <- All implementation source code
327
- | +-- backend/ <- Java plugins: source repos, reference JARs, decompiled
328
- | | +-- fc-plugin-custom/
349
+ +-- SOURCE/ [you] YOUR implementation source code
350
+ | +-- backend/ [you] Clone or copy your Java plugin repos here
351
+ | | +-- fc-plugin-custom/ <- your repo (git clone or cp)
329
352
  | | | +-- pom.xml
330
353
  | | | +-- resources/module.json
331
354
  | | | +-- src/main/java/...
332
- | | +-- .decompiled/ <- Auto-generated from JAR decompilation
355
+ | | +-- .decompiled/ [auto] Auto-generated from deployed JARs by /fluent-connect
333
356
  | |
334
- | +-- frontend/ <- Mystique SDK component projects
335
- | +-- mystique-appeasement/
357
+ | +-- frontend/ [you] Clone or copy your Mystique SDK component projects here
358
+ | +-- mystique-appeasement/ <- your repo
336
359
  | +-- package.json
337
360
  | +-- src/index.tsx
338
361
  |
339
- +-- knowledge/ <- Account-specific conventions and client knowledge
362
+ +-- knowledge/ [you] Account-specific conventions (via /fluent-knowledge-init)
340
363
  | +-- naming-conventions.md
341
364
  | +-- coding-standards.md
342
365
  | +-- client/
343
366
  |
344
- +-- workflows/
345
- | +-- My Retailer/ <- Downloaded workflow JSONs (one per workflow)
346
- | +-- ORDER__HD.json
367
+ +-- workflows/ [auto] Downloaded from Fluent by /fluent-connect
368
+ | +-- My Retailer/
369
+ | +-- ORDER__HD.json <- live workflow JSON from your account
347
370
  | +-- workflow-context.json
348
371
  |
349
- +-- features/ <- One subdir per feature
372
+ +-- features/ [ai] Created by AI during feature development
350
373
  | +-- return-order/
351
- | +-- spec.md <- Business requirements
352
- | +-- plan.md <- Implementation plan
353
- | +-- architecture.md <- Reverse-engineered doc
354
- | +-- status.json <- Lifecycle tracker
355
- | +-- assets/ <- Screenshots, recordings, evidence
374
+ | +-- spec.md <- from /fluent-use-case-discover
375
+ | +-- plan.md <- from /fluent-feature-plan
376
+ | +-- architecture.md <- from /fluent-feature-explain
377
+ | +-- status.json <- lifecycle tracker (auto-updated)
378
+ | +-- assets/ <- screenshots, recordings, evidence
356
379
  |
357
- +-- reports/ <- Ephemeral: build/, pre-deploy/, e2e-test/
358
- +-- analysis/ <- Persistent: code/, modules/, topology/
359
- +-- tasks/ <- Operational plans (non-feature work)
360
- +-- sessions/ <- Audit trail exports
380
+ +-- memory/ [ai] Auto-accumulated learnings from your sessions
381
+ +-- feedback/ [ai] Skill execution feedback (success/failure patterns)
382
+ +-- reports/ [ai] Ephemeral: build/, pre-deploy/, e2e-test/
383
+ +-- analysis/ [ai] Persistent: code/, modules/, topology/
384
+ +-- tasks/ [ai] Operational plans (non-feature work)
385
+ +-- sessions/ [ai] Audit trail exports
361
386
  ```
362
387
 
363
388
  #### Where to put your code
@@ -539,7 +564,7 @@ For server-by-server MCP details, auth notes, and optional hosting providers, se
539
564
 
540
565
  | Symptom | Fix |
541
566
  |---|---|
542
- | "Fluent CLI not found" | `npm install -g @fluentcommerce/cli` then `fluent --version` |
567
+ | "Fluent CLI not found" | Install from [docs.fluentcommerce.com](https://docs.fluentcommerce.com/building-blocks/fluent-cli-package) then `fluent --version` |
543
568
  | "Profile directory not found" | `fluent profile create MY_PROFILE --id ... --username ... --password ... --client-secret ... --base-url ...` |
544
569
  | `.mcp.json` not created | `npx @fluentcommerce/ai-skills mcp-setup --profile MY_PROFILE` |
545
570
  | MCP tools return connection errors | Restart IDE, then `fluent profile retailers MY_PROFILE` to verify connectivity |
@@ -596,6 +621,31 @@ Just work normally # AI captures corrections progressively into
596
621
 
597
622
  **Full guide with format specs, loading chains, and examples:** [Data Architecture](content/knowledge/DATA-ARCHITECTURE.md) | [Knowledge Guidelines](content/knowledge/GUIDELINES.md)
598
623
 
624
+ ### CLAUDE.md — Workspace Instructions
625
+
626
+ The installer auto-generates a starter `CLAUDE.md` in your workspace root. Claude Code reads it automatically at the start of every session. It includes:
627
+
628
+ - **Account context** — profile and retailer (pre-filled if you used `--profile`)
629
+ - **First steps** — doctor, connect, explore
630
+ - **SDLC skill map** — which skills to use at each stage (setup → discover → plan → build → deploy → test → diagnose → audit)
631
+ - **Quick actions** — common prompts and slash commands
632
+ - **Knowledge pointers** — where platform and account-specific knowledge lives
633
+ - **Conventions placeholder** — add your team-specific rules here
634
+
635
+ **The installer never overwrites an existing CLAUDE.md** — so once generated, it's yours to customize.
636
+
637
+ **What to add:**
638
+
639
+ ```markdown
640
+ ## Conventions
641
+ - Order refs: ORD-{storeCode}-{seq}
642
+ - All custom rules use prefix `com.client.`
643
+ - Workflow subtypes: HD, CC, SFS (no custom types)
644
+ - Always use MCP tools for GraphQL — never hardcode queries
645
+ ```
646
+
647
+ **What NOT to put in it:** Don't duplicate what's already in `knowledge/` or skills. CLAUDE.md is for workspace-level overrides and team preferences.
648
+
599
649
  ---
600
650
 
601
651
  ## Further Reading
@@ -621,7 +671,7 @@ Just work normally # AI captures corrections progressively into
621
671
  | Package | Purpose |
622
672
  |---|---|
623
673
  | [`@fluentcommerce/fluent-mcp-extn`](https://www.npmjs.com/package/@fluentcommerce/fluent-mcp-extn) | MCP extension server — 45 tools for live API access (events, batch, metrics, settings, entities, workflows, cache) |
624
- | Fluent CLI (`@fluentcommerce/cli`) | Official CLI + built-in MCP server. `npm i -g @fluentcommerce/cli` |
674
+ | [Fluent CLI](https://docs.fluentcommerce.com/building-blocks/fluent-cli-package) | Official CLI + built-in MCP server. See [install guide](https://docs.fluentcommerce.com/building-blocks/fluent-cli-package) |
625
675
  | [`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp) | Browser automation — auto-configured for `/fluent-ui-test`, `/fluent-ui-record`, and `/fluent-mystique-preview` |
626
676
 
627
677
  ---
package/bin/cli.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  writeFileSync,
11
11
  } from "node:fs";
12
12
  import { spawnSync } from "node:child_process";
13
- import { join, dirname, basename, isAbsolute } from "node:path";
13
+ import { join, dirname, basename, isAbsolute, resolve } from "node:path";
14
14
  import { homedir } from "node:os";
15
15
  import { fileURLToPath } from "node:url";
16
16
 
@@ -975,6 +975,106 @@ function installKnowledge() {
975
975
  return count;
976
976
  }
977
977
 
978
+ /**
979
+ * Generate a starter CLAUDE.md in the workspace if one doesn't exist.
980
+ * Never overwrites — user's CLAUDE.md is always preserved.
981
+ */
982
+ function generateStarterClaudeMd(profile, retailer) {
983
+ const dest = join(getProjectRoot(), "CLAUDE.md");
984
+ if (existsSync(dest)) return false; // never overwrite user's file
985
+
986
+ const profileLine = profile ? `- Profile: \`${profile}\`` : "- Profile: `YOUR_PROFILE` (update after creating a profile)";
987
+ const retailerLine = retailer ? `- Retailer: \`${retailer}\`` : "- Retailer: `YOUR_RETAILER` (update after selecting a retailer)";
988
+ const profileRef = profile || "MY_PROFILE";
989
+ const retailerRef = retailer || "My Retailer";
990
+
991
+ const content = `# CLAUDE.md — Fluent Commerce AI Skills Workspace
992
+
993
+ > Auto-generated by \`@fluentcommerce/ai-skills install\`. Safe to edit — the installer never overwrites this file.
994
+
995
+ ## Account
996
+
997
+ ${profileLine}
998
+ ${retailerLine}
999
+
1000
+ ## First Steps
1001
+
1002
+ 1. **Verify setup:** run \`npx @fluentcommerce/ai-skills doctor\` in terminal — checks skills, MCP, knowledge, profiles
1003
+ 2. **Connect to account:** type \`/fluent-connect\` as your first prompt — downloads workflows, scans source, wires workspace
1004
+ 3. **Explore:** ask \`What can you do?\` or \`Show me the SDLC skill map\`
1005
+
1006
+ ## Reference Docs
1007
+
1008
+ When the user asks about capabilities, available skills, "what can you do", or needs help choosing a skill:
1009
+ - Read \`knowledge/index.md\` for the knowledge file registry
1010
+ - The SDLC skill map below covers all 64 skills organized by lifecycle stage
1011
+ - For scenario-based examples with exact prompts and outcomes, see:
1012
+ https://bitbucket.org/fluentcommerce/fluent-ai-skills/src/main/docs/use-cases.md
1013
+ - For agent routing and skill invocation guide:
1014
+ https://bitbucket.org/fluentcommerce/fluent-ai-skills/src/main/docs/agents-and-skills-guide.md
1015
+ - All docs: https://bitbucket.org/fluentcommerce/fluent-ai-skills/src/main/docs/index.md
1016
+
1017
+ ## MCP Tools
1018
+
1019
+ Configured in \`.mcp.json\` — use MCP tools for ALL live API operations:
1020
+ - **fluent-mcp** — Official Fluent CLI MCP (workflows, profiles, modules)
1021
+ - **fluent-mcp-extn** — Extension MCP with 45+ tools (GraphQL, events, batch, metrics, settings, entities)
1022
+ - **chrome-devtools** — Browser automation for UI testing and preview
1023
+
1024
+ Run \`/fluent-mcp-tools\` for the full tool reference.
1025
+
1026
+ ## SDLC Skill Map
1027
+
1028
+ Follow this lifecycle. Each stage has purpose-built skills:
1029
+
1030
+ | Stage | Skills | When |
1031
+ |---|---|---|
1032
+ | **Setup** | \`/fluent-connect\`, \`/fluent-bootstrap\`, \`/fluent-profile\` | First-time workspace setup, account onboarding |
1033
+ | **Discover** | \`/fluent-implementation-map\`, \`/fluent-feature-explain\`, \`/fluent-workflow-analyzer\`, \`/fluent-mystique-analyze\` | Understand what exists before changing anything |
1034
+ | **Requirements** | \`/fluent-use-case-discover\` | Turn business needs into an approved spec |
1035
+ | **Plan** | \`/fluent-feature-phase\`, \`/fluent-feature-plan\` | Break specs into phases, produce implementation contract |
1036
+ | **Build (backend)** | \`/fluent-workflow-builder\`, \`/fluent-rule-scaffold\`, \`/fluent-module-scaffold\`, \`/fluent-settings\` | Workflows, rules, modules, settings |
1037
+ | **Build (frontend)** | \`/fluent-mystique-builder\`, \`/fluent-mystique-scaffold\`, \`/fluent-mystique-component\` | Manifests, SDK components, pages |
1038
+ | **Validate** | \`/fluent-pre-deploy-check\`, \`/fluent-module-validate\`, \`/fluent-mystique-validate\`, \`/fluent-build\` | Quality gates before deploy |
1039
+ | **Deploy** | \`/fluent-module-deploy\`, \`/fluent-workflow-deploy\` | Push changes to environment |
1040
+ | **Test** | \`/fluent-test-data\`, \`/fluent-e2e-test\`, \`/fluent-ui-test\`, \`/fluent-transition-api\` | Create test data, run E2E, verify UI |
1041
+ | **Diagnose** | \`/fluent-trace\`, \`/fluent-system-monitoring\`, \`/fluent-connection-analysis\`, \`/fluent-rollback\` | Debug failures, monitor health, roll back |
1042
+ | **Audit** | \`/fluent-rfl-assess\`, \`/fluent-session\`, \`/fluent-feature-status\` | Go-live readiness, audit trail, status dashboard |
1043
+
1044
+ ## Quick Actions
1045
+
1046
+ | What you want | Say this |
1047
+ |---|---|
1048
+ | Connect to account | \`/fluent-connect --profile ${profileRef}\` |
1049
+ | What's deployed? | \`Map the implementation\` |
1050
+ | Build a feature | \`Help me define use cases for ...\` → \`Plan it\` → \`Build it\` |
1051
+ | Debug stuck order | \`Why is order HD-001 stuck?\` |
1052
+ | Create test data | \`Create a test HD order\` |
1053
+ | Build a workflow | \`Build an ORDER::RETURN workflow\` |
1054
+ | Edit a manifest | \`Add an appeasement form to the order page\` |
1055
+ | Scaffold a rule | \`Create a rule for ...\` |
1056
+ | Deploy | \`Deploy to staging\` |
1057
+ | Go-live audit | \`Run a Ready For Launch assessment\` |
1058
+
1059
+ ## Knowledge
1060
+
1061
+ - \`knowledge/\` — Platform knowledge (domain model, SDK reference, rule contracts, order patterns). Managed by installer.
1062
+ - \`accounts/<PROFILE>/knowledge/\` — Account-specific conventions. Create via \`/fluent-knowledge-init\`.
1063
+ - \`accounts/<PROFILE>/memory/\` — Auto-accumulated learnings from your sessions.
1064
+
1065
+ ## Conventions
1066
+
1067
+ <!-- Add your team-specific conventions below. Examples: -->
1068
+ <!-- - Order refs: ORD-{storeCode}-{seq} -->
1069
+ <!-- - All custom rules use prefix com.client. -->
1070
+ <!-- - Workflow subtypes: HD, CC, SFS (no custom types) -->
1071
+ <!-- - Always use MCP tools for GraphQL — never hardcode queries -->
1072
+ `;
1073
+
1074
+ writeFileSync(dest, content, "utf-8");
1075
+ return true;
1076
+ }
1077
+
978
1078
  function uninstallKnowledge() {
979
1079
  const dest = join(getProjectRoot(), "knowledge");
980
1080
  if (!existsSync(dest)) return false;
@@ -1297,7 +1397,7 @@ function runVerify(profile) {
1297
1397
  if (fluentVer) {
1298
1398
  pass("Fluent CLI", fluentVer);
1299
1399
  } else {
1300
- fail("Fluent CLI not found", "npm install -g @fluentcommerce/cli");
1400
+ fail("Fluent CLI not found", "Install from https://docs.fluentcommerce.com/building-blocks/fluent-cli-package");
1301
1401
  }
1302
1402
 
1303
1403
  // 3. Claude Code
@@ -1452,7 +1552,7 @@ function runVerify(profile) {
1452
1552
  if (existsSync(claudeMdPath)) {
1453
1553
  pass("CLAUDE.md", "workspace instructions present");
1454
1554
  } else {
1455
- warn("CLAUDE.md not found", "Create repo/workspace instructions manually if needed");
1555
+ warn("CLAUDE.md not found", "Re-run install to generate a starter, or create one manually");
1456
1556
  }
1457
1557
 
1458
1558
  // 8. Fluent CLI profile (if --profile provided or detected from MCP config)
@@ -1678,6 +1778,8 @@ function parseMcpSetupArgs(args) {
1678
1778
  extnRepo: DEFAULT_MCP_EXTN_REPO,
1679
1779
  profile: "",
1680
1780
  profileRetailer: "",
1781
+ profilesFile: "",
1782
+ discoverProfiles: false,
1681
1783
  officialServerName: "fluent-mcp",
1682
1784
  extnServerName: "fluent-mcp-extn",
1683
1785
  browserServerName: "chrome-devtools",
@@ -1765,6 +1867,15 @@ function parseMcpSetupArgs(args) {
1765
1867
  case "--save-video":
1766
1868
  options.saveVideo = args[++i] || "1920x1080";
1767
1869
  break;
1870
+ case "--profiles-file":
1871
+ options.profilesFile = args[++i];
1872
+ if (!options.profilesFile) {
1873
+ throw new Error("Missing value for --profiles-file");
1874
+ }
1875
+ break;
1876
+ case "--discover-profiles":
1877
+ options.discoverProfiles = true;
1878
+ break;
1768
1879
  default:
1769
1880
  throw new Error(`Unknown option for mcp-setup: ${arg}`);
1770
1881
  }
@@ -1774,9 +1885,80 @@ function parseMcpSetupArgs(args) {
1774
1885
  throw new Error("--profile-retailer requires --profile");
1775
1886
  }
1776
1887
 
1888
+ if (options.discoverProfiles && options.profilesFile) {
1889
+ throw new Error("--discover-profiles and --profiles-file are mutually exclusive");
1890
+ }
1891
+
1777
1892
  return options;
1778
1893
  }
1779
1894
 
1895
+ /**
1896
+ * Scan ~/.fluentcommerce/ for CLI profile directories and their retailer overrides.
1897
+ * Returns an array of { profile, retailer? } entries suitable for fluent-profiles.json.
1898
+ */
1899
+ function discoverFluentProfiles() {
1900
+ const fluentDir = join(homedir(), ".fluentcommerce");
1901
+ if (!existsSync(fluentDir)) {
1902
+ throw new Error(`No Fluent CLI profiles found: ${fluentDir} does not exist`);
1903
+ }
1904
+
1905
+ const entries = [];
1906
+ const dirs = readdirSync(fluentDir, { withFileTypes: true })
1907
+ .filter((d) => d.isDirectory() && !d.name.startsWith("."))
1908
+ .map((d) => d.name)
1909
+ .sort();
1910
+
1911
+ for (const dirName of dirs) {
1912
+ const profileJsonPath = join(fluentDir, dirName, "profile.json");
1913
+ if (!existsSync(profileJsonPath)) continue;
1914
+
1915
+ // Find retailer override files: retailer.<REF>.json
1916
+ const profileDir = join(fluentDir, dirName);
1917
+ const retailerFiles = readdirSync(profileDir)
1918
+ .filter((f) => f.startsWith("retailer.") && f.endsWith(".json") && !f.endsWith(".bak"))
1919
+ .sort();
1920
+
1921
+ if (retailerFiles.length === 0) {
1922
+ // Profile with no retailer overrides — add as profile-only entry
1923
+ entries.push({ profile: dirName });
1924
+ } else {
1925
+ for (const rf of retailerFiles) {
1926
+ // Extract retailer ref from filename: retailer.<REF>.json
1927
+ const ref = rf.slice("retailer.".length, -".json".length);
1928
+ if (ref) {
1929
+ entries.push({ profile: dirName, retailer: ref });
1930
+ }
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+ if (entries.length === 0) {
1936
+ throw new Error(`No valid profiles found in ${fluentDir} (no profile.json files)`);
1937
+ }
1938
+
1939
+ return entries;
1940
+ }
1941
+
1942
+ /**
1943
+ * Read and validate a profiles JSON file. Returns the parsed array.
1944
+ */
1945
+ function readProfilesFile(filePath) {
1946
+ const resolved = resolve(filePath);
1947
+ if (!existsSync(resolved)) {
1948
+ throw new Error(`Profiles file not found: ${resolved}`);
1949
+ }
1950
+ const parsed = JSON.parse(readFileSync(resolved, "utf-8"));
1951
+ if (!Array.isArray(parsed) || parsed.length === 0) {
1952
+ throw new Error(`Profiles file must be a non-empty JSON array: ${resolved}`);
1953
+ }
1954
+ for (const entry of parsed) {
1955
+ if (!entry.profile || typeof entry.profile !== "string") {
1956
+ throw new Error(`Each entry in profiles file must have a "profile" string: ${JSON.stringify(entry)}`);
1957
+ }
1958
+ }
1959
+ return parsed;
1960
+ }
1961
+
1780
1962
  function buildManagedMcpConfigs(options, settings = {}) {
1781
1963
  const codexGlobal = Boolean(settings.codexGlobal);
1782
1964
  const startup_timeout_sec = codexGlobal ? 30.0 : undefined;
@@ -1826,6 +2008,14 @@ function buildManagedMcpConfigs(options, settings = {}) {
1826
2008
  FLUENT_RETAILER_ID: "YOUR_RETAILER",
1827
2009
  };
1828
2010
  }
2011
+ // Multi-profile: wire profiles file into extn server for connection.list/switch
2012
+ if (options.resolvedProfilesFile) {
2013
+ extnDesired.env = {
2014
+ ...extnDesired.env,
2015
+ FLUENT_PROFILES_FILE: options.resolvedProfilesFile,
2016
+ FLUENT_CACHE_ENABLED: "true",
2017
+ };
2018
+ }
1829
2019
 
1830
2020
  let browserDesired = null;
1831
2021
  if (!options.noBrowser) {
@@ -2030,6 +2220,41 @@ function setupMcp(options) {
2030
2220
  // lands in the workspace root, not inside a sub-package that happens to
2031
2221
  // have its own .git directory.
2032
2222
  const projectRoot = getProjectRoot();
2223
+
2224
+ // --- Multi-profile: discover or validate profiles file ---
2225
+ if (options.discoverProfiles) {
2226
+ const profiles = discoverFluentProfiles();
2227
+ const profilesPath = join(projectRoot, "fluent-profiles.json");
2228
+ writeFileSync(profilesPath, `${JSON.stringify(profiles, null, 2)}\n`);
2229
+ logOk(`discovered ${profiles.length} profile/retailer entries → fluent-profiles.json`);
2230
+ options.resolvedProfilesFile = "./fluent-profiles.json";
2231
+ // Use first entry as default profile if --profile not explicitly provided
2232
+ if (!options.profile && profiles[0]) {
2233
+ options.profile = profiles[0].profile;
2234
+ if (profiles[0].retailer && !options.profileRetailer) {
2235
+ options.profileRetailer = profiles[0].retailer;
2236
+ }
2237
+ log(` Default profile: ${options.profile}${options.profileRetailer ? ` / ${options.profileRetailer}` : ""}`);
2238
+ }
2239
+ } else if (options.profilesFile) {
2240
+ const profiles = readProfilesFile(options.profilesFile);
2241
+ // Store relative path for .mcp.json (relative to project root)
2242
+ const absPath = resolve(options.profilesFile);
2243
+ const relPath = absPath.startsWith(projectRoot)
2244
+ ? "./" + absPath.slice(projectRoot.length + 1).replace(/\\/g, "/")
2245
+ : absPath.replace(/\\/g, "/");
2246
+ options.resolvedProfilesFile = relPath;
2247
+ logOk(`validated profiles file: ${relPath} (${profiles.length} entries)`);
2248
+ // Use first entry as default profile if --profile not explicitly provided
2249
+ if (!options.profile && profiles[0]) {
2250
+ options.profile = profiles[0].profile;
2251
+ if (profiles[0].retailer && !options.profileRetailer) {
2252
+ options.profileRetailer = profiles[0].retailer;
2253
+ }
2254
+ log(` Default profile: ${options.profile}${options.profileRetailer ? ` / ${options.profileRetailer}` : ""}`);
2255
+ }
2256
+ }
2257
+
2033
2258
  const mcpConfigPath = join(projectRoot, ".mcp.json");
2034
2259
  const mcpConfig = readJsonObjectOrDefault(mcpConfigPath, {});
2035
2260
 
@@ -2062,6 +2287,14 @@ function setupMcp(options) {
2062
2287
  : {}),
2063
2288
  };
2064
2289
  }
2290
+ // Preserve profiles file env from buildManagedMcpConfigs
2291
+ if (options.resolvedProfilesFile) {
2292
+ extnMerged.env = {
2293
+ ...(extnMerged.env || {}),
2294
+ FLUENT_PROFILES_FILE: options.resolvedProfilesFile,
2295
+ FLUENT_CACHE_ENABLED: "true",
2296
+ };
2297
+ }
2065
2298
  stripSensitiveEnv(extnMerged);
2066
2299
 
2067
2300
  mcpConfig.mcpServers[options.officialServerName] = officialMerged;
@@ -2098,8 +2331,11 @@ function setupMcp(options) {
2098
2331
  log("");
2099
2332
  log("MCP bootstrap complete.");
2100
2333
  log(`Updated: ${mcpConfigPath}`);
2101
- logOk(`official server: ${options.officialServerName}`);
2102
- logOk(`extension server: ${options.extnServerName}`);
2334
+ logOk(`official server: ${options.officialServerName}${options.profile ? ` (profile: ${options.profile})` : ""}`);
2335
+ logOk(`extension server: ${options.extnServerName}${options.resolvedProfilesFile ? " (multi-profile)" : ""}`);
2336
+ if (options.resolvedProfilesFile) {
2337
+ logOk(`profiles file: ${options.resolvedProfilesFile} → connection.list / connection.switch`);
2338
+ }
2103
2339
  if (!options.noBrowser) {
2104
2340
  logOk(`chrome-devtools server: ${options.browserServerName} (for /fluent-ui-test, /fluent-ui-record)`);
2105
2341
  if (options.saveVideo) {
@@ -2825,6 +3061,8 @@ GLOBAL OPTIONS
2825
3061
  --scope <name> Codex scope: user (default) or project
2826
3062
  --profile <name> Fluent CLI profile — auto-configures .mcp.json on install
2827
3063
  --profile-retailer <ref> Retailer ref (requires --profile)
3064
+ --profiles-file <path> Path to fluent-profiles.json for multi-profile switching
3065
+ --discover-profiles Scan ~/.fluentcommerce/ and generate fluent-profiles.json
2828
3066
  --install-mcp-extn npm install @fluentcommerce/fluent-mcp-extn locally (faster startup)
2829
3067
 
2830
3068
  GROUPS
@@ -2840,6 +3078,9 @@ EXAMPLES
2840
3078
  npx @fluentcommerce/ai-skills generate
2841
3079
  npx @fluentcommerce/ai-skills mcp-setup --profile MYPROFILE
2842
3080
  npx @fluentcommerce/ai-skills mcp-setup --profile MYPROFILE --profile-retailer MY_RETAILER
3081
+ npx @fluentcommerce/ai-skills mcp-setup --discover-profiles
3082
+ npx @fluentcommerce/ai-skills mcp-setup --profiles-file ./fluent-profiles.json
3083
+ npx @fluentcommerce/ai-skills mcp-setup --profile MYPROFILE --profiles-file ./fluent-profiles.json
2843
3084
  npx @fluentcommerce/ai-skills mcp-setup --with-chrome
2844
3085
  npx @fluentcommerce/ai-skills mcp-setup --install-extn-source
2845
3086
  npx @fluentcommerce/ai-skills flow-run --profile MYPROFILE --retailer MY_RETAILER --module dist/module.zip
@@ -2854,6 +3095,8 @@ NOTES
2854
3095
  - Use --save-video [resolution] to enable browser video recording via experimentalScreencast (default: 1920x1080).
2855
3096
  - Chrome MCP Extension is opt-in for manual debugging with existing Chrome sessions. Use --with-chrome to add it alongside Chrome DevTools MCP. Requires Chrome extension from https://github.com/hangwin/mcp-chrome
2856
3097
  - mcp-setup writes/merges .mcp.json in the project root and preserves existing servers.
3098
+ - Multi-profile: --discover-profiles scans ~/.fluentcommerce/ for CLI profiles and retailer overrides, generates fluent-profiles.json, and wires it into the extension server. Use --profiles-file to point to an existing file instead. The first entry becomes the default profile. Switch profiles at runtime via connection.list / connection.switch MCP tools.
3099
+ - When --profiles-file or --discover-profiles is combined with --profile, the explicit --profile takes precedence as the default (overriding the first-entry default).
2857
3100
  - Aliases: mcp -> mcp-extn, mcp-core -> mcp-official.
2858
3101
 
2859
3102
  ENVIRONMENT VARIABLES (optional overrides — profile-based auth is primary)
@@ -2884,6 +3127,8 @@ function parseArgs(argv) {
2884
3127
  let scope = "user";
2885
3128
  let profile = "";
2886
3129
  let profileRetailer = "";
3130
+ let profilesFile = "";
3131
+ let discoverProfilesFlag = false;
2887
3132
  const rest = [];
2888
3133
 
2889
3134
  for (let i = 0; i < argv.length; i++) {
@@ -2917,6 +3162,14 @@ function parseArgs(argv) {
2917
3162
  throw new Error("Missing value for --profile-retailer");
2918
3163
  }
2919
3164
  i++;
3165
+ } else if (argv[i] === "--profiles-file") {
3166
+ profilesFile = argv[i + 1] || "";
3167
+ if (!profilesFile) {
3168
+ throw new Error("Missing value for --profiles-file");
3169
+ }
3170
+ i++;
3171
+ } else if (argv[i] === "--discover-profiles") {
3172
+ discoverProfilesFlag = true;
2920
3173
  } else {
2921
3174
  rest.push(argv[i]);
2922
3175
  }
@@ -2928,6 +3181,8 @@ function parseArgs(argv) {
2928
3181
  scope: normalizeCodexScope(scope),
2929
3182
  profile,
2930
3183
  profileRetailer,
3184
+ profilesFile,
3185
+ discoverProfiles: discoverProfilesFlag,
2931
3186
  command: rest[0],
2932
3187
  commandArgs: rest.slice(1),
2933
3188
  groupArgs: rest.slice(1).filter((v) => !v.startsWith("--")).map((v) => v.toLowerCase()),
@@ -2954,7 +3209,7 @@ function main() {
2954
3209
  process.exit(1);
2955
3210
  }
2956
3211
 
2957
- const { projectRoot, target, scope, profile, profileRetailer, command, commandArgs, groupArgs } = parsed;
3212
+ const { projectRoot, target, scope, profile, profileRetailer, profilesFile, discoverProfiles, command, commandArgs, groupArgs } = parsed;
2958
3213
 
2959
3214
  try {
2960
3215
  setProjectRoot(resolveProjectRoot(projectRoot));
@@ -2981,18 +3236,25 @@ function main() {
2981
3236
  logOk(`knowledge: ${knowledgeCount} file(s) → knowledge/`);
2982
3237
  }
2983
3238
 
3239
+ // Generate starter CLAUDE.md if not present (never overwrites)
3240
+ if (generateStarterClaudeMd(profile, profileRetailer)) {
3241
+ logOk("CLAUDE.md: starter workspace instructions created");
3242
+ }
3243
+
2984
3244
  log("");
2985
3245
  log(`Done. Groups: ${selected.map((g) => g.name).join(", ")}`);
2986
3246
 
2987
- // Auto-configure MCP when --profile is provided
2988
- if (profile) {
3247
+ // Auto-configure MCP when --profile or --discover-profiles or --profiles-file is provided
3248
+ if (profile || discoverProfiles || profilesFile) {
2989
3249
  log("");
2990
3250
  log("Configuring MCP servers...");
2991
3251
  log("==========================");
2992
3252
  try {
2993
3253
  const mcpOptions = parseMcpSetupArgs([
2994
- "--profile", profile,
3254
+ ...(profile ? ["--profile", profile] : []),
2995
3255
  ...(profileRetailer ? ["--profile-retailer", profileRetailer] : []),
3256
+ ...(profilesFile ? ["--profiles-file", profilesFile] : []),
3257
+ ...(discoverProfiles ? ["--discover-profiles"] : []),
2996
3258
  ]);
2997
3259
  if (target === "codex" && scope === "user") {
2998
3260
  setupCodexGlobalMcp(mcpOptions);
@@ -3061,7 +3323,7 @@ function main() {
3061
3323
  case "mcp-setup":
3062
3324
  case "setup-mcp":
3063
3325
  case "init-mcp": {
3064
- // Re-inject --profile/--profile-retailer if parsed at top level
3326
+ // Re-inject top-level args if not already in command-specific args
3065
3327
  const mcpArgs = [...commandArgs];
3066
3328
  if (profile && !mcpArgs.includes("--profile") && !mcpArgs.includes("-p")) {
3067
3329
  mcpArgs.push("--profile", profile);
@@ -3069,6 +3331,12 @@ function main() {
3069
3331
  if (profileRetailer && !mcpArgs.includes("--profile-retailer")) {
3070
3332
  mcpArgs.push("--profile-retailer", profileRetailer);
3071
3333
  }
3334
+ if (profilesFile && !mcpArgs.includes("--profiles-file")) {
3335
+ mcpArgs.push("--profiles-file", profilesFile);
3336
+ }
3337
+ if (discoverProfiles && !mcpArgs.includes("--discover-profiles")) {
3338
+ mcpArgs.push("--discover-profiles");
3339
+ }
3072
3340
  const options = parseMcpSetupArgs(mcpArgs);
3073
3341
  if (target === "codex" && scope === "user") {
3074
3342
  setupCodexGlobalMcp(options);
@@ -97,7 +97,8 @@ jobs:
97
97
  with: { node-version: 20 }
98
98
 
99
99
  - name: Install Fluent CLI
100
- run: npm i -g @fluentcommerce/cli
100
+ # Install method: https://docs.fluentcommerce.com/building-blocks/fluent-cli-package
101
+ run: echo "Replace with your org's Fluent CLI install step"
101
102
 
102
103
  - name: Create profile
103
104
  run: |
@@ -134,7 +135,8 @@ fluent-deploy:
134
135
  only:
135
136
  changes: [plugins/**, resources/**]
136
137
  before_script:
137
- - npm i -g @fluentcommerce/cli
138
+ # Install method: https://docs.fluentcommerce.com/building-blocks/fluent-cli-package
139
+ - echo "Replace with your org's Fluent CLI install step"
138
140
  - apt-get update && apt-get install -y maven
139
141
  script:
140
142
  - fluent profile create deploy-target --id $FLUENT_ACCOUNT_ID --base-url $FLUENT_BASE_URL --username $FLUENT_USERNAME --password $FLUENT_PASSWORD --client-secret $FLUENT_CLIENT_SECRET
@@ -167,7 +169,8 @@ jobs:
167
169
  - uses: actions/checkout@v4
168
170
  - uses: actions/setup-node@v4
169
171
  with: { node-version: '20' }
170
- - run: npm install -g @fluentcommerce/cli
172
+ # Install method: https://docs.fluentcommerce.com/building-blocks/fluent-cli-package
173
+ - run: echo "Replace with your org's Fluent CLI install step"
171
174
  - name: Validate
172
175
  run: fluent module validate --path ${{ github.workspace }}/modules/$MODULE_NAME
173
176
  - name: Pre-deploy check