@ijfw/install 1.2.9 → 1.3.0

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @ijfw/install
2
2
 
3
3
  One-command installer for [IJFW](https://gitlab.com/therealseandonahoe/ijfw) -- the AI
4
- efficiency layer for Claude Code, Codex, Gemini, Cursor, Windsurf, Copilot.
4
+ efficiency layer for 14 AI coding agents: Claude Code, Codex, Gemini, Cursor, Windsurf, Copilot, Hermes, Wayland, OpenCode, Qwen Code, Cline, Kimi Code, OpenClaw, and Aider.
5
5
 
6
6
  ## Install
7
7
 
@@ -39,8 +39,10 @@ Memory is preserved across re-runs by default.
39
39
 
40
40
  ## Preflight
41
41
 
42
- Requires `node >=18`, `git`, `bash`. On native Windows use the PowerShell
43
- installer (PS 5.1+), which shells Git Bash under the hood -- no WSL required:
42
+ Requires `node >=18` and `git` (used for the initial repo clone). The
43
+ installer is Node-native end to end -- no bash, no WSL, no Git for Windows
44
+ shell. On native Windows use the PowerShell installer (PS 5.1+), which
45
+ delegates to Node directly:
44
46
 
45
47
  ```powershell
46
48
  iwr https://gitlab.com/therealseandonahoe/ijfw/-/raw/main/installer/src/install.ps1 -OutFile install.ps1
package/dist/ijfw.js CHANGED
@@ -483,7 +483,7 @@ async function run5(ctx) {
483
483
  const res = spawnSync5(
484
484
  "npx",
485
485
  ["--yes", `publint@${ver}`, "--strict"],
486
- { encoding: "utf8", cwd: ctx.repoRoot + "/installer", timeout: 3e4 }
486
+ { encoding: "utf8", cwd: ctx.repoRoot + "/installer", timeout: 9e4 }
487
487
  );
488
488
  const durationMs = Date.now() - t0;
489
489
  const output = (res.stdout || "") + (res.stderr || "");
@@ -727,7 +727,7 @@ __export(pack_smoke_exports, {
727
727
  severity: () => severity10
728
728
  });
729
729
  import { spawnSync as spawnSync10 } from "node:child_process";
730
- import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, mkdirSync, writeFileSync as writeFileSync2, readdirSync as readdirSync3 } from "node:fs";
730
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, mkdirSync, writeFileSync as writeFileSync2, readdirSync as readdirSync3, existsSync } from "node:fs";
731
731
  import { join as join6, resolve } from "node:path";
732
732
  import { tmpdir as tmpdir2 } from "node:os";
733
733
  async function run10(ctx) {
@@ -803,13 +803,9 @@ async function run10(ctx) {
803
803
  ];
804
804
  let binPath = null;
805
805
  for (const c2 of binCandidates) {
806
- try {
807
- const r = spawnSync10("ls", [c2], { encoding: "utf8" });
808
- if (r.status === 0) {
809
- binPath = c2;
810
- break;
811
- }
812
- } catch {
806
+ if (existsSync(c2)) {
807
+ binPath = c2;
808
+ break;
813
809
  }
814
810
  }
815
811
  if (!binPath) {
@@ -883,7 +879,7 @@ __export(upgrade_smoke_exports, {
883
879
  severity: () => severity11
884
880
  });
885
881
  import { spawnSync as spawnSync11 } from "node:child_process";
886
- import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, readFileSync, existsSync } from "node:fs";
882
+ import { mkdtempSync as mkdtempSync3, rmSync as rmSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, readFileSync, existsSync as existsSync2 } from "node:fs";
887
883
  import { join as join7, resolve as resolve2 } from "node:path";
888
884
  import { tmpdir as tmpdir3 } from "node:os";
889
885
  async function run11(ctx) {
@@ -952,8 +948,7 @@ async function run11(ctx) {
952
948
  ];
953
949
  let installerBin = null;
954
950
  for (const c2 of binCandidates) {
955
- const check = spawnSync11("ls", [c2], { encoding: "utf8" });
956
- if (check.status === 0) {
951
+ if (existsSync2(c2)) {
957
952
  installerBin = c2;
958
953
  break;
959
954
  }
@@ -968,7 +963,7 @@ async function run11(ctx) {
968
963
  };
969
964
  }
970
965
  const settingsPath = join7(claudeDir, "settings.json");
971
- if (existsSync(settingsPath)) {
966
+ if (existsSync2(settingsPath)) {
972
967
  let settings;
973
968
  try {
974
969
  settings = JSON.parse(readFileSync(settingsPath, "utf8"));
@@ -993,7 +988,7 @@ async function run11(ctx) {
993
988
  }
994
989
  }
995
990
  const marketplaceSrc = join7(installerDir, "src", "marketplace.js");
996
- if (existsSync(marketplaceSrc)) {
991
+ if (existsSync2(marketplaceSrc)) {
997
992
  const src = readFileSync(marketplaceSrc, "utf8");
998
993
  const registersCorrectKey = src.includes("'ijfw@ijfw'") || src.includes('"ijfw@ijfw"');
999
994
  const registersWrongKey = /enabledPlugins\[['"]ijfw-core@ijfw['"]\]\s*=\s*true/.test(src);
@@ -1049,7 +1044,7 @@ var preflight_exports = {};
1049
1044
  __export(preflight_exports, {
1050
1045
  runPreflightCommand: () => runPreflightCommand
1051
1046
  });
1052
- import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
1047
+ import { readFileSync as readFileSync2, existsSync as existsSync3 } from "node:fs";
1053
1048
  import { join as join8, dirname } from "node:path";
1054
1049
  import { fileURLToPath } from "node:url";
1055
1050
  function printHelp() {
@@ -1091,7 +1086,7 @@ function loadVersions(repoRoot2) {
1091
1086
  join8(repoRoot2, ".ijfw", "preflight-versions.json")
1092
1087
  ];
1093
1088
  for (const f of candidates) {
1094
- if (existsSync2(f)) {
1089
+ if (existsSync3(f)) {
1095
1090
  try {
1096
1091
  return JSON.parse(readFileSync2(f, "utf8"));
1097
1092
  } catch {
@@ -2419,14 +2414,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
2419
2414
  // src/ijfw.js
2420
2415
  import { dirname as dirname2, join as join9, resolve as resolve3, basename } from "node:path";
2421
2416
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2422
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, copyFileSync, readdirSync as readdirSync4, rmSync as rmSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
2417
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, copyFileSync, readdirSync as readdirSync4, rmSync as rmSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
2423
2418
  import { homedir, platform as platform2 } from "node:os";
2424
2419
  import { spawnSync as spawnSync12 } from "node:child_process";
2425
2420
  var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
2426
2421
  function repoRoot() {
2427
2422
  let dir = __dirname2;
2428
2423
  for (let i = 0; i < 6; i++) {
2429
- if (existsSync3(join9(dir, "package.json")) && existsSync3(join9(dir, ".git"))) return dir;
2424
+ if (existsSync4(join9(dir, "package.json")) && existsSync4(join9(dir, ".git"))) return dir;
2430
2425
  dir = resolve3(dir, "..");
2431
2426
  }
2432
2427
  return process.cwd();
@@ -2442,7 +2437,7 @@ COMMANDS
2442
2437
  install Install IJFW into your AI coding agents
2443
2438
  uninstall Remove IJFW from your AI coding agents
2444
2439
  help Open the full IJFW guide (terminal, or --browser for rendered)
2445
- preflight Run 11-gate quality pipeline before publishing
2440
+ preflight Run 12-gate quality pipeline before publishing
2446
2441
  dashboard Start / stop / check the local observability dashboard
2447
2442
  design Manage the visual design companion
2448
2443
  doctor Diagnose IJFW installation health
@@ -2453,19 +2448,21 @@ COMMANDS
2453
2448
  }
2454
2449
  function doctorCheck(cmd, args) {
2455
2450
  const r = spawnSync12(cmd, args, { encoding: "utf8" });
2456
- return r.status === 0 ? r.stdout.split("\n")[0].trim() : "not found";
2451
+ if (r.status === 0) return r.stdout.split("\n")[0].trim();
2452
+ if (r.status === 127 || r.error && r.error.code === "ENOENT") return "not found";
2453
+ return `exit ${r.status} (may be transient)`;
2457
2454
  }
2458
2455
  function findCli() {
2459
2456
  const candidates = [
2460
2457
  join9(repoRoot(), "mcp-server", "src", "cross-orchestrator-cli.js"),
2461
2458
  join9(homedir(), ".ijfw", "mcp-server", "src", "cross-orchestrator-cli.js")
2462
2459
  ];
2463
- return candidates.find((p) => existsSync3(p)) || null;
2460
+ return candidates.find((p) => existsSync4(p)) || null;
2464
2461
  }
2465
2462
  function delegateToCli(argTail) {
2466
2463
  const cli = findCli();
2467
2464
  if (!cli) return false;
2468
- const r = spawnSync12("node", [cli, ...argTail], { stdio: "inherit" });
2465
+ const r = spawnSync12(process.execPath, [cli, ...argTail], { stdio: "inherit" });
2469
2466
  process.exit(r.status ?? 1);
2470
2467
  }
2471
2468
  async function main() {
@@ -2519,7 +2516,7 @@ async function main() {
2519
2516
  const ijfwHome = join9(homedir(), ".ijfw");
2520
2517
  const findInTree = (...rel) => {
2521
2518
  const candidates = [join9(root, ...rel), join9(ijfwHome, ...rel)];
2522
- return candidates.find((p) => existsSync3(p)) || null;
2519
+ return candidates.find((p) => existsSync4(p)) || null;
2523
2520
  };
2524
2521
  if (dashSub === "start" || dashSub === "stop" || dashSub === "status") {
2525
2522
  const dashBin = findInTree("mcp-server", "bin", "ijfw-dashboard");
@@ -2530,7 +2527,7 @@ async function main() {
2530
2527
  const serverJs = findInTree("mcp-server", "src", "dashboard-server.js");
2531
2528
  if (dashSub === "start" && serverJs) {
2532
2529
  const { spawn } = await import("node:child_process");
2533
- const child = spawn(process.execPath, [serverJs, "--daemon"], {
2530
+ const child = spawn(process.execPath, [serverJs, "start", "--daemon"], {
2534
2531
  detached: true,
2535
2532
  stdio: "ignore"
2536
2533
  });
@@ -2567,7 +2564,7 @@ async function main() {
2567
2564
  process.exit(1);
2568
2565
  }
2569
2566
  const abs = resolve3(filePath);
2570
- if (!existsSync3(abs)) {
2567
+ if (!existsSync4(abs)) {
2571
2568
  console.error(`File not found: ${abs}`);
2572
2569
  process.exit(1);
2573
2570
  }
@@ -2593,7 +2590,7 @@ async function main() {
2593
2590
  resolve3(__dirname2, "..", "docs", "GUIDE.md"),
2594
2591
  join9(homedir(), ".ijfw", "docs", "GUIDE.md")
2595
2592
  ];
2596
- const guidePath = candidates.find((p) => existsSync3(p));
2593
+ const guidePath = candidates.find((p) => existsSync4(p));
2597
2594
  if (!guidePath) {
2598
2595
  console.error("[ijfw] Guide not found. Run `ijfw install` to fetch the full guide, or visit https://gitlab.com/therealseandonahoe/ijfw/-/blob/main/docs/GUIDE.md");
2599
2596
  process.exit(1);
@@ -2603,7 +2600,7 @@ async function main() {
2603
2600
  const assetsSrc = join9(dirname2(guidePath), "guide", "assets");
2604
2601
  const outDir = join9(homedir(), ".ijfw", "guide");
2605
2602
  mkdirSync3(join9(outDir, "assets"), { recursive: true });
2606
- if (existsSync3(assetsSrc)) {
2603
+ if (existsSync4(assetsSrc)) {
2607
2604
  for (const f of readdirSync4(assetsSrc)) {
2608
2605
  copyFileSync(join9(assetsSrc, f), join9(outDir, "assets", f));
2609
2606
  }
@@ -2635,7 +2632,10 @@ async function main() {
2635
2632
  }
2636
2633
  const hasLess = spawnSync12("less", ["-V"], { stdio: "ignore" }).status === 0;
2637
2634
  if (hasLess) {
2638
- spawnSync12("less", ["-R", guidePath], { stdio: "inherit" });
2635
+ const lessRes = spawnSync12("less", ["-R", guidePath], { stdio: "inherit" });
2636
+ if (lessRes.status !== 0 && lessRes.status !== null) {
2637
+ process.stdout.write(readFileSync3(guidePath, "utf8"));
2638
+ }
2639
2639
  } else {
2640
2640
  process.stdout.write(readFileSync3(guidePath, "utf8"));
2641
2641
  }