@chemx/starter-kit 26.9.9-720 → 26.9.9-786

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/cli/index.js CHANGED
@@ -1,60 +1,65 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import os from 'node:os';
6
- import readline from 'node:readline';
7
- import { spawnSync } from 'node:child_process';
8
- import { runAudit as executeAstAudit, auditFile } from './audit.js';
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import os from "node:os";
6
+ import readline from "node:readline";
7
+ import { spawnSync } from "node:child_process";
8
+ import { runAudit as executeAstAudit, auditFile } from "./audit.js";
9
9
 
10
10
  const rawArgs = process.argv.slice(2);
11
- const invokedBin = path.basename(process.argv[1] || '');
12
- const isCreateInvoked = invokedBin.includes('create-chemx') || (rawArgs[0] && rawArgs[0] === 'create');
11
+ const invokedBin = path.basename(process.argv[1] || "");
12
+ const isCreateInvoked =
13
+ invokedBin.includes("create-chemx") || (rawArgs[0] && rawArgs[0] === "create");
13
14
 
14
- const CONFIG_DIR = path.join(os.homedir(), '.chemical-x');
15
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
16
- const DEVICE_FILE = path.join(CONFIG_DIR, 'device_id');
15
+ const CONFIG_DIR = path.join(os.homedir(), ".chemical-x");
16
+ const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
17
+ const DEVICE_FILE = path.join(CONFIG_DIR, "device_id");
17
18
 
18
- const API_BASE = process.env.CHEMICAL_X_API_URL || 'https://chemicalx.xophz.com';
19
- const URL_STANDARD = 'https://mycompassconsulting.com/buy/chemical-x/standard';
20
- const URL_MASTER = 'https://mycompassconsulting.com/buy/chemical-x/master';
19
+ const API_BASE = process.env.CHEMICAL_X_API_URL || "https://chemicalx.xophz.com";
20
+ const URL_LEARN = "https://chemicalx.xophz.com";
21
+ const URL_STANDARD = "https://mycompassconsulting.com/buy/chemical-x/standard";
22
+ const URL_MASTER = "https://mycompassconsulting.com/buy/chemical-x/master";
21
23
 
22
24
  if (!fs.existsSync(CONFIG_DIR)) {
23
- try { fs.mkdirSync(CONFIG_DIR, { recursive: true }); } catch {}
25
+ try {
26
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
27
+ } catch {}
24
28
  }
25
29
 
26
30
  const openBrowser = (url) => {
27
31
  const platform = process.platform;
28
32
  try {
29
- if (platform === 'darwin') spawnSync('open', [url], { stdio: 'ignore' });
30
- else if (platform === 'win32') spawnSync('cmd.exe', ['/c', 'start', '""', url], { stdio: 'ignore' });
31
- else spawnSync('xdg-open', [url], { stdio: 'ignore' });
33
+ if (platform === "darwin") spawnSync("open", [url], { stdio: "ignore" });
34
+ else if (platform === "win32")
35
+ spawnSync("cmd.exe", ["/c", "start", '""', url], { stdio: "ignore" });
36
+ else spawnSync("xdg-open", [url], { stdio: "ignore" });
32
37
  } catch {}
33
38
  };
34
39
 
35
40
  const hasGum = () => {
36
41
  try {
37
- return spawnSync('which', ['gum'], { stdio: 'ignore' }).status === 0;
42
+ return spawnSync("which", ["gum"], { stdio: "ignore" }).status === 0;
38
43
  } catch {
39
44
  return false;
40
45
  }
41
46
  };
42
47
 
43
- const gumChoose = (options, header = '') => {
44
- const args = ['choose'];
48
+ const gumChoose = (options, header = "") => {
49
+ const args = ["choose"];
45
50
  if (header) {
46
- args.push(`--header=${header}`, '--header.foreground=81');
51
+ args.push(`--header=${header}`, "--header.foreground=81");
47
52
  }
48
- args.push('--cursor.foreground=81', ...options);
49
- const res = spawnSync('gum', args, { encoding: 'utf-8', stdio: ['inherit', 'pipe', 'inherit'] });
50
- return (res.stdout || '').trim();
53
+ args.push("--cursor.foreground=81", ...options);
54
+ const res = spawnSync("gum", args, { encoding: "utf-8", stdio: ["inherit", "pipe", "inherit"] });
55
+ return (res.stdout || "").trim();
51
56
  };
52
57
 
53
- const gumInput = (promptText, placeholder = '', isPassword = false) => {
54
- const args = ['input', `--prompt=${promptText} `, `--placeholder=${placeholder}`];
55
- if (isPassword) args.push('--password');
56
- const res = spawnSync('gum', args, { encoding: 'utf-8', stdio: ['inherit', 'pipe', 'inherit'] });
57
- return (res.stdout || '').trim();
58
+ const gumInput = (promptText, placeholder = "", isPassword = false) => {
59
+ const args = ["input", `--prompt=${promptText} `, `--placeholder=${placeholder}`];
60
+ if (isPassword) args.push("--password");
61
+ const res = spawnSync("gum", args, { encoding: "utf-8", stdio: ["inherit", "pipe", "inherit"] });
62
+ return (res.stdout || "").trim();
58
63
  };
59
64
 
60
65
  const promptQuestion = (query) => {
@@ -70,19 +75,21 @@ const promptQuestion = (query) => {
70
75
  const getOrCreateDeviceId = () => {
71
76
  if (fs.existsSync(DEVICE_FILE)) {
72
77
  try {
73
- const id = fs.readFileSync(DEVICE_FILE, 'utf-8').trim();
78
+ const id = fs.readFileSync(DEVICE_FILE, "utf-8").trim();
74
79
  if (id) return id;
75
80
  } catch {}
76
81
  }
77
82
  const newId = `cli_${Math.random().toString(36).substring(2, 12)}_${Date.now()}`;
78
- try { fs.writeFileSync(DEVICE_FILE, newId, 'utf-8'); } catch {}
83
+ try {
84
+ fs.writeFileSync(DEVICE_FILE, newId, "utf-8");
85
+ } catch {}
79
86
  return newId;
80
87
  };
81
88
 
82
89
  const getCachedLicenseKey = () => {
83
90
  if (fs.existsSync(CONFIG_FILE)) {
84
91
  try {
85
- const data = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
92
+ const data = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
86
93
  return data.licenseKey || null;
87
94
  } catch {
88
95
  return null;
@@ -93,33 +100,45 @@ const getCachedLicenseKey = () => {
93
100
 
94
101
  const saveLicenseKey = (licenseKey) => {
95
102
  try {
96
- fs.writeFileSync(CONFIG_FILE, JSON.stringify({ licenseKey, updatedAt: new Date().toISOString() }, null, 2), 'utf-8');
103
+ fs.writeFileSync(
104
+ CONFIG_FILE,
105
+ JSON.stringify({ licenseKey, updatedAt: new Date().toISOString() }, null, 2),
106
+ "utf-8"
107
+ );
97
108
  } catch {}
98
109
  };
99
110
 
100
- const renderBanner = (title = 'Chemical X Protocol: Quantum Architecture') => {
111
+ const renderBanner = (title = "Chemical X Protocol: Quantum Architecture") => {
101
112
  if (hasGum()) {
102
- spawnSync('gum', [
103
- 'style',
104
- '--border=normal',
105
- '--margin=1',
106
- '--padding=1 2',
107
- '--border-foreground=45',
108
- '--foreground=81',
109
- '--bold',
110
- ` ${title}\n Zero-Context-Rot Scaffolding & Engineering Directives`
111
- ], { stdio: 'inherit' });
113
+ spawnSync(
114
+ "gum",
115
+ [
116
+ "style",
117
+ "--border=normal",
118
+ "--margin=1",
119
+ "--padding=1 2",
120
+ "--border-foreground=45",
121
+ "--foreground=81",
122
+ "--bold",
123
+ ` ${title}\n Zero-Context-Rot Scaffolding & Engineering Directives`
124
+ ],
125
+ { stdio: "inherit" }
126
+ );
112
127
  } else {
113
- process.stdout.write('\n\x1b[38;2;98;201;255m=====================================================\x1b[0m\n');
128
+ process.stdout.write(
129
+ "\n\x1b[38;2;98;201;255m=====================================================\x1b[0m\n"
130
+ );
114
131
  process.stdout.write(`\x1b[1m\x1b[38;2;98;201;255m ${title}\x1b[0m\n`);
115
- process.stdout.write(' Zero-Context-Rot Scaffolding & Engineering Directives\n');
116
- process.stdout.write('\x1b[38;2;98;201;255m=====================================================\x1b[0m\n\n');
132
+ process.stdout.write(" Zero-Context-Rot Scaffolding & Engineering Directives\n");
133
+ process.stdout.write(
134
+ "\x1b[38;2;98;201;255m=====================================================\x1b[0m\n\n"
135
+ );
117
136
  }
118
137
  };
119
138
 
120
139
  const obtainLicenseKey = async () => {
121
140
  let cached = getCachedLicenseKey();
122
- const cliFlagIdx = rawArgs.indexOf('--license');
141
+ const cliFlagIdx = rawArgs.indexOf("--license");
123
142
  if (cliFlagIdx !== -1 && rawArgs[cliFlagIdx + 1]) {
124
143
  cached = rawArgs[cliFlagIdx + 1].trim();
125
144
  }
@@ -131,77 +150,96 @@ const obtainLicenseKey = async () => {
131
150
  const useGum = hasGum();
132
151
 
133
152
  if (useGum) {
134
- const choice = gumChoose([
135
- '1. Buy Standard Edition ($49) -> Launch Checkout',
136
- '2. Buy Master Bundle ($99) -> Launch Checkout',
137
- '3. Enter License Key (CX-XXXX-XXXX-XXXX)',
138
- '4. Run Free Public Audit (npx chemx audit)',
139
- '5. Exit'
140
- ], 'Chemical X Scaffolding Requires a Paid License:');
141
-
142
- if (choice.startsWith('1.')) {
143
- process.stdout.write(`\x1b[36mOpening checkout in default browser:\x1b[0m ${URL_STANDARD}\n`);
153
+ const choice = gumChoose(
154
+ [
155
+ "1. Visit chemicalx.xophz.com to learn more",
156
+ "2. Buy eBook w/ AGENTS.md Rule Book ($27) -> Launch Checkout",
157
+ "3. Buy Master Bundle ($47) -> Launch Checkout",
158
+ "4. Enter License Key (CX-XXXX-XXXX-XXXX)",
159
+ "5. Run Free Public Audit (npx chemx audit)",
160
+ "6. Exit"
161
+ ],
162
+ "Chemical X Scaffolding Requires a Paid License:"
163
+ );
164
+
165
+ if (choice.startsWith("1.")) {
166
+ process.stdout.write(`\x1b[36mOpening Chemical X Portal in default browser:\x1b[0m ${URL_LEARN}\n`);
167
+ openBrowser(URL_LEARN);
168
+ process.stdout.write("\nOnce completed, paste your Sponsor / VIP License Key below.\n");
169
+ return gumInput("License Key (CX-XXXX-XXXX-XXXX):", "CX-XXXX-XXXX-XXXX");
170
+ }
171
+
172
+ if (choice.startsWith("2.")) {
173
+ process.stdout.write(`\x1b[36mOpening Standard Vault checkout in default browser:\x1b[0m ${URL_STANDARD}\n`);
144
174
  openBrowser(URL_STANDARD);
145
- process.stdout.write('\nOnce completed, paste your Sponsor / VIP License Key below.\n');
146
- return gumInput('License Key (CX-XXXX-XXXX-XXXX):', 'CX-XXXX-XXXX-XXXX');
175
+ process.stdout.write("\nOnce completed, paste your Sponsor / VIP License Key below.\n");
176
+ return gumInput("License Key (CX-XXXX-XXXX-XXXX):", "CX-XXXX-XXXX-XXXX");
147
177
  }
148
178
 
149
- if (choice.startsWith('2.')) {
150
- process.stdout.write(`\x1b[36mOpening checkout in default browser:\x1b[0m ${URL_MASTER}\n`);
179
+ if (choice.startsWith("3.")) {
180
+ process.stdout.write(`\x1b[36mOpening Master Bundle checkout in default browser:\x1b[0m ${URL_MASTER}\n`);
151
181
  openBrowser(URL_MASTER);
152
- process.stdout.write('\nOnce completed, paste your Sponsor / VIP License Key below.\n');
153
- return gumInput('License Key (CX-XXXX-XXXX-XXXX):', 'CX-XXXX-XXXX-XXXX');
182
+ process.stdout.write("\nOnce completed, paste your Sponsor / VIP License Key below.\n");
183
+ return gumInput("License Key (CX-XXXX-XXXX-XXXX):", "CX-XXXX-XXXX-XXXX");
154
184
  }
155
185
 
156
- if (choice.startsWith('3.')) {
157
- return gumInput('License Key (CX-XXXX-XXXX-XXXX):', 'CX-XXXX-XXXX-XXXX');
186
+ if (choice.startsWith("4.")) {
187
+ return gumInput("License Key (CX-XXXX-XXXX-XXXX):", "CX-XXXX-XXXX-XXXX");
158
188
  }
159
189
 
160
- if (choice.startsWith('4.')) {
190
+ if (choice.startsWith("5.")) {
161
191
  await runAudit(null, true);
162
192
  }
163
193
 
164
- if (choice.startsWith('5.') || !choice) {
194
+ if (choice.startsWith("6.") || !choice) {
165
195
  process.exit(0);
166
196
  }
167
197
 
168
- return gumInput('License Key (CX-XXXX-XXXX-XXXX):', 'CX-XXXX-XXXX-XXXX');
198
+ return gumInput("License Key (CX-XXXX-XXXX-XXXX):", "CX-XXXX-XXXX-XXXX");
169
199
  }
170
200
 
171
- process.stdout.write('\x1b[1mChemical X Scaffolding Requires a Paid License:\x1b[0m\n');
172
- process.stdout.write(' [1] Buy Standard Edition ($49) - Opens browser\n');
173
- process.stdout.write(' [2] Buy Master Bundle ($99) - Opens browser\n');
174
- process.stdout.write(' [3] Enter License Key\n');
175
- process.stdout.write(' [4] Run Free Public Audit (npx chemx audit)\n');
176
- process.stdout.write(' [5] Exit\n\n');
177
-
178
- const selection = await promptQuestion('Select option [1-5]: ');
201
+ process.stdout.write("\x1b[1mChemical X Scaffolding Requires a Paid License:\x1b[0m\n");
202
+ process.stdout.write(" [1] Visit chemicalx.xophz.com to learn more\n");
203
+ process.stdout.write(" [2] Buy eBook w/ AGENTS.md Rule Book ($27) - Opens browser\n");
204
+ process.stdout.write(" [3] Buy Master Bundle ($47) - Opens browser\n");
205
+ process.stdout.write(" [4] Enter License Key\n");
206
+ process.stdout.write(" [5] Run Free Public Audit (npx chemx audit)\n");
207
+ process.stdout.write(" [6] Exit\n\n");
208
+
209
+ const selection = await promptQuestion("Select option [1-6] (default: 1): ");
210
+ const effectiveChoice = selection.trim() || "1";
211
+
212
+ if (effectiveChoice === "1") {
213
+ process.stdout.write(`Opening: ${URL_LEARN}\n`);
214
+ openBrowser(URL_LEARN);
215
+ return promptQuestion("Enter License Key after review (or press Enter to exit): ");
216
+ }
179
217
 
180
- if (selection === '1') {
218
+ if (effectiveChoice === "2") {
181
219
  process.stdout.write(`Opening: ${URL_STANDARD}\n`);
182
220
  openBrowser(URL_STANDARD);
183
- return promptQuestion('Enter License Key after purchase: ');
221
+ return promptQuestion("Enter License Key after purchase: ");
184
222
  }
185
223
 
186
- if (selection === '2') {
224
+ if (effectiveChoice === "3") {
187
225
  process.stdout.write(`Opening: ${URL_MASTER}\n`);
188
226
  openBrowser(URL_MASTER);
189
- return promptQuestion('Enter License Key after purchase: ');
227
+ return promptQuestion("Enter License Key after purchase: ");
190
228
  }
191
229
 
192
- if (selection === '3') {
193
- return promptQuestion('Enter License Key (CX-XXXX-XXXX-XXXX): ');
230
+ if (effectiveChoice === "4") {
231
+ return promptQuestion("Enter License Key (CX-XXXX-XXXX-XXXX): ");
194
232
  }
195
233
 
196
- if (selection === '4') {
234
+ if (effectiveChoice === "5") {
197
235
  await runAudit(null, true);
198
236
  }
199
237
 
200
- if (selection === '5') {
238
+ if (effectiveChoice === "6") {
201
239
  process.exit(0);
202
240
  }
203
241
 
204
- return promptQuestion('Enter Chemical X Sponsor License Key (CX-XXXX-XXXX-XXXX): ');
242
+ return promptQuestion("Enter Chemical X Sponsor License Key (CX-XXXX-XXXX-XXXX): ");
205
243
  };
206
244
 
207
245
  const fetchStarterKitFiles = async (licenseKey) => {
@@ -212,51 +250,61 @@ const fetchStarterKitFiles = async (licenseKey) => {
212
250
 
213
251
  try {
214
252
  const res = await fetch(`${API_BASE}/api/starter-kit/download`, {
215
- method: 'POST',
216
- headers: { 'Content-Type': 'application/json' },
253
+ method: "POST",
254
+ headers: { "Content-Type": "application/json" },
217
255
  body: JSON.stringify({ licenseKey: normalizedKey, deviceId })
218
256
  });
219
257
 
220
258
  const responseData = await res.json();
221
259
 
222
260
  if (!res.ok || !responseData.valid) {
223
- process.stderr.write(`\x1b[31m✕ License Verification Failed: ${responseData.error || 'Invalid key.'}\x1b[0m\n`);
261
+ process.stderr.write(
262
+ `\x1b[31m✕ License Verification Failed: ${responseData.error || "Invalid key."}\x1b[0m\n`
263
+ );
224
264
  process.stderr.write(`Purchase key at: ${URL_STANDARD}\n\n`);
225
265
  process.exit(1);
226
266
  }
227
267
 
228
268
  saveLicenseKey(normalizedKey);
229
- process.stdout.write(`\x1b[32m✔ Verified License for @${responseData.githubUser || 'sponsor'}\x1b[0m\n\n`);
269
+ process.stdout.write(
270
+ `\x1b[32m✔ Verified License for @${responseData.githubUser || "sponsor"}\x1b[0m\n\n`
271
+ );
230
272
  return responseData.files || {};
231
273
  } catch (err) {
232
- process.stderr.write(`\x1b[31m✕ Network Error: Failed to reach edge server (${err.message}).\x1b[0m\n`);
274
+ process.stderr.write(
275
+ `\x1b[31m✕ Network Error: Failed to reach edge server (${err.message}).\x1b[0m\n`
276
+ );
233
277
  process.exit(1);
234
278
  }
235
279
  };
236
280
 
237
281
  const runScaffold = async (projectName) => {
238
- renderBanner('Chemical X: Quantum Scaffolder (npm create chemx)');
282
+ renderBanner("Chemical X: Quantum Scaffolder (npm create chemx)");
239
283
 
240
284
  const licenseKey = await obtainLicenseKey();
241
285
  if (!licenseKey) {
242
- process.stderr.write('\x1b[31m✕ Valid license key is required to scaffold blueprints.\x1b[0m\n');
286
+ process.stderr.write(
287
+ "\x1b[31m✕ Valid license key is required to scaffold blueprints.\x1b[0m\n"
288
+ );
243
289
  process.exit(1);
244
290
  }
245
291
 
246
292
  let targetName = projectName;
247
293
  if (!targetName) {
248
294
  if (hasGum()) {
249
- targetName = gumInput('Project directory name:', 'my-quantum-app');
295
+ targetName = gumInput("Project directory name:", "my-quantum-app");
250
296
  } else {
251
- targetName = await promptQuestion('Project directory name [my-quantum-app]: ');
297
+ targetName = await promptQuestion("Project directory name [my-quantum-app]: ");
252
298
  }
253
299
  }
254
300
 
255
- const finalDirName = targetName.trim() || 'my-quantum-app';
301
+ const finalDirName = targetName.trim() || "my-quantum-app";
256
302
  const targetDir = path.resolve(process.cwd(), finalDirName);
257
303
 
258
304
  if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
259
- process.stderr.write(`\x1b[31m✕ Error: Directory '${finalDirName}' already exists and is not empty.\x1b[0m\n`);
305
+ process.stderr.write(
306
+ `\x1b[31m✕ Error: Directory '${finalDirName}' already exists and is not empty.\x1b[0m\n`
307
+ );
260
308
  process.exit(1);
261
309
  }
262
310
 
@@ -271,32 +319,34 @@ const runScaffold = async (projectName) => {
271
319
  if (!fs.existsSync(dirName)) {
272
320
  fs.mkdirSync(dirName, { recursive: true });
273
321
  }
274
- fs.writeFileSync(fullPath, content, 'utf-8');
322
+ fs.writeFileSync(fullPath, content, "utf-8");
275
323
  process.stdout.write(` \x1b[32m✔\x1b[0m ${relPath}\n`);
276
324
  }
277
325
 
278
- const cursorRulesPath = path.join(targetDir, '.cursorrules');
326
+ const cursorRulesPath = path.join(targetDir, ".cursorrules");
279
327
  if (!fs.existsSync(cursorRulesPath)) {
280
328
  const rules = `# Chemical X Quantum Architecture Directives\nStrictly follow AGENTS.md rules. Never exceed 500 lines per file. All molecule capsules must stay under 100 lines.\n`;
281
- fs.writeFileSync(cursorRulesPath, rules, 'utf-8');
329
+ fs.writeFileSync(cursorRulesPath, rules, "utf-8");
282
330
  process.stdout.write(` \x1b[32m✔\x1b[0m .cursorrules\n`);
283
331
  }
284
332
 
285
- process.stdout.write(`\n\x1b[1m\x1b[32m✔ Quantum project created successfully at ${finalDirName}!\x1b[0m\n\n`);
286
- process.stdout.write('Next Steps:\n');
333
+ process.stdout.write(
334
+ `\n\x1b[1m\x1b[32m✔ Quantum project created successfully at ${finalDirName}!\x1b[0m\n\n`
335
+ );
336
+ process.stdout.write("Next Steps:\n");
287
337
  process.stdout.write(` 1. cd ${finalDirName}\n`);
288
- process.stdout.write(' 2. Review AGENTS.md for line budgets and architecture standards\n');
289
- process.stdout.write(' 3. Run npx chemx generate m-<feature> to create capsules\n');
290
- process.stdout.write(' 4. Run npx chemx audit to scan for line budget compliance\n\n');
338
+ process.stdout.write(" 2. Review AGENTS.md for line budgets and architecture standards\n");
339
+ process.stdout.write(" 3. Run npx chemx generate m-<feature> to create capsules\n");
340
+ process.stdout.write(" 4. Run npx chemx audit to scan for line budget compliance\n\n");
291
341
  };
292
342
 
293
- const runInit = async (targetSubDir = 'src/chemical-x') => {
294
- renderBanner('Chemical X: In-Repo Capsule Drop-in');
343
+ const runInit = async (targetSubDir = "src/chemical-x") => {
344
+ renderBanner("Chemical X: In-Repo Capsule Drop-in");
295
345
 
296
346
  const targetDir = path.resolve(process.cwd(), targetSubDir);
297
347
  const licenseKey = await obtainLicenseKey();
298
348
  if (!licenseKey) {
299
- process.stderr.write('\x1b[31m✕ Valid license key is required.\x1b[0m\n');
349
+ process.stderr.write("\x1b[31m✕ Valid license key is required.\x1b[0m\n");
300
350
  process.exit(1);
301
351
  }
302
352
 
@@ -311,16 +361,18 @@ const runInit = async (targetSubDir = 'src/chemical-x') => {
311
361
  if (!fs.existsSync(dirName)) {
312
362
  fs.mkdirSync(dirName, { recursive: true });
313
363
  }
314
- fs.writeFileSync(fullPath, content, 'utf-8');
364
+ fs.writeFileSync(fullPath, content, "utf-8");
315
365
  process.stdout.write(` \x1b[32m✔\x1b[0m ${relPath}\n`);
316
366
  count++;
317
367
  }
318
368
 
319
- process.stdout.write(`\n\x1b[1m\x1b[32m✔ Successfully installed ${count} Chemical X assets into ${targetSubDir}!\x1b[0m\n\n`);
369
+ process.stdout.write(
370
+ `\n\x1b[1m\x1b[32m✔ Successfully installed ${count} Chemical X assets into ${targetSubDir}!\x1b[0m\n\n`
371
+ );
320
372
  };
321
373
 
322
374
  const runGenerateCapsule = (capsuleName) => {
323
- const normalizedName = capsuleName.startsWith('m-') ? capsuleName : `m-${capsuleName}`;
375
+ const normalizedName = capsuleName.startsWith("m-") ? capsuleName : `m-${capsuleName}`;
324
376
  const targetDir = path.resolve(process.cwd(), normalizedName);
325
377
 
326
378
  if (fs.existsSync(targetDir)) {
@@ -331,9 +383,9 @@ const runGenerateCapsule = (capsuleName) => {
331
383
  fs.mkdirSync(targetDir, { recursive: true });
332
384
 
333
385
  const pascalName = normalizedName
334
- .split('-')
386
+ .split("-")
335
387
  .map((p) => p.charAt(0).toUpperCase() + p.slice(1))
336
- .join('');
388
+ .join("");
337
389
 
338
390
  const componentCode = `import React from 'react';
339
391
  import type { ${pascalName}Props } from './types';
@@ -358,37 +410,46 @@ export default ${pascalName};
358
410
  export type { ${pascalName}Props } from './types';
359
411
  `;
360
412
 
361
- fs.writeFileSync(path.join(targetDir, `${normalizedName}.tsx`), componentCode, 'utf-8');
362
- fs.writeFileSync(path.join(targetDir, 'types.d.ts'), typesCode, 'utf-8');
363
- fs.writeFileSync(path.join(targetDir, 'index.ts'), indexCode, 'utf-8');
413
+ fs.writeFileSync(path.join(targetDir, `${normalizedName}.tsx`), componentCode, "utf-8");
414
+ fs.writeFileSync(path.join(targetDir, "types.d.ts"), typesCode, "utf-8");
415
+ fs.writeFileSync(path.join(targetDir, "index.ts"), indexCode, "utf-8");
364
416
 
365
- process.stdout.write(`\x1b[32m✔ Successfully generated crystalline capsule:\x1b[0m ${normalizedName}/\n`);
417
+ process.stdout.write(
418
+ `\x1b[32m✔ Successfully generated crystalline capsule:\x1b[0m ${normalizedName}/\n`
419
+ );
366
420
  process.stdout.write(` - ${normalizedName}/${normalizedName}.tsx (< 50 lines)\n`);
367
421
  process.stdout.write(` - ${normalizedName}/types.d.ts\n`);
368
422
  process.stdout.write(` - ${normalizedName}/index.ts\n\n`);
369
423
  };
370
424
 
371
425
  export const runAudit = async (customDir = null, isCli = false) => {
372
- const isJson = rawArgs.includes('--json');
373
- const dirFlag = rawArgs.find((arg) => arg.startsWith('--dir='));
374
- const targetDir = customDir || (dirFlag ? dirFlag.split('=')[1] : (fs.existsSync('src') ? 'src' : '.'));
426
+ const isJson = rawArgs.includes("--json");
427
+ const dirFlag = rawArgs.find((arg) => arg.startsWith("--dir="));
428
+ const targetDir =
429
+ customDir || (dirFlag ? dirFlag.split("=")[1] : fs.existsSync("src") ? "src" : ".");
375
430
 
376
431
  const report = executeAstAudit(targetDir);
377
432
 
378
433
  if (isJson) {
379
- process.stdout.write(JSON.stringify(report, null, 2) + '\n');
434
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
380
435
  if (isCli) process.exit(report.violations.length > 0 ? 1 : 0);
381
436
  return report;
382
437
  }
383
438
 
384
- process.stdout.write('\n\x1b[38;2;98;201;255m[Chemical X Context Hazard Audit]\x1b[0m Scanning codebase for AST architectural hazards...\n');
439
+ process.stdout.write(
440
+ "\n\x1b[38;2;98;201;255m[Chemical X Context Hazard Audit]\x1b[0m Scanning codebase for AST architectural hazards...\n"
441
+ );
385
442
  process.stdout.write(`Target Directory: ${targetDir}\n`);
386
443
  process.stdout.write(`Scanned ${report.scannedFiles} source files.\n\n`);
387
444
 
388
445
  if (report.violations.length === 0) {
389
- process.stdout.write('\x1b[1m\x1b[32m✔ 100% Quantum Compliant: Zero context hazard violations detected across all line budgets, hooks, and AST rules.\x1b[0m\n\n');
446
+ process.stdout.write(
447
+ "\x1b[1m\x1b[32m✔ 100% Quantum Compliant: Zero context hazard violations detected across all line budgets, hooks, and AST rules.\x1b[0m\n\n"
448
+ );
390
449
  } else {
391
- process.stdout.write(`\x1b[31m✕ FAILED: ${report.totalViolations} context hazard violations detected:\x1b[0m\n\n`);
450
+ process.stdout.write(
451
+ `\x1b[31m✕ FAILED: ${report.totalViolations} context hazard violations detected:\x1b[0m\n\n`
452
+ );
392
453
  for (const v of report.violations) {
393
454
  process.stdout.write(` \x1b[31m[${v.rule}]\x1b[0m \x1b[33m${v.filePath}:${v.line}\x1b[0m\n`);
394
455
  process.stdout.write(` Hazard: ${v.hazard}\n`);
@@ -399,56 +460,95 @@ export const runAudit = async (customDir = null, isCli = false) => {
399
460
  if (isCli) {
400
461
  while (true) {
401
462
  if (hasGum()) {
402
- spawnSync('gum', [
403
- 'style',
404
- '--border=rounded',
405
- '--border-foreground=81',
406
- '--padding=0 1',
407
- '--bold',
408
- 'Eliminate AI Context Rot with Chemical X Architecture'
409
- ], { stdio: 'inherit' });
410
-
411
- const choice = gumChoose([
412
- '1. Buy Standard Edition ($49) -> Launch Checkout',
413
- '2. Buy Master Bundle ($99) -> Launch Checkout',
414
- '3. Enter License Key to Scaffold (Paid License Holders)',
415
- '4. Exit'
416
- ], 'Select a CTA action:');
417
-
418
- if (choice.startsWith('1.')) {
419
- process.stdout.write(`\n\x1b[36mOpening Standard Edition checkout in browser:\x1b[0m ${URL_STANDARD}\n\n`);
463
+ spawnSync(
464
+ "gum",
465
+ [
466
+ "style",
467
+ "--border=rounded",
468
+ "--border-foreground=81",
469
+ "--padding=0 1",
470
+ "--bold",
471
+ "Chemical X: The Secret Sauce to Vibe Coding\nStop letting AI agents scour 2,000-line monoliths and hallucinate.\n25+ Years XP | Codified by Principal Systems Architect Xopher Pollard\nTarget File Budget: Max 500 lines/file (<100 lines/molecule) | 85% Token Burn Cut"
472
+ ],
473
+ { stdio: "inherit" }
474
+ );
475
+
476
+ const choice = gumChoose(
477
+ [
478
+ "1. Visit chemicalx.xophz.com to learn more",
479
+ "2. Buy eBook w/ AGENTS.md Rule Book ($27) -> Launch Checkout",
480
+ "3. Buy Master Bundle ($47) -> Launch Checkout",
481
+ "4. Enter License Key to Scaffold (Paid License Holders)",
482
+ "5. Exit"
483
+ ],
484
+ "Unlock the Awesome Secret Sauce of Chemical X:"
485
+ );
486
+
487
+ if (choice.startsWith("1.")) {
488
+ process.stdout.write(
489
+ `\n\x1b[36mOpening Chemical X Portal in browser:\x1b[0m ${URL_LEARN}\n\n`
490
+ );
491
+ openBrowser(URL_LEARN);
492
+ continue;
493
+ }
494
+ if (choice.startsWith("2.")) {
495
+ process.stdout.write(
496
+ `\n\x1b[36mOpening Standard Vault checkout (eBook + AGENTS.md):\x1b[0m ${URL_STANDARD}\n\n`
497
+ );
420
498
  openBrowser(URL_STANDARD);
421
499
  continue;
422
500
  }
423
- if (choice.startsWith('2.')) {
424
- process.stdout.write(`\n\x1b[36mOpening Master Bundle checkout in browser:\x1b[0m ${URL_MASTER}\n\n`);
501
+ if (choice.startsWith("3.")) {
502
+ process.stdout.write(
503
+ `\n\x1b[36mOpening Master Bundle checkout (Repo + Hooks + Prompts):\x1b[0m ${URL_MASTER}\n\n`
504
+ );
425
505
  openBrowser(URL_MASTER);
426
506
  continue;
427
507
  }
428
- if (choice.startsWith('3.')) {
508
+ if (choice.startsWith("4.")) {
429
509
  await runScaffold();
430
510
  break;
431
511
  }
432
512
  break;
433
513
  } else {
434
- process.stdout.write('\x1b[1m\x1b[38;2;98;201;255mEliminate AI Context Rot with Chemical X Architecture:\x1b[0m\n');
435
- process.stdout.write(` [1] Buy Standard Edition ($49) - ${URL_STANDARD}\n`);
436
- process.stdout.write(` [2] Buy Master Bundle ($99) - ${URL_MASTER}\n`);
437
- process.stdout.write(' [3] Enter License Key to Scaffold (Paid License Holders)\n');
438
- process.stdout.write(' [4] Exit\n\n');
439
-
440
- const selection = await promptQuestion('Select option [1-4]: ');
441
- if (selection === '1') {
514
+ process.stdout.write(
515
+ "\n\x1b[1m\x1b[38;2;98;201;255mChemical X: The Secret Sauce to Vibe Coding\x1b[0m\n"
516
+ );
517
+ process.stdout.write(
518
+ "Stop letting AI agents scour 2,000-line monoliths and hallucinate breaking changes.\n" +
519
+ "25+ Years XP | Codified by Principal Systems Architect Xopher Pollard\n" +
520
+ "Target File Budget: Max 500 lines/file (<100 lines per molecule capsule).\n\n"
521
+ );
522
+ process.stdout.write(` [1] Visit chemicalx.xophz.com to learn more\n`);
523
+ process.stdout.write(
524
+ ` [2] Buy eBook w/ AGENTS.md Rule Book ($27) - ${URL_STANDARD}\n` +
525
+ ` Includes: Kindle/Print PDF eBook, 7 Quantum Chapters, Universal AGENTS.md & .cursorrules\n`
526
+ );
527
+ process.stdout.write(
528
+ ` [3] Buy Master Bundle ($47) - ${URL_MASTER}\n` +
529
+ ` Includes: Private Starter-Kit Repo, Pre-Commit Line Budget Hooks, 10x Prompts, VIP Discord\n`
530
+ );
531
+ process.stdout.write(" [4] Enter License Key to Scaffold (Paid License Holders)\n");
532
+ process.stdout.write(" [5] Exit\n\n");
533
+
534
+ const selection = await promptQuestion("Select option [1-5] (default: 1): ");
535
+ const effectiveSelection = selection.trim() || "1";
536
+ if (effectiveSelection === "1") {
537
+ process.stdout.write(`\nOpening: ${URL_LEARN}\n\n`);
538
+ openBrowser(URL_LEARN);
539
+ continue;
540
+ }
541
+ if (effectiveSelection === "2") {
442
542
  process.stdout.write(`\nOpening: ${URL_STANDARD}\n\n`);
443
543
  openBrowser(URL_STANDARD);
444
544
  continue;
445
545
  }
446
- if (selection === '2') {
546
+ if (effectiveSelection === "3") {
447
547
  process.stdout.write(`\nOpening: ${URL_MASTER}\n\n`);
448
548
  openBrowser(URL_MASTER);
449
549
  continue;
450
550
  }
451
- if (selection === '3') {
551
+ if (effectiveSelection === "4") {
452
552
  await runScaffold();
453
553
  break;
454
554
  }
@@ -464,50 +564,60 @@ export { auditFile };
464
564
 
465
565
  const printHelp = () => {
466
566
  renderBanner();
467
- process.stdout.write('\x1b[1mAvailable Commands:\x1b[0m\n');
468
- process.stdout.write(' \x1b[36mnpm create chemx [dir]\x1b[0m [PAID] Scaffold complete Quantum Architecture project\n');
469
- process.stdout.write(' \x1b[36mnpx @chemx/starter-kit init [dir]\x1b[0m [PAID] Drop blueprints & hooks into existing project\n');
470
- process.stdout.write(' \x1b[36mnpx chemx generate <m-name>\x1b[0m Generate isolated molecule capsule (< 100 lines)\n');
471
- process.stdout.write(' \x1b[36mnpx chemx audit [--json] [--dir=src]\x1b[0m[FREE] Scan codebase for AST architectural hazards\n\n');
567
+ process.stdout.write("\x1b[1mAvailable Commands:\x1b[0m\n");
568
+ process.stdout.write(
569
+ " \x1b[36mnpm create chemx [dir]\x1b[0m [PAID] Scaffold complete Quantum Architecture project\n"
570
+ );
571
+ process.stdout.write(
572
+ " \x1b[36mnpx @chemx/starter-kit init [dir]\x1b[0m [PAID] Drop blueprints & hooks into existing project\n"
573
+ );
574
+ process.stdout.write(
575
+ " \x1b[36mnpx chemx generate <m-name>\x1b[0m Generate isolated molecule capsule (< 100 lines)\n"
576
+ );
577
+ process.stdout.write(
578
+ " \x1b[36mnpx chemx audit [--json] [--dir=src]\x1b[0m[FREE] Scan codebase for AST architectural hazards\n\n"
579
+ );
472
580
  };
473
581
 
474
582
  const main = async () => {
475
583
  const firstArg = rawArgs[0];
476
584
 
477
585
  if (isCreateInvoked) {
478
- const dirArg = firstArg === 'create' ? rawArgs[1] : firstArg;
586
+ const dirArg = firstArg === "create" ? rawArgs[1] : firstArg;
479
587
  await runScaffold(dirArg);
480
588
  return;
481
589
  }
482
590
 
483
591
  switch (firstArg) {
484
- case 'audit':
592
+ case "audit":
485
593
  await runAudit(null, true);
486
594
  break;
487
- case 'init':
488
- await runInit(rawArgs[1] || 'src/chemical-x');
595
+ case "init":
596
+ await runInit(rawArgs[1] || "src/chemical-x");
489
597
  break;
490
- case 'create':
598
+ case "create":
491
599
  await runScaffold(rawArgs[1]);
492
600
  break;
493
- case 'generate':
494
- case 'capsule':
495
- case 'add':
601
+ case "generate":
602
+ case "capsule":
603
+ case "add":
496
604
  if (!rawArgs[1]) {
497
- process.stderr.write('Usage: npx chemx generate <capsule-name>\nExample: npx chemx generate m-user-avatar\n');
605
+ process.stderr.write(
606
+ "Usage: npx chemx generate <capsule-name>\nExample: npx chemx generate m-user-avatar\n"
607
+ );
498
608
  process.exit(1);
499
609
  }
500
610
  runGenerateCapsule(rawArgs[1]);
501
611
  break;
502
- case 'help':
503
- case '--help':
504
- case '-h':
612
+ case "help":
613
+ case "--help":
614
+ case "-h":
505
615
  printHelp();
506
616
  break;
507
617
  default:
508
- if (firstArg && firstArg.startsWith('m-')) {
618
+ if (firstArg && firstArg.startsWith("m-")) {
509
619
  runGenerateCapsule(firstArg);
510
- } else if (firstArg && !firstArg.startsWith('-')) {
620
+ } else if (firstArg && !firstArg.startsWith("-")) {
511
621
  await runScaffold(firstArg);
512
622
  } else {
513
623
  printHelp();
@@ -520,4 +630,3 @@ main().catch((err) => {
520
630
  process.stderr.write(`\x1b[31m✕ Unexpected Error: ${err.message}\x1b[0m\n`);
521
631
  process.exit(1);
522
632
  });
523
-
package/docs/CHANGELOG.md CHANGED
@@ -37,7 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
37
37
  - Unlocked `npx chemx audit` command as 100% free, unauthenticated, and ungated public utility with conversion CTAs.
38
38
  - Added dual project scaffolder (`npm create chemx` / `create-chemx`) and in-repo capsule drop-in (`init`).
39
39
  - Gated `runScaffold` (`npm create chemx`) with upfront license validation prior to project directory name prompt.
40
- - Integrated interactive Gum CTA action buttons at the conclusion of public audit for instant checkout launch ($49 Standard / $99 Master) and key-gated scaffolding for license holders.
40
+ - Integrated interactive Gum CTA action buttons at the conclusion of public audit for default portal browsing (`chemicalx.xophz.com`), instant checkout launch ($27 eBook w/ AGENTS.md / $47 Master Bundle), and key-gated scaffolding for license holders.
41
41
 
42
42
  ### Fixed
43
43
  - Removed embedded offline blueprint fallbacks and preview bypass keys from CLI executable (`cli/index.js`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chemx/starter-kit",
3
- "version": "26.9.9-720",
3
+ "version": "26.9.9-786",
4
4
  "description": "Chemical X Protocol: Private drop-in architecture starter kit and capsule generator",
5
5
  "type": "module",
6
6
  "bin": {